Hi John -
Long time no chat, I know, and my apologies ;-( Of course, I have
been
on a different project than the gridded server, and working on MDSS
instead (that's a CO Dept of Transportation app). But the good
news is that
we are using Netcdf/Thredds/NCML and GeoGrids to display radar
and satellite data. Works beautifully ;-), except for the stride....
I hope you can help? I tried to narrow down my code sample that
doesnt work, as much as possible to help you debug if you choose
to accept this ;-) Here I go. This is a long email, but the
conclusion
is simple, i think (skip the the bottom if you like) ;-)
So, we're doing client side decimation/stride, in order to decrease
the amount of data sent across the wire, especially when zoomed
way out. I first create a GeoGrid for a URL and grid name, and
then subset it with a LatLon bounding box and a stride. For now,
I hardcode the y stride to 3, and the x stride to 1. Here's my code
with a description below...
---------------------------
final String fileUrl =
"http://www.rap.ucar.edu/projects/rdwx_mdss/thredds.php/dodsC/data/rawIR";
final String geoGridName = "IR";
GridDataset gridDataset = null;
try
{
gridDataset = GridDataset.open( fileUrl );
}
catch( IOException ex )
{
ex.printStackTrace( );
return;
}
// Only gets the desired grid for now
GeoGrid mainGeoGrid = gridDataset.findGridByName(
geoGridName );
LonLatRect rapLonLatRect = vo.getLLBBox();
LatLonPoint unidataLowerLeftPoint = new LatLonPointImpl(
rapLonLatRect.getMinLat(), rapLonLatRect.getMinLon() );
LatLonPoint unidataUpperRightPoint = new LatLonPointImpl(
rapLonLatRect.getMaxLat(), rapLonLatRect.getMaxLon() );
// For example, unidataLatLonRect.toString() returns "ll:
37.0N 109.0W+ ur: 41.0N 102.0W"
LatLonRect unidataLatLonRect = new LatLonRect(
unidataLowerLeftPoint, unidataUpperRightPoint );
final int xStride = 1;
final int yStride = 3;
GeoGrid stridedGeoGrid = mainGeoGrid.subset( null, null,
unidataLatLonRect, 1, yStride, xStride );
ProjectionImpl stridedProjection =
stridedGeoGrid.getProjection();
GridCoordSys stridedCoordSys = (GridCoordSys)
stridedGeoGrid.getCoordinateSystem();
CoordinateAxis1D stridedXAxis = (CoordinateAxis1D)
stridedCoordSys.getXHorizAxis();
if( ! stridedXAxis.isRegular() )
{
System.out.println( "X Axis is not regular. Panic." );
return;
}
CoordinateAxis1D stridedYAxis = (CoordinateAxis1D)
stridedCoordSys.getYHorizAxis();
if( ! stridedYAxis.isRegular() )
{
System.out.println( "Y Axis is not regular. Panic." );
return;
}
Array xValues = stridedXAxis.read();
Array yValues = stridedYAxis.read();
Index xAxisIndex = xValues.getIndex();
Index yAxisIndex = yValues.getIndex();
double xDelta = stridedXAxis.getIncrement();
double xHalfDelta = xDelta / 2.0;
double yDelta = stridedYAxis.getIncrement();
double yHalfDelta = yDelta / 2.0;
DateFormat dateFormatter = new SimpleDateFormat( "MM/dd/yyyy
HH:mm:ss zzz" );
Date dataTime = dateFormatter.parse( "02/16/2007 08:00:00
MST" );
Array dataValues = stridedGeoGrid.readYXData(
stridedCoordSys.findTimeIndexFromDate( dataTime ), -1 );
for( int y = 0; y < stridedYAxis.getSize(); y++ )
{
yAxisIndex.set( y );
double yValue = yValues.getDouble( yAxisIndex ); //
<-------------- Reference A -----------------
for( int x = 0; x < stridedXAxis.getSize(); x++ )
{
xAxisIndex.set( x );
double xValue = xValues.getDouble( xAxisIndex ); //
<-------------- Reference A ------------------
Color myColor = null;
Index someIndex = dataValues.getIndex();
someIndex.set( y, x ); // y * yStride, x * xStride );
// <---------------- Reference B -------------------
double dataValue = dataValues.getDouble( someIndex );
if( Double.isNaN( dataValue ) )
{
myColor = null;
}
else
{
// Get the color for the value.
myColor = colorScale.getColorForValue( dataValue );
}
if( myColor == null )
{
continue;
}
else
{
// Calc the lower left
LatLonPointImpl uniLatLonPoint =
stridedProjection.projToLatLon( xValue - xHalfDelta, yValue -
yHalfDelta );
temp2DDouble.setLocation(
uniLatLonPoint.getLongitude(), uniLatLonPoint.getLatitude() );
llsp = xformToUse.xform( temp2DDouble, llsp );
// Calc the lower right
uniLatLonPoint = stridedProjection.projToLatLon(
xValue + xHalfDelta, yValue - yHalfDelta );
temp2DDouble.setLocation(
uniLatLonPoint.getLongitude(), uniLatLonPoint.getLatitude() );
lrsp = xformToUse.xform( temp2DDouble, lrsp );
// Calc the upper left
uniLatLonPoint = stridedProjection.projToLatLon(
xValue - xHalfDelta, yValue + yHalfDelta );
temp2DDouble.setLocation(
uniLatLonPoint.getLongitude(), uniLatLonPoint.getLatitude() );
ulsp = xformToUse.xform( temp2DDouble, ulsp );
// Calc the upper right
uniLatLonPoint = stridedProjection.projToLatLon(
xValue + xHalfDelta, yValue + yHalfDelta );
temp2DDouble.setLocation(
uniLatLonPoint.getLongitude(), uniLatLonPoint.getLatitude() );
ursp = xformToUse.xform( temp2DDouble, ursp );
Polygon polyToRender = new Polygon();
polyToRender.addPoint( (int) ( llsp.x + 0.5 ), (int) (
llsp.y + 0.5 ) );
polyToRender.addPoint( (int) ( ulsp.x + 0.5 ), (int) (
ulsp.y + 0.5 ) );
polyToRender.addPoint( (int) ( ursp.x + 0.5 ), (int) (
ursp.y + 0.5 ) );
polyToRender.addPoint( (int) ( lrsp.x + 0.5 ), (int) (
lrsp.y + 0.5 ) );
if( ! ( polyToRender.intersects( screenRect ) ) )
continue;
g2d.setColor( myColor );
g2d.drawPolygon( polyToRender );
}
}
}
-----------------------------
Now Im not sure if I am using the resulting strided GeoGrid
correctly.
But, from the strided GeoGrid, I use it's x and y axis values
(lat/lons)
for (Jade) projections and for determining the screen locations of
each data cell.
That's 'Reference A' labelled above. It seems to me that this is
correct -
those lat/lon values span the entire grid, as expected.
The problem, i think, is that the data values are not correct. I
think the
subsetted/strided data looks like (Figure 1 ;-):
Strided data Original data
------------------------------------------
Row 0 --------> original row 0 (good, for yStride = 3)
Row 1 --------> empty (bad)
Row 2 --------> empty (bad)
Row 3 --------> original row 3 (good, for yStride = 3)
Row 4 --------> empty (bad)
Row 5 --------> empty (bad)
Row 6 --------> original row 6 (good, for yStride = 3)
Row 7 --------> empty (bad)
Row 8 --------> empty (bad)
Row 9 --------> original row 9 (good, for yStride = 3)
....
At Reference B in the code, using someIndex.set( y, x ), will
plot the values as in Figure 1 - I will have empty rows going
across my screen = bad.
On the other hand, at Reference B in the code, using
someIndex.set( y * yStride, x * xStride ) will plot the
upper third of the data correctly, and then throw exceptions
when the index goes out of bounds. So the data remains
as in Figure 1, but it will be plotted like so until y gets
bigger than the data (1/3 down the map):
Strided data Original data
------------------------------------------
Row 0 --------> original row 0 (good, for yStride = 3)
Row 1 --------> original row 3 (good, for yStride = 3)
Row 2 --------> original row 6 (good, for yStride = 3)
Row 3 --------> original row 9 (good, for yStride = 3)
....
throw....
Conclusion: I think the data needs to look like:
Strided data Original data
------------------------------------------
Row 0 --------> original row 0 (good, for yStride = 3)
Row 1 --------> original row 3 (good, for yStride = 3)
Row 2 --------> original row 6 (good, for yStride = 3)
Row 3 --------> original row 9 (good, for yStride = 3)
Row 4 --------> original row 12 (good, for yStride = 3)
Row 5 --------> original row 15 (good, for yStride = 3)
Row 6 --------> original row 18 (good, for yStride = 3)
....
all the way down to stridedGeoGrid.getYAxis().getSize() effectively.
ie: The data needs to be packed, rather than sparse.
;-) Whew. I tried to be as concise as possible. What do you think?
Can you help me????
;-) Hope all is well over there....