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 java.util.HashMap; 032 033 import visad.CoordinateSystem; 034 import visad.FunctionType; 035 import visad.Linear2DSet; 036 import visad.RealTupleType; 037 import visad.RealType; 038 import visad.Set; 039 import visad.Unit; 040 041 public class SwathAdapter extends MultiDimensionAdapter { 042 043 String nav_type = "Interp"; 044 boolean lon_lat_trusted = true; 045 046 private int TrackLen; 047 private int XTrackLen; 048 049 static String longitude_name = "Longitude"; 050 static String latitude_name = "Latitude"; 051 static String track_name = "Track"; 052 static String xtrack_name = "XTrack"; 053 static String geo_track_name = "geo_Track"; 054 static String geo_xtrack_name = "geo_XTrack"; 055 static String array_name = "array_name"; 056 static String array_dimension_names = "array_dimension_names"; 057 static String lon_array_name = "lon_array_name"; 058 static String lat_array_name = "lat_array_name"; 059 static String lon_array_dimension_names = "lon_array_dimension_names"; 060 static String lat_array_dimension_names = "lat_array_dimension_names"; 061 static String range_name = "range_name"; 062 static String product_name = "product_name"; 063 static String scale_name = "scale_name"; 064 static String offset_name = "offset_name"; 065 static String fill_value_name = "fill_value_name"; 066 static String geo_track_offset_name = "geoTrack_offset"; 067 static String geo_xtrack_offset_name = "geoXTrack_offset"; 068 static String geo_track_skip_name = "geoTrack_skip"; 069 static String geo_xtrack_skip_name = "geoXTrack_skip"; 070 static String geo_scale_name = "geo_scale_name"; 071 static String geo_offset_name = "geo_scale_name"; 072 static String geo_fillValue_name = "geo_fillValue_name"; 073 static String multiScaleDimensionIndex = "multiScaleDimensionIndex"; 074 075 String[] rangeName_s = null; 076 Class[] arrayType_s = null; 077 Unit[] rangeUnit_s = new Unit[] {null}; 078 079 String rangeName = null; 080 081 RealType track = RealType.getRealType(track_name); 082 RealType xtrack = RealType.getRealType(xtrack_name); 083 RealType[] domainRealTypes = new RealType[2]; 084 085 int track_idx = -1; 086 int xtrack_idx = -1; 087 int lon_track_idx = -1; 088 int lon_xtrack_idx = -1; 089 int lat_track_idx = -1; 090 int lat_xtrack_idx = -1; 091 int range_rank = -1; 092 093 int geo_track_offset = 0; 094 int geo_track_skip = 1; 095 int geo_xtrack_offset = 0; 096 int geo_xtrack_skip = 1; 097 098 int track_tup_idx; 099 int xtrack_tup_idx; 100 101 private SwathNavigation navigation; 102 103 private Linear2DSet swathDomain; 104 private Linear2DSet domainSet_save; 105 106 private Object last_subset; 107 108 int default_stride = 1; 109 110 public static HashMap getEmptySubset() { 111 HashMap<String, double[]> subset = new HashMap<String, double[]>(); 112 subset.put(track_name, new double[3]); 113 subset.put(xtrack_name, new double[3]); 114 return subset; 115 } 116 117 public static HashMap<String, Object> getEmptyMetadataTable() { 118 HashMap<String, Object> metadata = new HashMap<String, Object>(); 119 metadata.put(array_name, null); 120 metadata.put(array_dimension_names, null); 121 metadata.put(track_name, null); 122 metadata.put(xtrack_name, null); 123 metadata.put(geo_track_name, null); 124 metadata.put(geo_xtrack_name, null); 125 metadata.put(lon_array_name, null); 126 metadata.put(lat_array_name, null); 127 metadata.put(lon_array_dimension_names, null); 128 metadata.put(lat_array_dimension_names, null); 129 metadata.put(scale_name, null); 130 metadata.put(offset_name, null); 131 metadata.put(fill_value_name, null); 132 metadata.put(range_name, null); 133 metadata.put(product_name, null); 134 metadata.put(geo_track_offset_name, null); 135 metadata.put(geo_xtrack_offset_name, null); 136 metadata.put(geo_track_skip_name, null); 137 metadata.put(geo_xtrack_skip_name, null); 138 metadata.put(multiScaleDimensionIndex, null); 139 return metadata; 140 } 141 142 public SwathAdapter() { 143 144 } 145 146 public SwathAdapter(MultiDimensionReader reader, HashMap metadata) { 147 super(reader, metadata); 148 this.init(); 149 } 150 151 private void init() { 152 for (int k=0; k<array_rank;k++) { 153 if ( ((String)metadata.get(track_name)).equals(array_dim_names[k]) ) { 154 track_idx = k; 155 } 156 if ( ((String)metadata.get(xtrack_name)).equals(array_dim_names[k]) ) { 157 xtrack_idx = k; 158 } 159 } 160 161 int[] lengths = new int[2]; 162 163 if (track_idx < xtrack_idx) { 164 domainRealTypes[0] = xtrack; 165 domainRealTypes[1] = track; 166 lengths[0] = array_dim_lengths[xtrack_idx]; 167 lengths[1] = array_dim_lengths[track_idx]; 168 track_tup_idx = 1; 169 xtrack_tup_idx = 0; 170 } 171 else { 172 domainRealTypes[0] = track; 173 domainRealTypes[1] = xtrack; 174 lengths[0] = array_dim_lengths[track_idx]; 175 lengths[1] = array_dim_lengths[xtrack_idx]; 176 track_tup_idx = 0; 177 xtrack_tup_idx = 1; 178 } 179 180 TrackLen = array_dim_lengths[track_idx]; 181 XTrackLen = array_dim_lengths[xtrack_idx]; 182 183 setLengths(); 184 185 lengths[track_tup_idx] = TrackLen; 186 lengths[xtrack_tup_idx] = XTrackLen; 187 188 if (metadata.get(range_name) != null) { 189 rangeName = (String)metadata.get(range_name); 190 } 191 else { 192 rangeName = (String)metadata.get(array_name); 193 } 194 195 rangeType = RealType.getRealType(rangeName, rangeUnit_s[0]); 196 197 /** TODO could be a mis-match between supplied unit, and default 198 unit of an existing RealType with same name. */ 199 if (rangeType == null) { 200 rangeType = RealType.getRealType(rangeName); 201 } 202 203 try { 204 RangeProcessor rangeProcessor = RangeProcessor.createRangeProcessor(reader, metadata); 205 if ( !(reader instanceof GranuleAggregation) ) { 206 setRangeProcessor(rangeProcessor); 207 } 208 } 209 catch (Exception e) { 210 System.out.println("RangeProcessor failed to create"); 211 e.printStackTrace(); 212 } 213 214 try { 215 navigation = SwathNavigation.createNavigation(this); 216 RealTupleType domainTupType = new RealTupleType(domainRealTypes[0], domainRealTypes[1]); 217 swathDomain = new Linear2DSet(domainTupType, 0, lengths[0]-1, lengths[0], 0, lengths[1]-1, lengths[1]); 218 } 219 catch (Exception e) { 220 System.out.println("Navigation failed to create"); 221 e.printStackTrace(); 222 } 223 224 if (XTrackLen <= 256) { 225 default_stride = 1; 226 } 227 else { 228 default_stride = (int) XTrackLen/256; 229 } 230 231 /* force default stride even */ 232 if (default_stride > 1) { 233 default_stride = (default_stride/2)*2; 234 } 235 236 } 237 238 protected void setLengths() { 239 } 240 241 public int getTrackLength() { 242 return TrackLen; 243 } 244 245 public int getXTrackLength() { 246 return XTrackLen; 247 } 248 249 public SwathNavigation getNavigation() { 250 return navigation; 251 } 252 253 protected void setTrackLength(int len) { 254 TrackLen = len; 255 } 256 257 protected void setXTrackLength(int len) { 258 XTrackLen = len; 259 } 260 261 public Set makeDomain(Object subset) throws Exception { 262 if (last_subset != null) { 263 if (spatialEquals(last_subset, subset)) return domainSet_save; 264 } 265 266 double[] first = new double[2]; 267 double[] last = new double[2]; 268 int[] length = new int[2]; 269 270 HashMap<String, double[]> domainSubset = new HashMap<String, double[]>(); 271 domainSubset.put(track_name, (double[]) ((HashMap)subset).get(track_name)); 272 domainSubset.put(xtrack_name, (double[]) ((HashMap)subset).get(xtrack_name)); 273 274 domainSubset.put(track_name, new double[] {0,0,0}); 275 domainSubset.put(xtrack_name, new double[] {0,0,0}); 276 277 // compute coordinates for the Linear2D domainSet 278 for (int kk=0; kk<2; kk++) { 279 RealType rtype = domainRealTypes[kk]; 280 String name = rtype.getName(); 281 double[] coords = (double[]) ((HashMap)subset).get(name); 282 coords[0] = Math.ceil(coords[0]); 283 coords[1] = Math.floor(coords[1]); 284 first[kk] = coords[0]; 285 last[kk] = coords[1]; 286 length[kk] = (int) ((last[kk] - first[kk])/coords[2] + 1); 287 last[kk] = first[kk] + (length[kk]-1)*coords[2]; 288 289 double[] new_coords = domainSubset.get(name); 290 new_coords[0] = first[kk]; 291 new_coords[1] = last[kk]; 292 new_coords[2] = coords[2]; 293 } 294 last_subset = subset; 295 296 Linear2DSet domainSet = new Linear2DSet(first[0], last[0], length[0], first[1], last[1], length[1]); 297 //CoordinateSystem cs = navigation.getVisADCoordinateSystem(domainSet, domainSubset); 298 CoordinateSystem cs = navigation.getVisADCoordinateSystem(domainSet, subset); 299 300 RealTupleType domainTupType = new RealTupleType(domainRealTypes[0], domainRealTypes[1], cs, null); 301 domainSet_save = new Linear2DSet(domainTupType, first[0], last[0], length[0], first[1], last[1], length[1]); 302 303 return domainSet_save; 304 } 305 306 public String getArrayName() { 307 return rangeName; 308 } 309 310 public FunctionType getMathType() { 311 return null; 312 } 313 314 public RealType[] getDomainRealTypes() { 315 return domainRealTypes; 316 } 317 318 public Linear2DSet getSwathDomain() { 319 return swathDomain; 320 } 321 322 public boolean spatialEquals(Object last_subset, Object subset) { 323 double[] last_coords = (double[]) ((HashMap)last_subset).get(track_name); 324 double[] coords = (double[]) ((HashMap)subset).get(track_name); 325 326 for (int k=0; k<coords.length; k++) { 327 if (coords[k] != last_coords[k]) { 328 return false; 329 } 330 } 331 332 last_coords = (double[]) ((HashMap)last_subset).get(xtrack_name); 333 coords = (double[]) ((HashMap)subset).get(xtrack_name); 334 335 for (int k=0; k<coords.length; k++) { 336 if (coords[k] != last_coords[k]) { 337 return false; 338 } 339 } 340 341 return true; 342 } 343 344 public void setDefaultStride(int stride) { 345 default_stride = stride; 346 } 347 348 public HashMap getDefaultSubset() { 349 HashMap subset = SwathAdapter.getEmptySubset(); 350 351 double[] coords = (double[])subset.get("Track"); 352 coords[0] = 0.0; 353 coords[1] = TrackLen - 1; 354 coords[2] = (double)default_stride; 355 subset.put("Track", coords); 356 357 coords = (double[])subset.get("XTrack"); 358 coords[0] = 0.0; 359 coords[1] = XTrackLen - 1 ; 360 coords[2] = (double)default_stride; 361 subset.put("XTrack", coords); 362 return subset; 363 } 364 }