001    /*
002     * $Id: NetCDFFile.java,v 1.28 2012/02/19 17:35:42 davep Exp $
003     *
004     * This file is part of McIDAS-V
005     *
006     * Copyright 2007-2012
007     * Space Science and Engineering Center (SSEC)
008     * University of Wisconsin - Madison
009     * 1225 W. Dayton Street, Madison, WI 53706, USA
010     * https://www.ssec.wisc.edu/mcidas
011     * 
012     * All Rights Reserved
013     * 
014     * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
015     * some McIDAS-V source code is based on IDV and VisAD source code.  
016     * 
017     * McIDAS-V is free software; you can redistribute it and/or modify
018     * it under the terms of the GNU Lesser Public License as published by
019     * the Free Software Foundation; either version 3 of the License, or
020     * (at your option) any later version.
021     * 
022     * McIDAS-V is distributed in the hope that it will be useful,
023     * but WITHOUT ANY WARRANTY; without even the implied warranty of
024     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
025     * GNU Lesser Public License for more details.
026     * 
027     * You should have received a copy of the GNU Lesser Public License
028     * along with this program.  If not, see http://www.gnu.org/licenses.
029     */
030    
031    package edu.wisc.ssec.mcidasv.data.hydra;
032    
033    import ucar.nc2.*;
034    import ucar.nc2.ncml.NcMLReader;
035    import ucar.ma2.*;
036    
037    import java.util.HashMap;
038    import java.util.List;
039    import java.util.ArrayList;
040    import java.util.Iterator;
041    import java.net.URL;
042    import java.io.InputStream;
043    import java.io.ByteArrayInputStream;
044    
045    import org.jdom.input.SAXBuilder;
046    import org.jdom.output.XMLOutputter;
047    import org.jdom.Document;
048    import org.jdom.Element;
049    
050    
051    public class NetCDFFile implements MultiDimensionReader {
052    
053       HashMap<String, Variable> varMap = new HashMap<String, Variable>();
054       HashMap<String, String[]> varDimNames = new HashMap<String, String[]>();
055       HashMap<String, int[]> varDimLengths = new HashMap<String, int[]>();
056       HashMap<String, Class> varDataType = new HashMap<String, Class>();
057       HashMap<String, String> varUnits = new HashMap<String, String>();
058    
059       NetcdfFile ncfile = null;
060    
061       public static NetCDFFile makeUnion(String filename, String other) throws Exception {
062         Object obj = new Object();
063         URL url = obj.getClass().getResource("/edu/wisc/ssec/mcidasv/data/hydra/resources/union.ncml");
064         SAXBuilder builder = new SAXBuilder(false);
065         Document doc = null;
066    
067         try {
068           doc = builder.build(url);
069         } catch (Exception e) {
070           e.printStackTrace();
071         }
072         Element root = doc.getRootElement();
073    
074         List list = root.getChildren();
075    
076         list = ((Element)list.get(1)).getChildren();
077    
078         org.jdom.Attribute attr1 = (org.jdom.Attribute) (((Element)list.get(0)).getAttributes()).get(0);
079         attr1.setValue(filename);
080    
081         org.jdom.Attribute attr2 = (org.jdom.Attribute) (((Element)list.get(1)).getAttributes()).get(0);
082         attr2.setValue(other);
083    
084         XMLOutputter xmlOut = new XMLOutputter();
085         String newStr = xmlOut.outputString(doc);
086         ByteArrayInputStream is = new ByteArrayInputStream(newStr.getBytes());
087         return new NetCDFFile(is);
088       }
089    
090       public NetCDFFile(InputStream is) throws Exception {
091         ncfile = NcMLReader.readNcML(is, null);
092         init();
093       }
094    
095       public NetCDFFile(String filename) throws Exception {
096         if (filename.endsWith(".ncml")) {
097           java.io.FileReader rdr = new java.io.FileReader(filename);
098           ncfile = NcMLReader.readNcML(rdr, null);
099         }
100         else {
101           ncfile = NetcdfFile.open(filename);
102         }
103         init();
104       }
105         
106       public NetCDFFile(String filename, org.jdom.Element root) throws Exception {
107              ncfile = NcMLReader.readNcML(filename, root, null);
108              init();
109       }
110       
111       private void init() throws Exception {
112         Iterator varIter = ncfile.getVariables().iterator();
113         while(varIter.hasNext()) {
114           Variable var = (Variable) varIter.next();
115    
116           if (var instanceof Structure) {
117             analyzeStructure((Structure) var);
118             continue;
119           }
120    
121           int rank = var.getRank();
122           String varName = var.getFullName();
123           varMap.put(varName, var);
124           Iterator dimIter = var.getDimensions().iterator();
125           String[] dimNames = new String[rank];
126           int[] dimLengths = new int[rank];
127           int cnt = 0;
128           while(dimIter.hasNext()) {
129             Dimension dim = (Dimension) dimIter.next();
130             String dim_name = dim.getName();
131             if (dim_name == null) dim_name = "dim"+cnt;
132             dimNames[cnt] = dim_name;
133             dimLengths[cnt] = dim.getLength();
134             cnt++;
135           }
136           varDimNames.put(varName, dimNames);
137           varDimLengths.put(varName, dimLengths);
138           varDataType.put(varName, var.getDataType().getPrimitiveClassType());
139           
140           Attribute attr = var.findAttribute("units");
141           if (attr != null) {
142             String unitStr = attr.getStringValue();
143             varUnits.put(varName, unitStr);
144           }
145         }
146       }
147    
148       void analyzeStructure(Structure var) throws Exception {
149               if ((var.getShape()).length == 0) {
150                       return;
151               }
152               String varName = var.getFullName();
153               String[] dimNames = new String[2];
154               int[] dimLengths = new int[2];
155               int cnt = 0;
156               dimLengths[0] = (var.getShape())[0];
157               dimNames[0] = "dim" + cnt;
158    
159               cnt++;
160               StructureData sData = var.readStructure(0);
161               List memList = sData.getMembers();
162               dimLengths[1] = memList.size();
163               dimNames[1] = "dim" + cnt;
164    
165               varDimNames.put(varName, dimNames);
166               varDimLengths.put(varName, dimLengths);
167               varMap.put(varName, var);
168    
169               StructureMembers sMembers = sData.getStructureMembers();
170               Object obj = sData.getScalarObject(sMembers.getMember(0));
171               varDataType.put(varName, obj.getClass());
172       }
173    
174       public Class getArrayType(String array_name) {
175               return varDataType.get(array_name);
176       }
177    
178       public String[] getDimensionNames(String array_name) {
179         return varDimNames.get(array_name);
180       }
181    
182       public int[] getDimensionLengths(String array_name) {
183         return varDimLengths.get(array_name);
184       }
185    
186       public String getArrayUnitString(String array_name) {
187         return varUnits.get(array_name);
188       }
189    
190       public int getDimensionLength(String dimName) {
191         Dimension dim = ncfile.findDimension(dimName);
192         if (dim != null) {
193           return dim.getLength();
194         }
195         else {
196           return -1;
197         }
198       }
199    
200       public float[] getFloatArray(String array_name, int[] start, int[] count, int[] stride) throws Exception {
201         return (float[]) readArray(array_name, start, count, stride);
202       }
203    
204       public int[] getIntArray(String array_name, int[] start, int[] count, int[] stride) throws Exception {
205         return (int[]) readArray(array_name, start, count, stride);
206       }
207    
208       public double[] getDoubleArray(String array_name, int[] start, int[] count, int[] stride) throws Exception {
209         return (double[]) readArray(array_name, start, count, stride);
210       }
211    
212       public short[] getShortArray(String array_name, int[] start, int[] count, int[] stride) throws Exception {
213         return (short[]) readArray(array_name, start, count, stride);
214       }
215    
216       public byte[] getByteArray(String array_name, int[] start, int[] count, int[] stride) throws Exception {
217         return (byte[]) readArray(array_name, start, count, stride);
218       }
219    
220       public Object getArray(String array_name, int[] start, int[] count, int[] stride) throws Exception {
221         return readArray(array_name, start, count, stride);
222       }
223    
224       protected synchronized Object readArray(String array_name, int[] start, int[] count, int[] stride) throws Exception {
225         Variable var = varMap.get(array_name);
226         if (var instanceof Structure) {
227           Array array = Array.factory(getArrayType(array_name), count);
228           Index2D idx = new Index2D(count);
229           for (int i=0; i<count[0]; i++) {
230             StructureData sData = ((Structure)var).readStructure(start[0]+i);
231             StructureMembers sMembers = sData.getStructureMembers();
232             for (int j=0; j<count[1]; j++) {
233               Object obj = sData.getScalarObject(sMembers.getMember(start[1]+j));
234               idx.set(i,j);
235               array.setObject(idx, obj);
236             }
237           }
238           return array.copyTo1DJavaArray();
239         }
240         else {
241           ArrayList rangeList = new ArrayList();
242           for (int i=0;i<start.length;i++) {
243             Range rng = new Range(start[i], start[i]+(count[i]-1)*stride[i], stride[i]);
244             rangeList.add(i, rng);
245           }
246           Array array = var.read(rangeList);
247           return array.copyTo1DJavaArray();
248         }
249       }
250    
251       public HDFArray getGlobalAttribute(String attr_name) throws Exception {
252         throw new Exception("NetCDFFile.getGlobalAttributes: Unimplemented");
253       }
254    
255       public HDFArray getArrayAttribute(String array_name, String attr_name) throws Exception {
256         Object array = null;
257         DataType dataType = null;
258    
259         Variable var = varMap.get(array_name);
260         if (var != null) {
261            Attribute attr = var.findAttribute(attr_name);
262            if (attr != null) {
263               Array attrVals = attr.getValues();
264               dataType = attr.getDataType();
265               array = attrVals.copyTo1DJavaArray();
266            }
267         }
268    
269         if (array == null) {
270            return null;
271         }
272         
273         HDFArray harray = null;
274    
275         if (dataType.getPrimitiveClassType() == Float.TYPE) {
276           harray = HDFArray.make((float[])array);
277         }
278         else if (dataType.getPrimitiveClassType() == Double.TYPE) {
279           harray = HDFArray.make((double[])array);
280         }
281         else if (dataType == DataType.STRING) {
282           harray = HDFArray.make((String[])array);
283         }
284         else if (dataType.getPrimitiveClassType() == Short.TYPE) {
285           harray = HDFArray.make((short[])array);
286         }
287         else if (dataType.getPrimitiveClassType() == Integer.TYPE) {
288           harray = HDFArray.make((int[])array);
289         }
290         return harray;
291       }
292    
293       public void close() throws Exception {
294         ncfile.close();
295       }
296    
297       public HashMap getVarMap() {
298         return varMap;
299       }
300    
301       public boolean hasArray(String name) {
302               if (varMap.get(name) == null) {
303                       return false;
304               } else {
305                       return true;
306               }
307       }
308    
309       public boolean hasDimension(String name) {
310         if (ncfile.findDimension(name) != null) {
311           return true;
312         }
313         else {
314           return false;
315         }
316       }
317    
318       public NetcdfFile getNetCDFFile() {
319               return ncfile;
320       }
321       
322       public static void main(String[] args) throws Exception {
323         NetCDFFile ncfile = new NetCDFFile(args[0]);
324         ncfile.close();
325       }
326    }