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