001/*
002 * $Id: NetCDFFile.java,v 1.21 2011/03/24 16:06:33 davep Exp $
003 *
004 * This file is part of McIDAS-V
005 *
006 * Copyright 2007-2011
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
031package edu.wisc.ssec.mcidasv.data.hydra;
032
033import ucar.nc2.*;
034import ucar.nc2.ncml.NcMLReader;
035import ucar.ma2.*;
036import java.util.HashMap;
037import java.util.List;
038import java.util.ArrayList;
039import java.util.Iterator;
040import java.net.URL;
041import java.net.URL;
042import java.io.InputStream;
043import java.io.ByteArrayInputStream;
044
045import org.jdom.input.SAXBuilder;
046import org.jdom.output.XMLOutputter;
047import org.jdom.Document;
048import org.jdom.Element;
049
050
051public 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
060   NetcdfFile ncfile = null;
061
062
063   public static NetCDFFile makeUnion(String filename) throws Exception {
064     String other = new String(filename);
065     other = other.replace("obs", "nav");
066     Object obj = new Object();
067     URL url = obj.getClass().getResource("/edu/wisc/ssec/mcidasv/data/hydra/resources/union.ncml");
068     SAXBuilder builder = new SAXBuilder(false);
069     Document doc = null;
070
071     try {
072       doc = builder.build(url);
073     } catch (Exception e) {
074       e.printStackTrace();
075     }
076     Element root = doc.getRootElement();
077
078     List list = root.getChildren();
079
080     list = ((Element)list.get(1)).getChildren();
081
082     org.jdom.Attribute attr1 = (org.jdom.Attribute) (((Element)list.get(0)).getAttributes()).get(0);
083     attr1.setValue(filename);
084
085     org.jdom.Attribute attr2 = (org.jdom.Attribute) (((Element)list.get(1)).getAttributes()).get(0);
086     attr2.setValue(other);
087
088     XMLOutputter xmlOut = new XMLOutputter();
089     String newStr = xmlOut.outputString(doc);
090     ByteArrayInputStream is = new ByteArrayInputStream(newStr.getBytes());
091     return new NetCDFFile(is);
092   }
093
094   public NetCDFFile(InputStream is) throws Exception {
095     ncfile = NcMLReader.readNcML(is, null);
096     init();
097   }
098
099   public NetCDFFile(String filename) throws Exception {
100     if (filename.endsWith(".ncml")) {
101       java.io.FileReader rdr = new java.io.FileReader(filename);
102       ncfile = NcMLReader.readNcML(rdr, null);
103     }
104     else {
105       ncfile = NetcdfFile.open(filename);
106     }
107     init();
108   }
109     
110   public NetCDFFile(String filename, org.jdom.Element root) throws Exception {
111          ncfile = NcMLReader.readNcML(filename, root, null);
112          init();
113   }
114   
115   private void init() throws Exception {
116     Iterator varIter = ncfile.getVariables().iterator();
117     while(varIter.hasNext()) {
118       Variable var = (Variable) varIter.next();
119
120       if (var instanceof Structure) {
121         analyzeStructure((Structure) var);
122         continue;
123       }
124
125       int rank = var.getRank();
126       String varName = var.getName();
127       varMap.put(var.getName(), var);
128       Iterator dimIter = var.getDimensions().iterator();
129       String[] dimNames = new String[rank];
130       int[] dimLengths = new int[rank];
131       int cnt = 0;
132       while(dimIter.hasNext()) {
133         Dimension dim = (Dimension) dimIter.next();
134         String dim_name = dim.getName();
135         if (dim_name == null) dim_name = "dim"+cnt;
136         dimNames[cnt] = dim_name;
137         dimLengths[cnt] = dim.getLength();
138         cnt++;
139       }
140       varDimNames.put(varName, dimNames);
141       varDimLengths.put(varName, dimLengths);
142       varDataType.put(varName, var.getDataType().getPrimitiveClassType());
143       
144       Attribute attr = var.findAttribute("units");
145       if (attr != null) {
146         String unitStr = attr.getStringValue();
147         varUnits.put(varName, unitStr);
148       }
149     }
150   }
151
152   void analyzeStructure(Structure var) throws Exception {
153     if ((var.getShape()).length == 0) {
154       return;
155     }
156     String varName = var.getName();
157     String[] dimNames = new String[2];
158     int[] dimLengths = new int[2];
159     List vlist = var.getVariables();
160     int cnt = 0;
161     dimLengths[0] = (var.getShape())[0];
162     dimNames[0] = "dim"+cnt;
163     
164     
165     cnt++;
166     StructureData sData = var.readStructure(0);
167     List memList = sData.getMembers();
168     dimLengths[1] = memList.size();
169     dimNames[1] = "dim"+cnt;
170
171     varDimNames.put(varName, dimNames);
172     varDimLengths.put(varName, dimLengths);
173     varMap.put(var.getName(), var);
174     
175     StructureMembers sMembers = sData.getStructureMembers();
176     Object obj = sData.getScalarObject(sMembers.getMember(0));
177     varDataType.put(varName, obj.getClass());
178   }
179
180   public Class getArrayType(String array_name) {
181     Variable var = varMap.get(array_name);
182     return varDataType.get(array_name);
183   }
184
185   public String[] getDimensionNames(String array_name) {
186     return varDimNames.get(array_name);
187   }
188
189   public int[] getDimensionLengths(String array_name) {
190     return varDimLengths.get(array_name);
191   }
192
193   public String getArrayUnitString(String array_name) {
194     return varUnits.get(array_name);
195   }
196
197   public int getDimensionLength(String dimName) {
198     Dimension dim = ncfile.findDimension(dimName);
199     return dim.getLength();
200   }
201
202   public float[] getFloatArray(String array_name, int[] start, int[] count, int[] stride) throws Exception {
203     return (float[]) readArray(array_name, start, count, stride);
204   }
205
206   public int[] getIntArray(String array_name, int[] start, int[] count, int[] stride) throws Exception {
207     return (int[]) readArray(array_name, start, count, stride);
208   }
209
210   public double[] getDoubleArray(String array_name, int[] start, int[] count, int[] stride) throws Exception {
211     return (double[]) readArray(array_name, start, count, stride);
212   }
213
214   public short[] getShortArray(String array_name, int[] start, int[] count, int[] stride) throws Exception {
215     return (short[]) readArray(array_name, start, count, stride);
216   }
217
218   public byte[] getByteArray(String array_name, int[] start, int[] count, int[] stride) throws Exception {
219     return (byte[]) readArray(array_name, start, count, stride);
220   }
221
222   public Object getArray(String array_name, int[] start, int[] count, int[] stride) throws Exception {
223     return readArray(array_name, start, count, stride);
224   }
225
226   private synchronized Object readArray(String array_name, int[] start, int[] count, int[] stride) throws Exception {
227     Variable var = varMap.get(array_name);
228     if (var instanceof Structure) {
229       Array array = Array.factory(getArrayType(array_name), count);
230       Index2D idx = new Index2D(count);
231       for (int i=0; i<count[0]; i++) {
232         StructureData sData = ((Structure)var).readStructure(start[0]+i);
233         StructureMembers sMembers = sData.getStructureMembers();
234         for (int j=0; j<count[1]; j++) {
235           Object obj = sData.getScalarObject(sMembers.getMember(start[1]+j));
236           idx.set(i,j);
237           array.setObject(idx, obj);
238         }
239       }
240       return array.copyTo1DJavaArray();
241     }
242     else {
243       ArrayList rangeList = new ArrayList();
244       for (int i=0;i<start.length;i++) {
245         Range rng = new Range(start[i], start[i]+(count[i]-1)*stride[i], stride[i]);
246         rangeList.add(i, rng);
247       }
248       Array array = var.read(rangeList);
249       return array.copyTo1DJavaArray();
250     }
251   }
252
253   public HDFArray getGlobalAttribute(String attr_name) throws Exception {
254     throw new Exception("NetCDFFile.getGlobalAttributes: Unimplemented");
255   }
256
257   public HDFArray getArrayAttribute(String array_name, String attr_name) throws Exception {
258     Object array = null;
259     DataType dataType = null;
260
261     Variable var = varMap.get(array_name);
262     if (var != null) {
263        Attribute attr = var.findAttribute(attr_name);
264        if (attr != null) {
265           Array attrVals = attr.getValues();
266           dataType = attr.getDataType();
267           array = attrVals.copyTo1DJavaArray();
268        }
269     }
270
271     if (array == null) {
272        return null;
273     }
274     
275     HDFArray harray = null;
276
277     if (dataType.getPrimitiveClassType() == Float.TYPE) {
278       harray = HDFArray.make((float[])array);
279     }
280     else if (dataType.getPrimitiveClassType() == Double.TYPE) {
281       harray = HDFArray.make((double[])array);
282     }
283     else if (dataType == DataType.STRING) {
284       harray = HDFArray.make((String[])array);
285     }
286     else if (dataType.getPrimitiveClassType() == Short.TYPE) {
287       harray = HDFArray.make((short[])array);
288     }
289     else if (dataType.getPrimitiveClassType() == Integer.TYPE) {
290       harray = HDFArray.make((int[])array);
291     }
292     return harray;
293   }
294
295   public void close() throws Exception {
296     ncfile.close();
297   }
298
299   public HashMap getVarMap() {
300     return varMap;
301   }
302
303   public boolean hasArray(String name) {
304           if (varMap.get(name) == null) {
305                   return false;
306           } else {
307                   return true;
308           }
309   }
310
311   public NetcdfFile getNetCDFFile() {
312           return ncfile;
313   }
314   
315   public static void main(String[] args) throws Exception {
316     NetCDFFile ncfile = new NetCDFFile(args[0]);
317     ncfile.close();
318   }
319}