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 visad.Data;
032 import visad.FlatField;
033 import visad.Set;
034 import visad.Gridded1DSet;
035 import visad.CoordinateSystem;
036 import visad.RealType;
037 import visad.RealTupleType;
038 import visad.SetType;
039 import visad.Linear1DSet;
040 import visad.Linear2DSet;
041 import visad.Unit;
042 import visad.FunctionType;
043 import visad.VisADException;
044 import visad.QuickSort;
045 import java.rmi.RemoteException;
046
047 import java.util.Hashtable;
048 import java.util.HashMap;
049 import java.util.StringTokenizer;
050
051 import java.io.BufferedReader;
052 import java.io.FileInputStream;
053 import java.io.IOException;
054 import java.io.InputStream;
055 import java.io.InputStreamReader;
056
057
058 public abstract class ProfileAlongTrack extends MultiDimensionAdapter {
059
060 private FunctionType mathtype;
061
062 int TrackLen;
063 int VertLen;
064
065 private float[] vertLocs = null;
066 private float[] trackTimes = null;
067 private float[] trackLongitude = null;
068 private float[] trackLatitude = null;
069
070 public static String longitude_name = "Longitude";
071 public static String latitude_name = "Latitude";
072 public static String trackDim_name = "TrackDim";
073 public static String vertDim_name = "VertDim";
074 public static String array_name = "array_name";
075 public static String profileTime_name = "ProfileTime";
076 public static String profileTime_unit = "ProfileTime_unit";
077 public static String altitude_unit = "altitude_unit";
078 public static String sfcElev_name = "SurfaceElev";
079 public static String range_name = "range_name";
080 public static String scale_name = "scale_name";
081 public static String offset_name = "offset_name";
082 public static String fill_value_name = "fill_value_name";
083 public static String valid_range = "valid_range";
084 public static String ancillary_file_name = "ancillary_file";
085 static String product_name = "product_name";
086
087 String[] rangeName_s = null;
088 Class[] arrayType_s = null;
089 Unit[] rangeUnit_s = new Unit[] {null};
090
091 RealType track = RealType.getRealType(trackDim_name);
092 RealType vert = RealType.getRealType(vertDim_name);
093 RealType[] domainRealTypes = new RealType[2];
094
095 RealType vertLocType;
096 RealType trackTimeType;
097
098 int track_idx = -1;
099 int vert_idx = -1;
100 int range_rank = -1;
101
102 int track_tup_idx;
103 int vert_tup_idx;
104
105 boolean isVertDimAlt = true;
106
107 CoordinateSystem cs = null;
108
109 public static HashMap getEmptySubset() {
110 HashMap<String, double[]> subset = new HashMap<String, double[]>();
111 subset.put(trackDim_name, new double[3]);
112 subset.put(vertDim_name, new double[3]);
113 return subset;
114 }
115
116 public static HashMap getEmptyMetadataTable() {
117 HashMap<String, String> metadata = new HashMap<String, String>();
118 metadata.put(array_name, null);
119 metadata.put(trackDim_name, null);
120 metadata.put(vertDim_name, null);
121 metadata.put(longitude_name, null);
122 metadata.put(latitude_name, null);
123 metadata.put(profileTime_name, null);
124 metadata.put(profileTime_unit, null);
125 metadata.put(altitude_unit, null);
126 metadata.put(sfcElev_name, null);
127 metadata.put(scale_name, null);
128 metadata.put(offset_name, null);
129 metadata.put(fill_value_name, null);
130 /*
131 metadata.put(range_name, null);
132 metadata.put(range_unit, null);
133 metadata.put(valid_range, null);
134 */
135 return metadata;
136 }
137
138 public ProfileAlongTrack() {
139 }
140
141 public ProfileAlongTrack(MultiDimensionReader reader, HashMap metadata) {
142 this(reader, metadata, true);
143 }
144
145 public ProfileAlongTrack(MultiDimensionReader reader, HashMap metadata, boolean isVertDimAlt) {
146 super(reader, metadata);
147 this.isVertDimAlt = isVertDimAlt;
148 this.init();
149 }
150
151
152 private void init() {
153 for (int k=0; k<array_rank;k++) {
154 if ( ((String)metadata.get(trackDim_name)).equals(array_dim_names[k]) ) {
155 track_idx = k;
156 }
157 if ( ((String)metadata.get(vertDim_name)).equals(array_dim_names[k]) ) {
158 vert_idx = k;
159 }
160 }
161
162 int[] lengths = new int[2];
163
164 if (track_idx < vert_idx) {
165 domainRealTypes[0] = vert;
166 domainRealTypes[1] = track;
167 track_tup_idx = 1;
168 vert_tup_idx = 0;
169 lengths[0] = array_dim_lengths[vert_idx];
170 lengths[1] = array_dim_lengths[track_idx];
171 }
172 else {
173 domainRealTypes[0] = track;
174 domainRealTypes[1] = vert;
175 track_tup_idx = 0;
176 vert_tup_idx = 1;
177 lengths[0] = array_dim_lengths[track_idx];
178 lengths[1] = array_dim_lengths[vert_idx];
179 }
180
181 TrackLen = array_dim_lengths[track_idx];
182 VertLen = array_dim_lengths[vert_idx];
183
184 String rangeName = null;
185 if (metadata.get("range_name") != null) {
186 rangeName = (String)metadata.get("range_name");
187 }
188 else {
189 rangeName = (String)metadata.get("array_name");
190 }
191 rangeType = RealType.getRealType(rangeName, rangeUnit_s[0]);
192
193 try {
194 rangeProcessor = RangeProcessor.createRangeProcessor(reader, metadata);
195 }
196 catch (Exception e) {
197 System.out.println("RangeProcessor failed to create");
198 e.printStackTrace();
199 }
200
201 try {
202 if (isVertDimAlt) {
203 vertLocs = getVertBinAltitude();
204 }
205 vertLocType = makeVertLocType();
206 trackTimes = getTrackTimes();
207 trackTimeType = makeTrackTimeType();
208 trackLongitude = getTrackLongitude();
209 trackLatitude = getTrackLatitude();
210 }
211 catch (Exception e) {
212 System.out.println(e);
213 }
214
215 }
216
217 public int getTrackLength() {
218 return TrackLen;
219 }
220
221 public int getVertLength() {
222 return VertLen;
223 }
224
225 public int getVertIdx() {
226 return vert_idx;
227 }
228
229 public int getTrackIdx() {
230 return track_idx;
231 }
232
233 public int getVertTupIdx() {
234 return vert_tup_idx;
235 }
236
237 public int getTrackTupIdx() {
238 return track_tup_idx;
239 }
240
241 public Set makeDomain(Object subset) throws Exception {
242 double[] first = new double[2];
243 double[] last = new double[2];
244 int[] length = new int[2];
245
246 HashMap<String, double[]> domainSubset = new HashMap<String, double[]>();
247 domainSubset.put(trackDim_name, (double[]) ((HashMap)subset).get(trackDim_name));
248 domainSubset.put(vertDim_name, (double[]) ((HashMap)subset).get(vertDim_name));
249
250 for (int kk=0; kk<2; kk++) {
251 RealType rtype = domainRealTypes[kk];
252 double[] coords = (double[]) ((HashMap)subset).get(rtype.getName());
253 first[kk] = coords[0];
254 last[kk] = coords[1];
255 length[kk] = (int) ((last[kk] - first[kk])/coords[2] + 1);
256 last[kk] = first[kk]+coords[2]*(length[kk]-1);
257 }
258 Linear2DSet domainSet = new Linear2DSet(first[0], last[0], length[0], first[1], last[1], length[1]);
259 final Linear1DSet[] lin1DSet_s = new Linear1DSet[] {domainSet.getLinear1DComponent(0),
260 domainSet.getLinear1DComponent(1)};
261
262 float[] new_altitudes = new float[length[vert_tup_idx]];
263 float[] new_times = new float[length[track_tup_idx]];
264
265 int track_start = (int) first[track_tup_idx];
266 int vert_start = (int) first[vert_tup_idx];
267 int vert_skip = (int) ((double[]) ((HashMap)subset).get(vertDim_name))[2];
268 int track_skip = (int) ((double[]) ((HashMap)subset).get(trackDim_name))[2];
269 for (int k=0; k<new_altitudes.length; k++) {
270 new_altitudes[k] = vertLocs[vert_start+(k*vert_skip)];
271 }
272
273 for (int k=0; k<new_times.length; k++) {
274 new_times[k] = trackTimes[track_start+(k*track_skip)];
275 }
276
277 final Gridded1DSet alt_set = new Gridded1DSet(vertLocType, new float[][] {new_altitudes}, new_altitudes.length);
278 final Gridded1DSet time_set = new Gridded1DSet(trackTimeType, new float[][] {new_times}, new_times.length);
279 final float vert_offset = (float) first[vert_tup_idx];
280 final float track_offset = (float) first[track_tup_idx];
281
282 RealTupleType reference = new RealTupleType(vertLocType, trackTimeType);
283
284 CoordinateSystem cs = null;
285
286 try {
287 cs = new CoordinateSystem(reference, null) {
288 public float[][] toReference(float[][] vals) throws VisADException {
289 int[] indexes = lin1DSet_s[0].valueToIndex(new float[][] {vals[0]});
290 for (int k=0; k<vals[0].length;k++) {
291 //-indexes[k] = (int) (vals[vert_tup_idx][k] - vert_offset); ?
292 }
293 float[][] alts = alt_set.indexToValue(indexes);
294
295 indexes = lin1DSet_s[1].valueToIndex(new float[][] {vals[1]});
296 for (int k=0; k<vals[0].length;k++) {
297 //-indexes[k] = (int) (vals[track_tup_idx][k] - track_offset); ?
298 }
299 float[][] times = time_set.indexToValue(indexes);
300
301 return new float[][] {alts[0], times[0]};
302 }
303 public float[][] fromReference(float[][] vals) throws VisADException {
304 int[] indexes = alt_set.valueToIndex(new float[][] {vals[vert_tup_idx]});
305 float[][] vert_coords = lin1DSet_s[vert_tup_idx].indexToValue(indexes);
306 indexes = time_set.valueToIndex(new float[][] {vals[track_tup_idx]});
307 float[][] track_coords = lin1DSet_s[track_tup_idx].indexToValue(indexes);
308 return new float[][] {vert_coords[0], track_coords[0]};
309 }
310 public double[][] toReference(double[][] vals) throws VisADException {
311 return Set.floatToDouble(toReference(Set.doubleToFloat(vals)));
312 }
313 public double[][] fromReference(double[][] vals) throws VisADException {
314 return Set.floatToDouble(fromReference(Set.doubleToFloat(vals)));
315 }
316 public boolean equals(Object obj) {
317 return true;
318 }
319 };
320 }
321 catch (Exception e) {
322 }
323
324 RealTupleType domainTupType = new RealTupleType(domainRealTypes[0], domainRealTypes[1], cs, null);
325 domainSet = new Linear2DSet(domainTupType, first[0], last[0], length[0], first[1], last[1], length[1]);
326
327 return domainSet;
328 }
329
330 public FunctionType getMathType() {
331 return null;
332 }
333
334 public RealType[] getDomainRealTypes() {
335 return domainRealTypes;
336 }
337
338 public HashMap getDefaultSubset() {
339 HashMap subset = ProfileAlongTrack.getEmptySubset();
340
341 double[] coords = (double[])subset.get("TrackDim");
342 coords[0] = 20000.0;
343 coords[1] = (TrackLen - 15000.0) - 1;
344 //-coords[2] = 30.0;
345 coords[2] = 5.0;
346 subset.put("TrackDim", coords);
347
348 coords = (double[])subset.get("VertDim");
349 coords[0] = 98.0;
350 coords[1] = (VertLen) - 1;
351 coords[2] = 2.0;
352 subset.put("VertDim", coords);
353 return subset;
354 }
355
356 public int[] getTrackRangeInsideLonLatRect(double minLat, double maxLat, double minLon, double maxLon) {
357 int nn = 100;
358 int skip = TrackLen/nn;
359 double lon;
360 double lat;
361
362 int idx = 0;
363 while (idx < TrackLen) {
364 lon = (double)trackLongitude[idx];
365 lat = (double)trackLatitude[idx];
366 if (((lon > minLon) && (lon < maxLon)) && ((lat > minLat)&&(lat < maxLat))) break;
367 idx += skip;
368 }
369 if (idx > TrackLen-1) idx = TrackLen-1;
370 if (idx == TrackLen-1) return new int[] {-1,-1};
371
372 int low_idx = idx;
373 while (low_idx > 0) {
374 lon = (double)trackLongitude[low_idx];
375 lat = (double)trackLatitude[low_idx];
376 if (((lon > minLon) && (lon < maxLon)) && ((lat > minLat)&&(lat < maxLat))) {
377 low_idx -= 1;
378 continue;
379 }
380 else {
381 break;
382 }
383 }
384
385 int hi_idx = idx;
386 while (hi_idx < TrackLen-1) {
387 lon = (double)trackLongitude[hi_idx];
388 lat = (double)trackLatitude[hi_idx];
389 if (((lon > minLon) && (lon < maxLon)) && ((lat > minLat)&&(lat < maxLat))) {
390 hi_idx += 1;
391 continue;
392 }
393 else {
394 break;
395 }
396 }
397 return new int[] {low_idx, hi_idx};
398 }
399
400 public HashMap getSubsetFromLonLatRect(HashMap subset, double minLat, double maxLat, double minLon, double maxLon) {
401 double[] coords = (double[])subset.get("TrackDim");
402 int[] idxs = getTrackRangeInsideLonLatRect(minLat, maxLat, minLon, maxLon);
403 coords[0] = (double) idxs[0];
404 coords[1] = (double) idxs[1];
405 if ((coords[0] == -1) || (coords[1] == -1)) return null;
406 return subset;
407 }
408
409 public HashMap getSubsetFromLonLatRect(HashMap subset, double minLat, double maxLat, double minLon, double maxLon,
410 int xStride, int yStride, int zStride) {
411
412 double[] coords = (double[])subset.get("TrackDim");
413 int[] idxs = getTrackRangeInsideLonLatRect(minLat, maxLat, minLon, maxLon);
414 coords[0] = (double) idxs[0];
415 coords[1] = (double) idxs[1];
416 if ((coords[0] == -1) || (coords[1] == -1)) return null;
417 if (xStride > 0) {
418 coords[2] = xStride;
419 }
420
421 coords = (double[])subset.get("VertDim");
422 if (yStride > 0) {
423 coords[2] = yStride;
424 }
425 return subset;
426 }
427
428 public HashMap getSubsetFromLonLatRect(double minLat, double maxLat, double minLon, double maxLon) {
429 return getSubsetFromLonLatRect(getDefaultSubset(), minLat, maxLat, minLon, maxLon);
430 }
431
432 public HashMap getSubsetFromLonLatRect(double minLat, double maxLat, double minLon, double maxLon,
433 int xStride, int yStride, int zStride) {
434
435 return getSubsetFromLonLatRect(getDefaultSubset(), minLat, maxLat, minLon, maxLon, xStride, yStride, zStride);
436 }
437
438 public abstract float[] getVertBinAltitude() throws Exception;
439 public abstract float[] getTrackTimes() throws Exception;
440 public abstract RealType makeVertLocType() throws Exception;
441 public abstract RealType makeTrackTimeType() throws Exception;
442 public abstract float[] getTrackLongitude() throws Exception;
443 public abstract float[] getTrackLatitude() throws Exception;
444
445 public static float[] medianFilter(float[] A, int lenx, int leny, int window_lenx, int window_leny)
446 throws VisADException {
447 float[] result = new float[A.length];
448 float[] window = new float[window_lenx*window_leny];
449 float[] new_window = new float[window_lenx*window_leny];
450 int[] sort_indexes = new int[window_lenx*window_leny];
451
452 int a_idx;
453 int w_idx;
454
455 int w_lenx = window_lenx/2;
456 int w_leny = window_leny/2;
457
458 int lo;
459 int hi;
460 int ww_jj;
461 int ww_ii;
462 int cnt;
463
464 for (int j=0; j<leny; j++) {
465 for (int i=0; i<lenx; i++) {
466 a_idx = j*lenx + i;
467 cnt = 0;
468 for (int w_j=-w_leny; w_j<w_leny; w_j++) {
469 for (int w_i=-w_lenx; w_i<w_lenx; w_i++) {
470 ww_jj = w_j + j;
471 ww_ii = w_i + i;
472 w_idx = (w_j+w_leny)*window_lenx + (w_i+w_lenx);
473 if ((ww_jj >= 0) && (ww_ii >=0) && (ww_jj < leny) && (ww_ii < lenx)) {
474 window[cnt] = A[ww_jj*lenx+ww_ii];
475 cnt++;
476 }
477 }
478 }
479 System.arraycopy(window, 0, new_window, 0, cnt);
480 //-sort_indexes = QuickSort.sort(new_window, sort_indexes);
481 sort_indexes = QuickSort.sort(new_window);
482 result[a_idx] = new_window[cnt/2];
483 }
484 }
485 return result;
486 }
487
488 }