/* * Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata * * Portions of this software were developed by the Unidata Program at the * University Corporation for Atmospheric Research. * * Access and use of this software shall impose the following obligations * and understandings on the user. The user is granted the right, without * any fee or cost, to use, copy, modify, alter, enhance and distribute * this software, and any derivative works thereof, and its supporting * documentation for any purpose whatsoever, provided that this entire * notice appears in all copies of the software, derivative works and * supporting documentation. Further, UCAR requests that the user credit * UCAR/Unidata in any publications that result from the use of this * software or in any product that includes this software. The names UCAR * and/or Unidata, however, may not be used in any advertising or publicity * to endorse or promote any products or commercial entity unless specific * written permission is obtained from UCAR/Unidata. The user also * understands that UCAR/Unidata is not obligated to provide the user with * any support, consulting, training or assistance of any kind with regard * to the use, operation and performance of this software nor to provide * the user with any updates, revisions, new versions or "bug fixes." * * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL, * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE. */ package ucar.nc2.dt.radial; import ucar.nc2.dt.*; import ucar.nc2.dataset.*; import ucar.nc2.constants.*; import ucar.nc2.time.CalendarDateUnit; import ucar.nc2.units.DateUnit; import ucar.nc2.VariableSimpleIF; import ucar.nc2.Variable; import ucar.nc2.Attribute; import ucar.nc2.Dimension; import ucar.ma2.*; import ucar.ma2.DataType; import java.io.IOException; import java.util.*; /** * User: yuanho * Date: Jun 7, 2007 * Time: 10:36:52 AM */ public class Netcdf2Dataset extends RadialDatasetSweepAdapter implements TypedDatasetFactoryIF { private NetcdfDataset ds; private boolean isVolume; private double latv, lonv, elev; ///////////////////////////////////////////////// // TypedDatasetFactoryIF public boolean isMine(NetcdfDataset ds) { String format = ds.findAttValueIgnoreCase(null, "format", null); if(format != null) { if(format.startsWith("nssl/netcdf")) return true; } Dimension az = ds.findDimension("Azimuth"); Dimension gt = ds.findDimension("Gate"); if ((null != az) && (null != gt)) { return true; } return false; } public TypedDataset open(NetcdfDataset ncd, ucar.nc2.util.CancelTask task, StringBuilder errlog) throws IOException { return new Netcdf2Dataset(ncd); } public FeatureType getScientificDataType() { return FeatureType.RADIAL; } public Netcdf2Dataset() {} /** * Constructor. * * @param ds must be from netcdf IOSP */ public Netcdf2Dataset(NetcdfDataset ds) { super(ds); this.ds = ds; desc = "Netcdf/NCML 2 radar dataset"; setEarthLocation(); try { setTimeUnits(); } catch (Exception e) { throw new RuntimeException(e); } setStartDate(); setEndDate(); setBoundingBox(); try { addCoordSystem(ds); } catch ( IOException e ) { e.printStackTrace(); } } private void addCoordSystem(NetcdfDataset ds) throws IOException { // int time = ds.findGlobalAttributeIgnoreCase("Time").getNumericValue().intValue(); double ele = 0; Attribute attr = ds.findGlobalAttributeIgnoreCase("Elevation"); if( attr != null ) ele = attr.getNumericValue().doubleValue(); // ncml agg add this sweep variable as agg dimension Variable sp = ds.findVariable("sweep"); if(sp == null) { // add Elevation ds.addDimension( null, new Dimension("Elevation", 1 , true)); String lName = "elevation angle in degres: 0 = parallel to pedestal base, 90 = perpendicular"; CoordinateAxis v = new CoordinateAxis1D(ds, null, "Elevation", DataType.DOUBLE, "Elevation", "degrees", lName); ds.setValues(v, 1, ele, 0); v.addAttribute(new Attribute(_Coordinate.AxisType, AxisType.RadialElevation.toString())); ds.addVariable(null, v); } else { Array spdata = sp.read(); float [] spd = (float [])spdata.get1DJavaArray(float.class); int spsize = spd.length; // add Elevation ds.addDimension( null, new Dimension("Elevation", spsize , true)); String lName = "elevation angle in degres: 0 = parallel to pedestal base, 90 = perpendicular"; CoordinateAxis v = new CoordinateAxis1D(ds, null, "Elevation", DataType.DOUBLE, "Elevation", "degrees", lName); //ds.setValues(v, (ArrayList)spdata); v.addAttribute(new Attribute(_Coordinate.AxisType, AxisType.RadialElevation.toString())); ds.addVariable(null, v); } ds.addAttribute( null, new Attribute("IsRadial", new Integer(1))); attr = ds.findGlobalAttributeIgnoreCase("vcp-value"); String vcp; if(attr == null) vcp = "11"; else vcp = attr.getStringValue(); ds.addAttribute( null, new Attribute("VolumeCoveragePatternName", vcp)); ds.finish(); } public ucar.unidata.geoloc.EarthLocation getCommonOrigin() { return origin; } public String getRadarID() { Attribute ga = ds.findGlobalAttribute("radarName-value"); if(ga != null) return ga.getStringValue(); else return "XXXX"; } public boolean isStationary() { return true; } public String getRadarName() { return ds.findGlobalAttribute("ProductStationName").getStringValue(); } public String getDataFormat() { return "NetCDF Level II"; } public void setIsVolume(NetcdfDataset nds) { String format = nds.findAttValueIgnoreCase(null, "volume", null); if( format == null) { isVolume = false; return; } if (format.equals("true")) isVolume = true; else isVolume = false; } public boolean isVolume() { return isVolume; } protected void setEarthLocation() { Attribute ga = ds.findGlobalAttribute("Latitude"); if(ga != null ) latv = ga.getNumericValue().doubleValue(); else latv = 0.0; ga = ds.findGlobalAttribute("Longitude"); if(ga != null) lonv = ga.getNumericValue().doubleValue(); else lonv = 0.0; ga = ds.findGlobalAttribute("Height"); if(ga != null) elev = ga.getNumericValue().doubleValue(); else elev = 0.0; origin = new ucar.unidata.geoloc.EarthLocationImpl(latv, lonv, elev); } protected void setTimeUnits() throws Exception { List axes = ds.getCoordinateAxes(); for (int i = 0; i < axes.size(); i++) { CoordinateAxis axis = (CoordinateAxis) axes.get(i); if (axis.getAxisType() == AxisType.Time) { String units = axis.getUnitsString(); dateUnits = new DateUnit(units); calDateUnits = CalendarDateUnit.of(null, units); return; } } parseInfo.append("*** Time Units not Found\n"); } protected void setStartDate() { String start_datetime = ds.findAttValueIgnoreCase(null, "time_coverage_start", null); if (start_datetime != null) startDate = DateUnit.getStandardOrISO(start_datetime); else parseInfo.append("*** start_datetime not Found\n"); } protected void setEndDate() { String end_datetime = ds.findAttValueIgnoreCase(null, "time_coverage_end", null); if (end_datetime != null) endDate = DateUnit.getStandardOrISO(end_datetime); else parseInfo.append("*** end_datetime not Found\n"); } protected void addRadialVariable(NetcdfDataset nds, Variable var) { RadialVariable rsvar = null; String vName = var.getShortName() ; int rnk = var.getRank(); setIsVolume(nds); if(isVolume && rnk == 3) { VariableSimpleIF v = new MyRadialVariableAdapter(vName, var.getAttributes()); rsvar = makeRadialVariable(nds, v, var); } else if(!isVolume && rnk == 2) { VariableSimpleIF v = new MyRadialVariableAdapter(vName, var.getAttributes()); rsvar = makeRadialVariable(nds, v, var); } if(rsvar != null) dataVariables.add(rsvar); } protected RadialVariable makeRadialVariable(NetcdfDataset nds, VariableSimpleIF v, Variable v0) { return new Netcdf2Variable(nds, v, v0); } public void clearDatasetMemory() { List rvars = getDataVariables(); Iterator iter = rvars.iterator(); while (iter.hasNext()) { RadialVariable radVar = (RadialVariable)iter.next(); radVar.clearVariableMemory(); } } public String getInfo() { StringBuilder sbuff = new StringBuilder(); sbuff.append("Netcdfs2Dataset\n"); sbuff.append(super.getDetailInfo()); sbuff.append("\n\n"); sbuff.append(parseInfo.toString()); return sbuff.toString(); } private class Netcdf2Variable extends MyRadialVariableAdapter implements RadialDatasetSweep.RadialVariable { ArrayList sweeps; int nsweeps; String name; private Netcdf2Variable(NetcdfDataset nds, VariableSimpleIF v, Variable v0) { super(v.getShortName(), v0.getAttributes()); sweeps = new ArrayList(); nsweeps = 0; name = v.getShortName(); int[] shape = v0.getShape(); int count = v0.getRank() - 1; int ngates = shape[count]; count--; int nrays = shape[count]; count--; if(shape.length == 3) nsweeps = shape[count]; else nsweeps = 1; for(int i = 0; i< nsweeps; i++) sweeps.add( new Netcdf2Sweep(v0, i, nrays, ngates)) ; } public String toString() { return name; } public float[] readAllData() throws IOException { Array allData; Sweep spn = (Sweep)sweeps.get(0); Variable v = spn.getsweepVar(); try { allData = v.read(); } catch (IOException e) { throw new IOException(e.getMessage()); } return (float []) allData.get1DJavaArray(float.class); } public int getNumSweeps() { return nsweeps; } public Sweep getSweep(int sweepNo) { return (Sweep) sweeps.get(sweepNo); } public void clearVariableMemory() { // doing nothing } ////////////////////////////////////////////////////////////////////// private class Netcdf2Sweep implements RadialDatasetSweep.Sweep { double meanElevation = Double.NaN; double meanAzimuth = Double.NaN; int sweepno, nrays, ngates; Variable sweepVar; Netcdf2Sweep(Variable v, int sweepno, int rays, int gates) { this.sweepno = sweepno; this.nrays = rays; this.ngates = gates; this.sweepVar = v; //setMeanElevation(); //setMeanAzimuth(); } public Variable getsweepVar(){ return sweepVar; } public float[] readData() throws java.io.IOException { Array allData; int [] shape = sweepVar.getShape(); int [] origind = new int[ sweepVar.getRank()]; if(isVolume) { origind[0] = sweepno; origind[1] = 0; shape[0] = 1; } try { allData = sweepVar.read(origind, shape); } catch (InvalidRangeException e) { throw new IOException(e.getMessage()); } int nradials = shape[0]; int ngates = shape[1]; IndexIterator dataIter = allData.getIndexIterator(); for (int j = 0; j < nradials; j++) { for(int i = 0; i < ngates; i++) { float tp = dataIter.getFloatNext(); if(tp == -32768.0f || tp == -99900.0f) { dataIter.setFloatCurrent(Float.NaN); } } } return (float []) allData.get1DJavaArray(float.class); } // private Object MUTEX =new Object(); /* read 1d data ngates */ public float[] readData(int ray) throws java.io.IOException { Array rayData; int [] shape = sweepVar.getShape(); int [] origind = new int[ sweepVar.getRank()]; if(isVolume) { origind[0] = sweepno; origind[1] = ray; shape[0] = 1; shape[1] = 1; } else { shape[0] = 1; origind[0] = ray; } try { rayData = sweepVar.read(origind, shape); } catch (ucar.ma2.InvalidRangeException e) { throw new IOException(e.getMessage()); } int ngates = shape[1]; IndexIterator dataIter = rayData.getIndexIterator(); for(int i = 0; i < ngates; i++) { float tp = dataIter.getFloatNext(); if(tp == -32768.0f || tp == -99900.0f) { dataIter.setFloatCurrent(Float.NaN); } } return (float []) rayData.get1DJavaArray(float.class); } private void setMeanElevation() { if(isVolume) { try{ Variable sp = ds.findVariable("sweep"); Array spData = sp.read(); float [] spArray = (float [])spData.get1DJavaArray(float.class); meanElevation = spArray[sweepno]; } catch (IOException e) { e.printStackTrace(); meanElevation = 0.0; } } else { Attribute data = ds.findGlobalAttribute("Elevation"); meanElevation = data.getNumericValue().doubleValue(); } } public float getMeanElevation() { if( Double.isNaN(meanElevation) ) setMeanElevation(); return (float) meanElevation ; } public double meanDouble(Array a) { double sum = 0; int size = 0; IndexIterator iterA = a.getIndexIterator(); while (iterA.hasNext()) { double s = iterA.getDoubleNext(); if (! Double.isNaN(s)) { sum += s; size ++; } } if (size > 0) return sum / size; else return Double.POSITIVE_INFINITY; } public int getGateNumber() { return ngates; } public int getRadialNumber() { return nrays; } public RadialDatasetSweep.Type getType() { return null; } public ucar.unidata.geoloc.EarthLocation getOrigin(int ray) { return origin; } public Date getStartingTime() { return startDate; } public Date getEndingTime() { return endDate; } public int getSweepIndex() { return sweepno; } // public int getNumGates() { // return ngates; // } private void setMeanAzimuth() { meanAzimuth = 0.0; } public float getMeanAzimuth() { if(Double.isNaN(meanAzimuth)) setMeanAzimuth(); return (float) meanAzimuth; } public boolean isConic() { return true; } public float getElevation(int ray) throws IOException { return (float)meanElevation; } public float[] getElevation() throws IOException { float [] dataValue = new float[nrays]; for (int i = 0; i < nrays; i++) { dataValue[i] = (float)meanElevation; } return dataValue; } public float[] getAzimuth() throws IOException { Array aziData = ds.findVariable("Azimuth").read(); return (float [])aziData.get1DJavaArray(float.class); } public float getAzimuth(int ray) throws IOException { String aziName = "Azimuth"; try { Array aziData = ds.findVariable(aziName).read(); if(isVolume) { int [] aziOrigin = new int[2]; aziOrigin[0] = sweepno; aziOrigin[1] = 0; int [] aziShape = {1, getRadialNumber()}; aziData = aziData.section(aziOrigin, aziShape); } Index index = aziData.getIndex(); return aziData.getFloat(index.set(ray)); } catch (ucar.ma2.InvalidRangeException e) { throw new IOException(e); } } public float getRadialDistance(int gate) throws IOException { float gateStart = getRangeToFirstGate(); Variable gateSize = ds.findVariable("GateWidth"); float [] data = (float [])gateSize.read().get1DJavaArray(float.class); float dist = gateStart + gate*data[0]; return dist; } public float getTime(int ray) throws IOException { return startDate.getTime(); } public float getBeamWidth() { return 0.95f; // degrees, info from Chris Burkhart } public float getNyquistFrequency() { return 0; // LOOK this may be radial specific } public float getRangeToFirstGate() { Attribute firstGate = ds.findGlobalAttributeIgnoreCase("RangeToFirstGate"); double gateStart = firstGate.getNumericValue().doubleValue(); return (float)gateStart; } public float getGateSize() { try { return getRadialDistance(1) - getRadialDistance(0); } catch (IOException e) { e.printStackTrace(); return 0.0f; } } public boolean isGateSizeConstant() { return true; } public void clearSweepMemory() { } } // Netcdf2Sweep class } // Netcdf2Variable private static void testRadialVariable(RadialDatasetSweep.RadialVariable rv) throws IOException { int nsweep = rv.getNumSweeps(); //System.out.println("*** radar Sweep number is: \n" + nsweep); Sweep sw; float [] az; for (int i = 0; i < nsweep; i++) { //ucar.unidata.util.Trace.call1("LevelII2Dataset:testRadialVariable getSweep " + i); sw = rv.getSweep(i); sw.getMeanElevation(); //ucar.unidata.util.Trace.call2("LevelII2Dataset:testRadialVariable getSweep " + i); float me = sw.getMeanElevation(); System.out.println("*** radar Sweep mean elevation of sweep " + i + " is: " + me); int nrays = sw.getRadialNumber(); az = new float[nrays]; for (int j = 0; j < nrays; j++) { float azi = sw.getAzimuth(j); az[j] = azi; } //System.out.println("*** radar Sweep mean elevation of sweep " + i + " is: " + me); } sw = rv.getSweep(0); //ucar.unidata.util.Trace.call1("LevelII2Dataset:testRadialVariable readData"); float [] ddd = sw.readData(); sw.getAzimuth(); sw.getElevation(); //ucar.unidata.util.Trace.call2("LevelII2Dataset:testRadialVariable readData"); assert(null != ddd); int nrays = sw.getRadialNumber(); az = new float[nrays]; for (int i = 0; i < nrays; i++) { int ngates = sw.getGateNumber(); assert(ngates > 0); float [] d = sw.readData(i); assert(null != d); // float [] e = sw.readDataNew(i); // assert(null != e); float azi = sw.getAzimuth(i); assert(azi > 0); az[i] = azi; float ele = sw.getElevation(i); assert(ele > 0); float la = (float) sw.getOrigin(i).getLatitude(); assert(la > 0); float lo = (float) sw.getOrigin(i).getLongitude(); assert(lo > 0); float al = (float) sw.getOrigin(i).getAltitude(); assert(al > 0); } assert(0 != nrays); } public static void main(String args[]) throws Exception, IOException, InstantiationException, IllegalAccessException { //String fileIn = "/home/yuanho/NIDS/Reflectivity_0.50_20070329-204156.netcdf"; String fileIn ="/home/yuanho/nssl/netcdf.ncml"; RadialDatasetSweep rds = (RadialDatasetSweep) TypedDatasetFactory.open( FeatureType.RADIAL, fileIn, null, new StringBuilder()); //String st = rds.getStartDate().toString(); //String et = rds.getEndDate().toString(); //String id = rds.getRadarID(); //String name = rds.getRadarName(); rds.getRadarID(); rds.getDataVariables(); RadialDatasetSweep.RadialVariable rf = (RadialDatasetSweep.RadialVariable) rds.getDataVariable("Reflectivity"); rf.getSweep(0); testRadialVariable(rf); } }