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 }