taxis.setDimensions("time");
taxis.addAttribute( new Attribute("long_name", "time since base date"));
taxis.addAttribute( new Attribute(_Coordinate.AxisType, AxisType.Time.toString()));
double [] tdata = new double[1];
tdata[0] = cal.getTimeInMillis();
Array dataA = Array.factory(DataType.DOUBLE.getPrimitiveClassType(), new int[] {1}, tdata);
taxis.setCachedData( dataA, false);
DateFormatter formatter = new DateFormatter();
taxis.addAttribute( new Attribute("units", "msecs since "+formatter.toDateTimeStringISO(new Date(0))));
ncfile.addVariable(null, taxis);
//att = new Attribute( "Time", dstring);
//this.ncfile.addAttribute(null, att);
this.ncfile.addAttribute(null, new Attribute("time_coverage_start", dstring));
this.ncfile.addAttribute(null, new Attribute("time_coverage_end", dstring));
bos.get(); /* skip a byte for hundreds of seconds */
nv = new Byte ( bos.get());
att = new Attribute( "ProjIndex", nv);
this.ncfile.addAttribute(null, att);
proj = nv.intValue();
if( proj == 1) {
att = new Attribute( "ProjName", "MERCATOR");
} else if (proj == 3) {
att = new Attribute( "ProjName", "LAMBERT_CONFORNAL");
} else if (proj == 5) {
att = new Attribute( "ProjName", "POLARSTEREOGRAPHIC");
}
this.ncfile.addAttribute(null, att);
/*
** Get grid dimensions
*/
byte[] b3 = new byte[3];
bos.get(b2, 0, 2);
nx = getInt( b2, 2);
Integer ni = new Integer(nx);
att = new Attribute( "NX", ni);
this.ncfile.addAttribute(null, att);
bos.get(b2, 0, 2);
ny = getInt( b2, 2);
ni = new Integer(ny);
att = new Attribute( "NY", ni);
this.ncfile.addAttribute(null, att);
ProjectionImpl projection = null;
double dxKm = 0.0, dyKm = 0.0, latin, lonProjectionOrigin ;
switch( proj ) {
case 1: /* Mercator */
/*
** Get the latitude and longitude of first and last "grid" points
*/
/* Latitude of first grid point */
bos.get(b3, 0, 3);
int nn = getInt( b3, 3);
lat1 = (double) nn / 10000.0;
Double nd = new Double(lat1);
att = new Attribute( "Latitude0", nd);
this.ncfile.addAttribute(null, att);
bos.get(b3, 0, 3);
nn = getInt( b3, 3);
int b33 = (int)(b3[0] & (1<< 7));
// if( b33 == 128) //west longitude
// nd = new Double(((double) nn) / 10000.0 * (-1));
// else
nd = new Double(((double) nn) / 10000.0 );
lon1 = nd.doubleValue();
att = new Attribute( "Longitude0", nd);
this.ncfile.addAttribute(null, att);
/* Longitude of last grid point */
bos.get(); /* skip one byte */
bos.get(b3, 0, 3);
nn = getInt( b3, 3);
nd = new Double( ((double) nn) / 10000.0);
lat2 = nd.doubleValue();
att = new Attribute( "LatitudeN", nd);
this.ncfile.addAttribute(null, att);
bos.get(b3, 0, 3);
nn = getInt( b3, 3);
b33 = (int)(b3[0] & (1<< 7));
// if( b33 == 128) //west longitude
// nd = new Double(((double) nn) / 10000.0 * (-1));
// else
nd = new Double(((double) nn) / 10000.0 );
lon2 = nd.doubleValue();
att = new Attribute( "LongitudeN", nd);
this.ncfile.addAttribute(null, att);
/*
** Hack to catch incorrect sign of lon2 in header.
*/
// if ( lon1 > 0.0 && lon2 < 0.0 ) lon2 *= -1;
double lon_1 = lon1;
double lon_2 = lon2;
if ( lon1 < 0 ) lon_1 += 360.0;
if ( lon2 < 0 ) lon_2 += 360.0;
lonv = lon_1 - (lon_1 - lon_2) / 2.0;
if ( lonv > 180.0 ) lonv -= 360.0;
if ( lonv < -180.0 ) lonv += 360.0;
/*
** Get the "Latin" parameter. The ICD describes this value as:
** "Latin - The latitude(s) at which the Mercator projection cylinder
** intersects the earth." It should read that this is the latitude
** at which the image resolution is that defined by octet 41.
*/
bos.getInt(); /* skip 4 bytes */
bos.get(); /* skip 1 byte */
bos.get(b3, 0, 3);
nn = getInt( b3, 3);
nd = new Double(((double) nn) / 10000.0);
/* Latitude of proj cylinder intersects */
att = new Attribute( "LatitudeX", nd);
latin = nd.doubleValue();
this.ncfile.addAttribute(null, att);
latt = 0.0; // this is not corrected // jc 8/7/08 not used
// dyKm = Math.cos( DEG_TO_RAD*latt);
// dxKm = DEG_TO_RAD * EARTH_RAD_KMETERS * Math.abs((lon_1-lon_2) / (nx-1));
// double dy = EARTH_RAD_KMETERS * Math.cos(DEG_TO_RAD*latt) / (ny - 1);
// dyKm = dy *( Math.log( Math.tan(DEG_TO_RAD*( (lat2-latt)/2.0 + 45.0 ) ) )
// -Math.log( Math.tan(DEG_TO_RAD*( (lat1-latt)/2.0 + 45.0 ) ) ) );
// dxKm = DEG_TO_RAD * EARTH_RAD_KMETERS * Math.abs(lon1-lon2) / (ny-1);
projection = new Mercator( lonv, latin) ;
break;
case 3: /* Lambert Conformal */
case 5: /* Polar Stereographic */
/*
** Get lat/lon of first grid point
*/
bos.get(b3, 0, 3);
nn = getInt( b3, 3);
nd = new Double(((double) nn) / 10000.0);
lat1 = nd.doubleValue();
//att = new Attribute( "Lat1", nd);
//this.ncfile.addAttribute(null, att);
bos.get(b3, 0, 3);
nn = getInt( b3, 3);
nd = new Double(((double) nn) / 10000.0);
lon1 = nd.doubleValue();
/*
** Get Lov - the orientation of the grid; i.e. the east longitude of
** the meridian which is parallel to the y-aixs
*/
bos.get(); /* skip one byte */
bos.get(b3, 0, 3);
nn = getInt( b3, 3);
nd = new Double(((double) nn) / 10000.0);
lonv = nd.doubleValue();
lonProjectionOrigin = lonv;
att = new Attribute( "Lov", nd);
this.ncfile.addAttribute(null, att);
/*
** Get distance increment of grid
*/
bos.get(b3, 0, 3);
nn = getInt( b3, 3);
dxKm = ((double) nn) / 10000.0;
nd = new Double(((double) nn) / 10000.);
att = new Attribute( "DxKm", nd);
this.ncfile.addAttribute(null, att);
bos.get(b3, 0, 3);
nn = getInt( b3, 3);
dyKm = ((double) nn) / 10000.0;
nd = new Double( ((double) nn) / 10000.);
att = new Attribute( "DyKm", nd);
this.ncfile.addAttribute(null, att);
/* calculate the lat2 and lon2 */
if ( proj == 5 ) {
latt = 60.0; /* Fixed for polar stereographic */
imageScale = (1. + Math.sin(DEG_TO_RAD*latt))/2.;
}
lat2 = lat1 + dyKm*(ny-1) / 111.26;
/* Convert to east longitude */
if ( lonv < 0. ) lonv += 360.;
if ( lon1 < 0. ) lon1 += 360.;
lon2 = lon1 + dxKm*(nx-1) / 111.26 * Math.cos(DEG_TO_RAD*lat1);
diff_lon = lonv - lon1;
if ( diff_lon > 180. ) diff_lon -= 360.;
if ( diff_lon < -180. ) diff_lon += 360.;
/*
** Convert to normal longitude to McIDAS convention
*/
lonv = (lonv > 180.) ? -(360.-lonv) : lonv;
lon1 = (lon1 > 180.) ? -(360.-lon1) : lon1;
lon2 = (lon2 > 180.) ? -(360.-lon2) : lon2;
/*
** Check high bit of octet for North or South projection center
*/
nv= new Byte(bos.get());
pole = nv.intValue();
pole = ( pole > 127 ) ? -1 : 1;
ni = new Integer(pole);
att = new Attribute( "ProjCenter", ni);
this.ncfile.addAttribute(null, att);
bos.get(); /* skip one byte for Scanning mode */
bos.get(b3, 0, 3);
nn = getInt( b3, 3);
latin = (((double) nn) / 10000.);
nd = new Double(((double) nn) / 10000.);
att = new Attribute( "Latin", nd);
this.ncfile.addAttribute(null, att);
if (proj == 3 )
projection = new LambertConformal(latin, lonProjectionOrigin, latin, latin);
else // (proj == 5)
projection = new Stereographic(90.0, lonv, imageScale);
break;
default:
System.out.println("unimplemented projection");
}
this.ncfile.addAttribute(null, new Attribute("title", gini_GetEntityID( ent_id )));
this.ncfile.addAttribute(null, new Attribute("summary", getPhysElemSummary(phys_elem, ent_id)));
this.ncfile.addAttribute(null, new Attribute("id", gini_GetSectorID(sec_id)));
this.ncfile.addAttribute(null, new Attribute("keywords_vocabulary", gini_GetPhysElemID(phys_elem, ent_id)));
this.ncfile.addAttribute(null, new Attribute("cdm_data_type", FeatureType.GRID.toString()));
this.ncfile.addAttribute(null, new Attribute("standard_name_vocabulary", getPhysElemLongName(phys_elem, ent_id)));
this.ncfile.addAttribute(null, new Attribute("creator_name", "UNIDATA"));
this.ncfile.addAttribute(null, new Attribute("creator_url", "http://www.unidata.ucar.edu/"));
this.ncfile.addAttribute(null, new Attribute("naming_authority", "UCAR/UOP"));
this.ncfile.addAttribute(null, new Attribute("geospatial_lat_min", new Float(lat1)));
this.ncfile.addAttribute(null, new Attribute("geospatial_lat_max", new Float(lat2)));
this.ncfile.addAttribute(null, new Attribute("geospatial_lon_min", new Float(lon1)));
this.ncfile.addAttribute(null, new Attribute("geospatial_lon_max", new Float(lon2)));
//this.ncfile.addAttribute(null, new Attribute("geospatial_vertical_min", new Float(0.0)));
//this.ncfile.addAttribute(null, new Attribute("geospatial_vertical_max", new Float(0.0)));
/** Get the image resolution.
*/
bos.position(41); /* jump to 42 bytes of PDB */
nv = new Byte( ( bos.get() ) ); /* Res [km] */
att = new Attribute( "imageResolution", nv);
this.ncfile.addAttribute(null, att);
// if(proj == 1)
// dyKm = nv.doubleValue()/dyKm;
/* compression flag 43 byte */
nv = new Byte( ( bos.get() )); /* Res [km] */
att = new Attribute( "compressionFlag", nv );
this.ncfile.addAttribute(null, att);
if ( convertunsignedByte2Short( nv.byteValue() ) == 128 )
{
Z_type = 2;
//out.println( "ReadNexrInfo:: This is a Z file ");
}
/* new 47 - 60 */
bos.position(46);
nv = new Byte( ( bos.get() ) ); /* Cal indicator */
int navcal = convertunsignedByte2Short(nv);
int [] calcods = null;
if(navcal == 128)
calcods = getCalibrationInfo(bos, phys_elem, ent_id);
// only one data variable per gini file
String vname= gini_GetPhysElemID(phys_elem, ent_id);
Variable var = new Variable( ncfile, ncfile.getRootGroup(), null, vname);
var.addAttribute( new Attribute("long_name", getPhysElemLongName(phys_elem, ent_id)));
var.addAttribute( new Attribute("units", getPhysElemUnits(phys_elem, ent_id)));
// var.addAttribute( new Attribute("missing_value", new Byte((byte) 0))); // ??
// get dimensions
int velems;
boolean isRecord = false;
ArrayList dims = new ArrayList();
Dimension dimX = new Dimension( "x", nx, true, false, false);
Dimension dimY = new Dimension( "y", ny, true, false, false);
ncfile.addDimension( null, dimY);
ncfile.addDimension( null, dimX);
velems = dimX.getLength() * dimY.getLength();
dims.add( dimT);
dims.add( dimY);
dims.add( dimX);
var.setDimensions( dims);
// size and beginning data position in file
int vsize = velems;
long begin = dataStart ;
if (debug) log.warn(" name= "+vname+" vsize="+vsize+" velems="+velems+" begin= "+begin+" isRecord="+isRecord+"\n");
if( navcal == 128) {
var.setDataType( DataType.FLOAT);
var.setSPobject( new Vinfo (vsize, begin, isRecord, nx, ny, calcods));
/* var.addAttribute(new Attribute("_Unsigned", "true"));
int numer = calcods[0] - calcods[1];
int denom = calcods[2] - calcods[3];
float a = (numer*1.f) / (1.f*denom);
float b = calcods[0] - a * calcods[2];
var.addAttribute( new Attribute("scale_factor", new Float(a)));
var.addAttribute( new Attribute("add_offset", new Float(b)));
*/
}
else {
var.setDataType( DataType.BYTE);
var.addAttribute(new Attribute("_Unsigned", "true"));
var.addAttribute(new Attribute("_missing_value", new Short((short)255)));
var.addAttribute( new Attribute("scale_factor", new Short((short)(1))));
var.addAttribute( new Attribute("add_offset", new Short((short)(0))));
var.setSPobject( new Vinfo (vsize, begin, isRecord, nx, ny));
}
String coordinates = "x y time";
var.addAttribute( new Attribute(_Coordinate.Axes, coordinates));
ncfile.addVariable(null, var);
// add coordinate information. we need:
// nx, ny, dx, dy,
// latin, lov, la1, lo1
// we have to project in order to find the origin
ProjectionPointImpl start = (ProjectionPointImpl) projection.latLonToProj( new LatLonPointImpl( lat1, lon1));
if (debug) log.warn("start at proj coord "+start);
double startx = start.getX();
double starty = start.getY();
// create coordinate variables
Variable xaxis = new Variable( ncfile, null, null, "x");
xaxis.setDataType( DataType.DOUBLE);
xaxis.setDimensions( "x");
xaxis.addAttribute( new Attribute("long_name", "projection x coordinate"));
xaxis.addAttribute( new Attribute("units", "km"));
xaxis.addAttribute( new Attribute(_Coordinate.AxisType, "GeoX"));
double[] data = new double[nx];
if( proj == 1 ) {
double lon_1 = lon1;
double lon_2 = lon2;
if ( lon1 < 0 ) lon_1 += 360.0;
if ( lon2 < 0 ) lon_2 += 360.0;
double dx = (lon_2 - lon_1) /(nx-1);
for (int i = 0; i < data.length; i++) {
double ln = lon1 + i * dx;
ProjectionPointImpl pt = (ProjectionPointImpl) projection.latLonToProj( new LatLonPointImpl( lat1, ln));
data[i] = pt.getX(); // startx + i*dx;
}
} else {
for (int i = 0; i < data.length; i++)
data[i] = startx + i*dxKm;
}
dataA = Array.factory(DataType.DOUBLE.getPrimitiveClassType(), new int[] {nx}, data);
xaxis.setCachedData( dataA, false);
ncfile.addVariable(null, xaxis);
Variable yaxis = new Variable( ncfile, null, null, "y");
yaxis.setDataType( DataType.DOUBLE);
yaxis.setDimensions( "y");
yaxis.addAttribute( new Attribute("long_name", "projection y coordinate"));
yaxis.addAttribute( new Attribute("units", "km"));
yaxis.addAttribute( new Attribute(_Coordinate.AxisType, "GeoY"));
data = new double[ny];
double endy = starty + dyKm * (data.length - 1); // apparently lat1,lon1 is always the lower ledt, but data is upper left
if(proj == 1) {
double dy = (lat2 - lat1 ) / (ny-1);
for (int i = 0; i < data.length; i++) {
double la = lat2 - i*dy;
ProjectionPointImpl pt = (ProjectionPointImpl) projection.latLonToProj( new LatLonPointImpl( la, lon1));
data[i] = pt.getY(); //endyy - i*dy;
}
}
else {
for (int i = 0; i < data.length; i++)
data[i] = endy - i*dyKm;
}
dataA = Array.factory(DataType.DOUBLE.getPrimitiveClassType(), new int[] {ny}, data);
yaxis.setCachedData( dataA, false);
ncfile.addVariable(null, yaxis);
// coordinate transform variable
Variable ct = new Variable( ncfile, null, null, projection.getClassName());
ct.setDataType( DataType.CHAR);
ct.setDimensions( "");
List params = projection.getProjectionParameters();
for (int i = 0; i < params.size(); i++) {
Parameter p = (Parameter) params.get(i);
ct.addAttribute( new Attribute(p));
}
ct.addAttribute( new Attribute(_Coordinate.TransformType, "Projection"));
ct.addAttribute( new Attribute(_Coordinate.Axes, "x y "));
// fake data
dataA = Array.factory(DataType.CHAR.getPrimitiveClassType(), new int[] {});
dataA.setChar(dataA.getIndex(), ' ');
ct.setCachedData(dataA, false);
ncfile.addVariable(null, ct);
ncfile.addAttribute( null, new Attribute("Conventions", _Coordinate.Convention));