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