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 }