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