How can I create an image of satellite pixel using 4 latitude/longitude corner points instead of a 1 center lat/long coordinate
barbara.dix
Hello,
I want to plot native swath satellite data without regridding it to a linear lat/long grid. Each ground pixel comes with its own set of 4 lat/long corner points describing its surface footprint. The grid that is created by these footprints has no gaps, but it is non linear and the pixel have different sizes. I would like to plot this as an image and fill each 4 sided polygon created by the corner points with color according to a color code based on the value for this pixel.
Any help appreciated, Thanks
If the satellite data is just non-linearly gridded, you can supply those coordinates to an Igor image plot using auxillary X and Y waves.
For more info, enter the following on Igor's command line:
DisplayHelpTopic "Image X and Y Coordinates - Unevenly Spaced"
November 18, 2019 at 03:35 pm - Permalink
Hello,
Thank you for this reply, which made me realize I was not sufficiently clear in my description. The pixel are are not rectangles, but something more like not fully linear parallelograms that change size across the image (field of view). In short, I would need to be able to supply individual x and y scalings for each row and column of the image matrix. I am attaching an image to illustrate what I would like to plot. The example image I have available is from the center of the satellite's field of view, where the pixel almost all have the same size, but across the whole image each image has a different size that is only determined by its corner latitude/longitude points. Perhaps wanting to plot it as as image is not the right approach?
Thanks and Best, Barbara
November 19, 2019 at 08:32 am - Permalink
You should probably use the Drawing Tools to create this, then. It might not render very quickly, though, and the recreation macro would be huge. Still, it should work. If the drawing tools are new to you, start with this help topic:
DisplayHelpTopic "Drawing"
The useful thing about drawing tools is that you can write code to create the drawings, and you can use the graph coordinate system to place lines, rectangles and polygons.
You can set the color of the poly before you draw it, too.
I imagine code that loops through your loaded data and executes SetDrawEnv fillRGB commands to set the color and then DrawPoly commands.
Like this:
String win="DemoPolyDrawingGraph"
DoWindow/K $win
Display/N=$win /W=(35,45,430,253)
NewFreeAxis/O/L freeLeft
NewFreeAxis/O/B freeBottom
ModifyGraph freePos(freeLeft)=0
ModifyGraph freePos(freeBottom)=0
// axis range
Variable xmin=10, xmax=60
Variable ymin=20, ymax=35
SetAxis freeBottom xmin,xmax+10
SetAxis freeLeft ymin,ymax
SetDrawEnv xcoord=freeBottom, ycoord=freeLeft, fillpat=1, save // 100% fill
ColorTab2Wave Rainbow // creates M_Colors
WAVE M_Colors // needed to refer to M_Colors
Variable i, nColors = DimSize(M_Colors,0)
// generate a bunch of closed polys with 4 corners (5 points), and sequential colors from Rainbow
Variable dx= 5, dy=1, xskew=1, yskew=0.2
Variable xrange = (xmax-xmin)
Variable yrange = (ymax-xmin) - dy
for(i=0; i<nColors; i+=1)
Variable xOffset = mod(i*dx,xrange)
Variable xRow = floor(i*dx/xrange)
Variable x0 = xmin + xOffset + xRow * xSkew
Variable x1 = x0 + dx
Variable x2 = x1 + xSkew
Variable x3 = x0 + xSkew
Variable y0 = ymin + xRow*(dy+ySkew)
Variable y1 = y0 + ySkew
Variable y2 = y1 + dy
Variable y3 = y0 + dy
Variable red= M_Colors[i][0]
Variable green= M_Colors[i][1]
Variable blue= M_Colors[i][2]
SetDrawEnv fillfgc=(red,green,blue)
DrawPoly x0, y0, 1, 1, {x0,y0, x1,y1, x2,y2, x3,y3, x0,y0}
endfor
End
November 19, 2019 at 04:22 pm - Permalink
Thank you very much, this is extremely helpful. I will check it out and if the rendering is too time consuming I will at least have it available for select cases.
Much appreciated, Cheers and Best,
Barbara
November 20, 2019 at 03:18 pm - Permalink
I think that there is another approach that may or may not have coding or rendering advantages. It is a little complicated, but not much more than programming the drawing tools. The suggestion is to use Gizmo, and construct a Group using quad objects for the irregular pixels. All quads would have the same fixed z-coordinate, each with its own four x,y vertex values. To get started
DisplayHelpTopic "Group Objects"
To give a flavor of a coding example, here is how I altered the color of one quad, in a two-quad group, setting it to green:
ModifyGizmo modifyObject=quad0, objectType=quad, property={colorValue,0, 0,1,0,1}
ModifyGizmo currentGroupObject="::"
You could use 2 Nx4 waves to hold all your vertex 'x' and 'y' values for each pixel ('z' is an arbitrary constant for the plane), and write a loop to construct each set of quad coordinates in the group. Coloring each quad would proceed as shown above, using an Nx4 wave of your color values (R,G,B,alpha) for each pixel (quad). Here is the recreation macro for my test Gizmo with two quads; converting to a loop structure over pixels should not be too difficult.
PauseUpdate; Silent 1 // building window...
// Building Gizmo 8 window...
NewGizmo/W=(26.25,50,412.5,395)
ModifyGizmo startRecMacro=700
ModifyGizmo scalingOption=63
AppendToGizmo Axes=boxAxes,name=axes0
ModifyGizmo ModifyObject=axes0,objectType=Axes,property={-1,axisScalingMode,1}
ModifyGizmo ModifyObject=axes0,objectType=Axes,property={-1,axisColor,0,0,0,1}
ModifyGizmo ModifyObject=axes0,objectType=Axes,property={0,ticks,3}
ModifyGizmo ModifyObject=axes0,objectType=Axes,property={1,ticks,3}
ModifyGizmo ModifyObject=axes0,objectType=Axes,property={2,ticks,3}
ModifyGizmo modifyObject=axes0,objectType=Axes,property={-1,Clipped,0}
AppendToGizmo group,name=group0
// ************************* Group Object Start *******************
ModifyGizmo currentGroupObject="group0"
AppendToGizmo quad={-0.25,-0.25,0,0,-0.25,0,0,0,0,-0.25,0,0},name=quad0
ModifyGizmo ModifyObject=quad0,objectType=quad,property={ colorType,1}
ModifyGizmo ModifyObject=quad0,objectType=quad,property={ colorValue,0,0,1,0,1}
AppendToGizmo quad={0,0,0,0.25,0,0,0.25,0.25,0,0,0.25,0},name=quad1
ModifyGizmo ModifyObject=quad1,objectType=quad,property={ colorType,1}
ModifyGizmo ModifyObject=quad1,objectType=quad,property={ colorValue,0,1.5259e-05,0.244434,1,1}
ModifyGizmo setDisplayList=0, object=quad0
ModifyGizmo setDisplayList=1, object=quad1
ModifyGizmo currentGroupObject="::"
// ************************* Group Object End *******************
AppendToGizmo freeAxesCue={0,0,0,1},name=freeAxesCue0
ModifyGizmo setDisplayList=0, object=axes0
ModifyGizmo setDisplayList=1, object=group0
ModifyGizmo setDisplayList=2, object=freeAxesCue0
ModifyGizmo autoscaling=1
ModifyGizmo currentGroupObject=""
ModifyGizmo showInfo
ModifyGizmo infoWindow={610,68,1226,366}
ModifyGizmo endRecMacro
ModifyGizmo idleEventQuaternion={8.1789e-07,5.63137e-07,6.43585e-07,1}
EndMacro
(Edit: Macro transcription error corrected)
November 21, 2019 at 06:35 am - Permalink
Here is a Gizmo comparison to Jim's previous graph. In practice the user supplies the wNx and wNy vertex values and color scale values, which I have concocted. Prior to executing the function below I opened a Gizmo window with initial box axes, translate, and scale operations. to simplify the example, I also opted not to use a group of quads
string Quadstring // varying quad label
WAVE wNx, wNy, wcolor // (35,4) x and y vertex values; (35,3) colorscale values based on Rainbow, indexed by pixel number
variable i
for(i=0;i<35;i+=1)
Quadstring= "quad"+num2str(i)
AppendToGizmo quad={wNx[i][0],wNy[i][0],0, wNx[i][1],wNy[i][1],0, wNx[i][2],wNy[i][2],0, wNx[i][3],wNy[i][3],0},name=$QuadString
ModifyGizmo ModifyObject=$QuadString,objectType=quad,property={ colorType,1}
ModifyGizmo ModifyObject=$QuadString,objectType=quad,property={ colorValue,0, wcolor[i][0],wcolor[i][1],wcolor[i][2], 1}
ModifyGizmo setDisplayList=i+3, object=$QuadString
endfor
end
The attached figure shows a vertical (home) view of the gap-less pixels' surface in the z=0 plane
November 26, 2019 at 06:42 am - Permalink
After helpful discussions with AG, my current opinion is that a Gizmo Surface plot using sequential quads for the source wave is the easiest way to go.
DisplayHelpTopic "Surface Object Data Formats"
All you have to do is put your data into the specified source wave format. Here is a code snippet for one kind of conversion:
wave wX, wY, wZ // vertex coordinate values [numquads, 4 vertices];
// one coordinate has four identical vertex values, representing measured datum
// the other two coordinates have different vertex values for lat/long corners
variable npts = dimsize(wX,0) // number of quads
make/O/N=((npts),4,3) wSeqQuad // (quads, vertices, coordinate values)
wSeqQuad[][][0]=wX[p][q] // Gizmo surface and axes and are added and modified from GUIs
wSeqQuad[][][1]=wY[p][q]
wSeqQuad[][][2]=wZ[p][q]
End
I am attaching a picture of a Gizmo projected view using simulated vertices (the color wave shows the data values along the projection axes, taken from one coordinate of vertex data). There are only two Gizmo objects involved, axes and surface plot.
December 26, 2019 at 06:21 am - Permalink