Hi Jason:
Ok, I was able to finish the projection stuff based on what you told me.
Attached is the new code. Note that you will need to use it with nj22
version 2.2.08 (just released) and IDV 1.2. You'll have to get both
packages and merge them together. Probably a source build is the easiest
way to do it. It may also work to get the new netcdf-2.2.jar and put it
on your class path before nc2.2.jar.
If you are able to change the file format, I would recommend that you do
that. If interested, I can send you some suggestions.
regards,
John.
// $Id: IFPSConvention.java,v 1.1 2005/03/15 23:24:11 caron Exp $
/*
* Copyright 1997-2000 Unidata Program Center/University Corporation for
* Atmospheric Research, P.O. Box 3000, Boulder, CO 80307,
* support@xxxxxxxxxxxxxxxx.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package ucar.nc2.dataset.conv;
import ucar.ma2.*;
import ucar.nc2.*;
import ucar.nc2.dataset.*;
import ucar.nc2.util.CancelTask;
import ucar.unidata.geoloc.projection.LambertConformal;
import ucar.unidata.geoloc.ProjectionPointImpl;
import ucar.unidata.geoloc.LatLonPointImpl;
import ucar.unidata.geoloc.Projection;
import java.io.IOException;
import java.util.*;
/**
* IFPS Convention Allows Local NWS forecast office generated forecast datasets
to be brought into IDV.
* @author Burks
* @version $Revision: 1.1 $ $Date: 2005/03/15 23:24:11 $
*/
public class IFPSConvention extends CoordSysBuilder {
/** return true if we think this is a IFPS file. */
public static boolean isMine( NetcdfFile ncfile) {
// not really sure until we can examine more files
//need to check more to see if DIM_0 is always in there
return null != ncfile.findDimension("DIM_0");
}
private Variable projVar = null; // use this to get projection info
protected void augmentDataset( NetcdfDataset ds, CancelTask cancelTask) {
this.conventionName = "IFPS";
parseInfo.append("IFPS augmentDataset \n");
// Figure out projection info. Assume the same for all variables
Variable lonVar = ds.findVariable("longitude");
lonVar.addAttribute( new Attribute("units", "degrees_east"));
lonVar.addAttribute( new Attribute("_CoordinateAxisType", "Lon"));
Variable latVar = ds.findVariable("latitude");
latVar.addAttribute( new Attribute("_CoordinateAxisType", "Lat"));
latVar.addAttribute( new Attribute("units", "degrees_north"));
projVar = latVar;
String projName = ds.findAttValueIgnoreCase(projVar, "projectionType",
null);
if (projName.equals("LAMBERT_CONFORMAL")) {
Projection proj = makeLCProjection( ds);
try {
makeXYcoords( ds, proj, latVar, lonVar);
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File |
Settings | File Templates.
}
}
// figure out the time coordinate for each data variable
// LOOK : always seperate; could try to discover if they are the same
Iterator vars = ds.getVariables().iterator();
while (vars.hasNext()) {
VariableDS ncvar = (VariableDS) vars.next();
//variables that are used but not displayable or have no data have
DIM_0, also don't want history, since those are just how the person edited the
grids
if ((ncvar.getDimension(0).getName().equals("DIM_0") != true) &&
(ncvar.getName().endsWith("History")== false)
&& (ncvar.getRank() > 2)&& (ncvar.getName().startsWith("Tool")==
false)){
createTimeCoordinate(ds,ncvar);
} else if (ncvar.getName().equals("Topo")){
//Deal with Topography variable
ncvar.addAttribute(new Attribute("long_name", "Topography"));
ncvar.addAttribute(new Attribute("units", "ft"));
}
}
ds.finish();
}
private void createTimeCoordinate(NetcdfDataset ds,VariableDS ncVar){
//Time coordinate is stored in the attribute validTimes
//One caveat is that the times have two bounds and upper and a lower
// get the times values
Attribute timesAtt = ncVar.findAttribute("validTimes");
if (timesAtt == null) return;
Array timesArray = timesAtt.getValues();
// get every other one LOOK this is awkward
try {
int n = (int) timesArray.getSize();
ArrayList list = new ArrayList();
list.add(new Range(0, n-1, 2));
timesArray = timesArray.section(list);
} catch (InvalidRangeException e) {
e.printStackTrace(); //To change body of catch statement use File |
Settings | File Templates.
}
// make sure it matches the dimension
DataType dtype = DataType.getType( timesArray.getElementType());
int nTimesAtt = (int) timesArray.getSize();
// create a special dimension and coordinate variable
Dimension dimTime = ncVar.getDimension(0);
int nTimesDim = dimTime.getLength();
if (nTimesDim != nTimesAtt) {
parseInfo.append(" **error ntimes in attribute ("+nTimesAtt+") doesnt
match dimension length ("+
nTimesDim+") for variable "+ ncVar.getName()+"\n");
return;
}
// add the dimension
String dimName = ncVar.getName()+"_timeCoord";
Dimension newDim = new Dimension(dimName, nTimesDim, true);
ds.addDimension( null, newDim);
// add the coordinate variable
String units = "seconds since 1970-1-1 00:00:00";
String desc = "time coordinate for "+ncVar.getName();
CoordinateAxis1D timeCoord = new CoordinateAxis1D( ds, null, dimName,
dtype, dimName, units, desc);
timeCoord.setCachedData(timesArray, true);
timeCoord.addAttribute(new Attribute("long_name", desc));
timeCoord.addAttribute(new Attribute("units", units));
timeCoord.addAttribute(new Attribute("_CoordinateAxisType", "Time"));
ds.addCoordinateAxis(timeCoord);
parseInfo.append(" added coordinate variable "+ dimName+"\n");
// now make the original variable use the new dimension
List dimsList = ncVar.getDimensions();
dimsList.set(0, newDim);
ncVar.setDimensions( dimsList);
// better to explicitly set the coordinate system
ncVar.addAttribute(new Attribute("_CoordinateAxes", dimName+" yCoord
xCoord"));
// fix the attributes
Attribute att = ncVar.findAttribute("fillValue");
if (att != null)
ncVar.addAttribute(new Attribute("_FillValue", att.getNumericValue()));
att = ncVar.findAttribute("descriptiveName");
if (null != att)
ncVar.addAttribute(new Attribute("long_name", att.getStringValue()));
ncVar.enhance();
}
protected String getZisPositive( NetcdfDataset ds, CoordinateAxis v) {
return "up";
}
private Projection makeLCProjection(NetcdfDataset ds) {
Attribute latLonOrigin = projVar.findAttributeIgnoreCase("latLonOrigin");
double centralLon = latLonOrigin.getNumericValue(0).doubleValue();
double centralLat = latLonOrigin.getNumericValue(1).doubleValue();
double par1 = findAttributeDouble( "stdParallelOne");
double par2 = findAttributeDouble( "stdParallelTwo");
LambertConformal lc = new LambertConformal(centralLat, centralLon, par1,
par2);
// make Coordinate Transform Variable
ProjectionCT ct = new ProjectionCT("lambertConformalProjection", "FGDC",
lc);
VariableDS ctVar = makeCoordinateTransformVariable(ds, ct);
ctVar.addAttribute( new Attribute("_CoordinateAxes", "xCoord yCoord"));
ds.addVariable(null, ctVar);
return lc;
}
private void makeXYcoords(NetcdfDataset ds, Projection proj, Variable latVar,
Variable lonVar) throws IOException {
// brute force
Array latData = latVar.read();
Array lonData = lonVar.read();
Dimension y_dim = latVar.getDimension(0);
Dimension x_dim = latVar.getDimension(1);
Array xData = Array.factory( float.class, new int[] {x_dim.getLength()});
Array yData = Array.factory( float.class, new int[] {y_dim.getLength()});
LatLonPointImpl latlon = new LatLonPointImpl();
ProjectionPointImpl pp = new ProjectionPointImpl();
Index latlonIndex = latData.getIndex();
Index xIndex = xData.getIndex();
Index yIndex = yData.getIndex();
// construct x coord
for (int i=0; i<x_dim.getLength(); i++) {
double lat = latData.getDouble( latlonIndex.set1(i));
double lon = lonData.getDouble( latlonIndex);
latlon.set( lat, lon);
proj.latLonToProj( latlon, pp);
xData.setDouble( xIndex.set(i), pp.getX());
}
// construct y coord
for (int i=0; i<y_dim.getLength(); i++) {
double lat = latData.getDouble( latlonIndex.set0(i));
double lon = lonData.getDouble( latlonIndex);
latlon.set( lat, lon);
proj.latLonToProj( latlon, pp);
yData.setDouble( yIndex.set(i), pp.getY());
}
VariableDS xaxis = new VariableDS(ds, null, null, "xCoord", DataType.FLOAT,
x_dim.getName(), "km", "x on projection");
xaxis.addAttribute(new Attribute("units", "km"));
xaxis.addAttribute(new Attribute("long_name", "x on projection"));
xaxis.addAttribute(new Attribute("_CoordinateAxisType", "GeoX"));
VariableDS yaxis = new VariableDS(ds, null, null, "yCoord", DataType.FLOAT,
y_dim.getName(), "km", "y on projection");
yaxis.addAttribute(new Attribute("units", "km"));
yaxis.addAttribute(new Attribute("long_name", "y on projection"));
yaxis.addAttribute(new Attribute("_CoordinateAxisType", "GeoY"));
xaxis.setCachedData( xData, true);
yaxis.setCachedData( yData, true);
ds.addVariable( null, xaxis);
ds.addVariable( null, yaxis);
}
private double findAttributeDouble(String attname) {
Attribute att = projVar.findAttributeIgnoreCase(attname);
return att.getNumericValue().doubleValue();
}
}