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 package edu.wisc.ssec.mcidasv.data;
029
030
031 import edu.wisc.ssec.mcidasv.data.hydra.NetCDFFile;
032 import visad.Data;
033 import visad.Unit;
034 import visad.Gridded3DSet;
035 import visad.Gridded1DDoubleSet;
036 import visad.Gridded1DSet;
037 import visad.Set;
038 import visad.UnionSet;
039 import visad.RealTupleType;
040 import visad.RealType;
041 import visad.FlatField;
042 import visad.FieldImpl;
043 import visad.Integer1DSet;
044 import visad.FunctionType;
045 import visad.CoordinateSystem;
046 import visad.VisADException;
047 import visad.DateTime;
048 import visad.data.units.Parser;
049 import visad.data.units.ParseException;
050
051 import java.rmi.RemoteException;
052 import java.util.Hashtable;
053 import java.util.List;
054
055 import ucar.unidata.util.Misc;
056 import ucar.unidata.util.Range;
057
058 import ucar.unidata.data.DataUtil;
059 import ucar.unidata.data.DataChoice;
060 import ucar.unidata.data.DataDataChoice;
061 import ucar.unidata.data.DirectDataChoice;
062 import ucar.unidata.data.DataSelection;
063 import ucar.unidata.data.DataCategory;
064 import ucar.unidata.data.DataSourceImpl;
065 import ucar.unidata.data.DataSourceDescriptor;
066
067
068
069 public class NearCastTrajDataSource extends DataSourceImpl {
070
071 private static final String DATA_DESCRIPTION = "NearCastTrajectory";
072
073 public static String parcelDimName = "parcel";
074 public static String timeDimName = "times";
075 public static String lonName = "lon";
076 public static String latName = "lat";
077
078 NetCDFFile ncFile = null;
079 String pressName = "pres";
080 String timeName = "times";
081
082
083 int[] start = new int[2];
084 int[] count = new int[2];
085 int[] stride = new int[2];
086
087
088 int parcelDimIdx = 0;
089 int timeDimIdx = 1;
090
091 String[] paramList = null;
092
093 String fileName = null;
094
095 CoordinateSystem presToHeightCS = null;
096
097 Unit timeUnit;
098 Set timeSet;
099
100 int numTimes;
101 int numParcels;
102
103 Range lonRange = new Range();
104 Range latRange = new Range();
105 Range paramRange = new Range();
106
107 public NearCastTrajDataSource() {
108 }
109
110 public NearCastTrajDataSource(String filename) throws VisADException {
111 this(null, Misc.newList(filename), null);
112 }
113
114 public NearCastTrajDataSource(DataSourceDescriptor descriptor,
115 String fileName, Hashtable properties) throws VisADException {
116 this(descriptor, Misc.newList(fileName), properties);
117 }
118
119 public NearCastTrajDataSource(DataSourceDescriptor descriptor,
120 List newSources, Hashtable properties) throws VisADException {
121
122 super(descriptor, DATA_DESCRIPTION, DATA_DESCRIPTION, properties);
123
124 presToHeightCS = DataUtil.getPressureToHeightCS(DataUtil.STD_ATMOSPHERE);
125
126 fileName = (String) newSources.get(0);
127
128 try {
129 ncFile = new NetCDFFile(fileName);
130 }
131 catch (Exception e) {
132 e.printStackTrace();
133 }
134
135 paramList = new String[] {"temp", "q", "the", "tp", "MS", "MQ", "MTe", "TP"};
136
137
138 String unitStr = ncFile.getArrayUnitString(timeName);
139 try {
140 timeUnit = Parser.parse(unitStr);
141 }
142 catch (ParseException e) {
143 System.out.println(e);
144 }
145
146 numTimes = ncFile.getDimensionLength(timeDimName);
147 numParcels = ncFile.getDimensionLength(parcelDimName);
148
149 try {
150 Class type = ncFile.getArrayType(timeName);
151 if (type == Double.TYPE) {
152 double[] timeValues = ncFile.getDoubleArray(timeName, new int[] {0}, new int[] {numTimes}, new int[] {1});
153 timeSet = new Gridded1DDoubleSet(
154 RealType.Time, new double[][] {timeValues}, numTimes, null, new Unit[] {timeUnit}, null);
155 }
156 else if (type == Float.TYPE) {
157 float[] timeValues = ncFile.getFloatArray(timeName, new int[] {0}, new int[] {numTimes}, new int[] {1});
158 timeSet = new Gridded1DSet(RealType.Time, new float[][] {timeValues}, numTimes, null, new Unit[] {timeUnit}, null);
159
160 }
161 }
162 catch (Exception e) {
163 e.printStackTrace();
164 }
165 }
166
167
168 public FlatField[] createVisADData(String paramName) {
169 return null;
170 }
171
172 public FlatField singleTraj(String paramName, int parcelIndex, int timeStart, int timeCount, int timeStride) throws Exception {
173
174 start[parcelDimIdx] = parcelIndex;
175 start[timeDimIdx] = timeStart;
176
177 count[parcelDimIdx] = 1;
178 count[timeDimIdx] = timeCount;
179
180 stride[parcelDimIdx] = 1;
181 stride[timeDimIdx] = 1;
182
183 float[] lons = ncFile.getFloatArray(lonName, start, count, stride);
184 float[] lats = ncFile.getFloatArray(latName, start, count, stride);
185
186 float[] minmax = minmax(lons, (float)lonRange.getMin(), (float)lonRange.getMax());
187 lonRange.setMin(minmax[0]);
188 lonRange.setMax(minmax[1]);
189 minmax = minmax(lats, (float)latRange.getMin(), (float)latRange.getMax());
190 latRange.setMin(minmax[0]);
191 latRange.setMax(minmax[1]);
192
193 float[] pres = ncFile.getFloatArray(pressName, start, count, stride);
194 float[] param = ncFile.getFloatArray(paramName, start, count, stride);
195 minmax = minmax(param, (float)paramRange.getMin(), (float)paramRange.getMax());
196 paramRange.setMin(minmax[0]);
197 paramRange.setMax(minmax[1]);
198
199 float[] alt = (presToHeightCS.toReference(new float[][] {pres}))[0];
200
201 float[][] trajCoords = new float[][] {lons, lats, alt};
202
203 Gridded3DSet domain = new Gridded3DSet(RealTupleType.SpatialEarth3DTuple, trajCoords, trajCoords[0].length);
204
205 FunctionType fncType = new FunctionType(RealTupleType.SpatialEarth3DTuple, RealType.getRealType(paramName));
206 FlatField traj = new FlatField(fncType, domain);
207 traj.setSamples(new float[][] {param}, false);
208
209 return traj;
210 }
211
212 /**
213 * Make and insert the <code>DataChoice</code>-s for this
214 * <code>DataSource</code>.
215 */
216 public void doMakeDataChoices() {
217 try {
218 for (int k=0; k<paramList.length; k++) {
219 DataChoice choice = doMakeDataChoice(k);
220 if (choice != null) {
221 addDataChoice(choice);
222 }
223 }
224 }
225 catch(Exception e) {
226 e.printStackTrace();
227 }
228 }
229
230 private DataChoice doMakeDataChoice(int idx) throws Exception {
231 String name = paramList[idx];
232 DirectDataChoice ddc = null;
233 if (ncFile.hasArray(name)) {
234 ddc = new DirectDataChoice(this, new Integer(idx), name, name, null, new Hashtable());
235 }
236 return ddc;
237 }
238
239 protected Data getDataInner(DataChoice dataChoice, DataCategory category,
240 DataSelection dataSelection,
241 Hashtable requestProperties)
242 throws VisADException, RemoteException {
243
244 String paramName = dataChoice.getName();
245
246 FieldImpl trajField = new FieldImpl(
247 new FunctionType(RealType.Generic, new FunctionType(RealTupleType.SpatialEarth3DTuple, RealType.getRealType(paramName))), new Integer1DSet(numParcels));
248
249 FieldImpl trajTimeField = new FieldImpl(new FunctionType(RealType.Time, trajField.getType()), timeSet);
250
251 lonRange.setMin(Float.MAX_VALUE);
252 lonRange.setMax(-Float.MAX_VALUE);
253 latRange.setMin(Float.MAX_VALUE);
254 latRange.setMax(-Float.MAX_VALUE);
255 paramRange.setMin(Float.MAX_VALUE);
256 paramRange.setMax(-Float.MAX_VALUE);
257
258 try {
259 for (int t=0; t<numTimes; t++) {
260 trajField = new FieldImpl(
261 new FunctionType(RealType.Generic, new FunctionType(RealTupleType.SpatialEarth3DTuple, RealType.getRealType(paramName))), new Integer1DSet(numParcels));
262 for (int k=0; k<numParcels/4; k++) {
263 FlatField fld = singleTraj(paramName, k*4, 0, t+1, 1);
264 trajField.setSample(k, fld);
265 }
266 trajTimeField.setSample(t, trajField);
267 }
268 return trajTimeField;
269 }
270 catch (Exception e) {
271 e.printStackTrace();
272 return null;
273 }
274 }
275
276 public static float[] minmax(float[] values, float min, float max) {
277 for (int k = 0; k < values.length; k++) {
278 float val = values[k];
279 if ((val == val) && (val < Float.POSITIVE_INFINITY) && (val > Float.NEGATIVE_INFINITY)) {
280 if (val < min) min = val;
281 if (val > max) max = val;
282 }
283 }
284 return new float[] {min, max};
285 }
286
287 public Range getLonRange() {
288 return lonRange;
289 }
290
291 public Range getLatRange() {
292 return latRange;
293 }
294
295 public Range getParamRange() {
296 return paramRange;
297 }
298
299 }