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.Set; 032 import visad.Gridded2DSet; 033 import visad.Gridded2DDoubleSet; 034 import visad.Linear2DSet; 035 import visad.CoordinateSystem; 036 import visad.GridCoordinateSystem; 037 import visad.RealTupleType; 038 import java.util.HashMap; 039 040 public class SwathNavigation implements Navigation { 041 042 public static SwathNavigation createNavigation(SwathAdapter swathAdapter) throws Exception { 043 String product_name = null; 044 SwathNavigation swathNav = null; 045 046 product_name = (String) ((HashMap)swathAdapter.getMetadata()).get(SwathAdapter.product_name); 047 048 if (product_name == null) { 049 swathNav = new SwathNavigation(swathAdapter); 050 } 051 else if (product_name == "IASI_L1C_xxx") { 052 swathNav = new IASI_L1C_LonLatNavigation(swathAdapter); 053 } 054 else if (product_name == "CrIS_SDR") { 055 swathNav = new CrIS_SDR_LonLatNavigation(swathAdapter); 056 } 057 else { 058 swathNav = new SwathNavigation(swathAdapter); 059 } 060 061 return swathNav; 062 } 063 064 int geo_track_idx; 065 int geo_xtrack_idx; 066 int geoTrackLen; 067 int geoXTrackLen; 068 069 SwathAdapter swathAdapter; 070 MultiDimensionReader reader; 071 String lon_array_name; 072 String lat_array_name; 073 int[] idx_order = new int[2]; 074 float ratio = 1; 075 float track_ratio = 1; 076 float xtrack_ratio = 1; 077 double track_offset = 0; 078 double xtrack_offset = 0; 079 int track_idx; 080 int xtrack_idx; 081 int[] geo_stride = new int[2]; 082 int[] geo_count = new int[2]; 083 int[] geo_start = new int[2]; 084 085 String scale_name = "SCALE_NAME"; 086 String offset_name = "OFFSET_NAME"; 087 String fillValue_name = "_FILLVALUE"; 088 089 090 int numDims = 2; 091 092 Class type; 093 094 public SwathNavigation(SwathAdapter swathAdapter) throws Exception { 095 096 HashMap metadata = (HashMap) swathAdapter.getMetadata(); 097 reader = swathAdapter.getReader(); 098 this.swathAdapter = swathAdapter; 099 track_idx = swathAdapter.track_idx; 100 xtrack_idx = swathAdapter.xtrack_idx; 101 102 lon_array_name = (String)metadata.get(SwathAdapter.lon_array_name); 103 lat_array_name = (String)metadata.get(SwathAdapter.lat_array_name); 104 105 String[] lon_dim_names = null; 106 String[] lat_dim_names = null; 107 108 String[] lonDimNames = (String[]) metadata.get(SwathAdapter.lon_array_dimension_names); 109 String[] latDimNames = (String[]) metadata.get(SwathAdapter.lat_array_dimension_names); 110 111 if (lonDimNames != null) { 112 lon_dim_names = lonDimNames; 113 lat_dim_names = latDimNames; 114 } 115 else { 116 lon_dim_names = reader.getDimensionNames(lon_array_name); 117 lat_dim_names = reader.getDimensionNames(lat_array_name); 118 } 119 120 int[] lon_dim_lengths = reader.getDimensionLengths(lon_array_name); 121 int[] lat_dim_lengths = reader.getDimensionLengths(lat_array_name); 122 123 numDims = lon_dim_lengths.length; 124 geo_stride = new int[numDims]; 125 geo_count = new int[numDims]; 126 geo_start = new int[numDims]; 127 128 129 String geo_track_name = (String) metadata.get(SwathAdapter.geo_track_name); 130 String geo_xtrack_name = (String) metadata.get(SwathAdapter.geo_xtrack_name); 131 132 for (int k=0; k<numDims;k++) { 133 if ( geo_track_name.equals(lon_dim_names[k]) ) { 134 geo_track_idx = k; 135 } 136 if ( geo_xtrack_name.equals(lon_dim_names[k]) ) { 137 geo_xtrack_idx = k; 138 } 139 } 140 141 if (geo_track_idx < geo_xtrack_idx) { 142 idx_order[0] = geo_xtrack_idx; 143 idx_order[1] = geo_track_idx; 144 } 145 else { 146 idx_order[0] = geo_track_idx; 147 idx_order[1] = geo_xtrack_idx; 148 } 149 150 geoTrackLen = lon_dim_lengths[geo_track_idx]; 151 geoXTrackLen = lon_dim_lengths[geo_xtrack_idx]; 152 153 String str = (String) metadata.get(SwathAdapter.geo_track_skip_name); 154 155 if (str != null) { 156 track_ratio = (float) Double.parseDouble(str); 157 ratio = track_ratio; 158 } 159 str = (String) metadata.get(SwathAdapter.geo_xtrack_skip_name); 160 if (str != null) { 161 xtrack_ratio = (float) Double.parseDouble(str); 162 } 163 str = (String) metadata.get(SwathAdapter.geo_track_offset_name); 164 if (str != null) { 165 track_offset = Double.parseDouble(str); 166 } 167 str = (String) metadata.get(SwathAdapter.geo_xtrack_offset_name); 168 if (str != null) { 169 xtrack_offset = Double.parseDouble(str); 170 } 171 172 str = (String) metadata.get(SwathAdapter.geo_scale_name); 173 if (str != null) { 174 scale_name = str; 175 } 176 177 str = (String) metadata.get(SwathAdapter.geo_offset_name); 178 if (str != null) { 179 offset_name = str; 180 } 181 182 str = (String) metadata.get(SwathAdapter.geo_fillValue_name); 183 if (str != null) { 184 fillValue_name = str; 185 } 186 187 type = reader.getArrayType(lon_array_name); 188 } 189 190 public CoordinateSystem getVisADCoordinateSystem(Linear2DSet domainSet, Object domainSubset) throws Exception 191 { 192 Subset select = swathAdapter.getIndexes((HashMap)domainSubset); 193 194 double[] track_coords = (double[]) ((HashMap)domainSubset).get(SwathAdapter.track_name); 195 double[] xtrack_coords = (double[]) ((HashMap)domainSubset).get(SwathAdapter.xtrack_name); 196 197 int[] stride = new int[numDims]; 198 stride[geo_track_idx] = (int) track_coords[2]; 199 stride[geo_xtrack_idx] = (int) xtrack_coords[2]; 200 201 202 if (numDims > 2) { // initialize geo arrays, then recompute xtrack/track dimensions below 203 if (numDims == select.getRank()) { 204 int[] start = select.getStart(); 205 int[] count = select.getCount(); 206 stride = select.getStride(); 207 for (int i=0; i<numDims; i++) { 208 geo_start[i] = start[i]; 209 geo_count[i] = count[i]; 210 geo_stride[i] = stride[i]; 211 } 212 } 213 else { 214 geo_start[geo_track_idx] = (int) track_coords[0]; 215 geo_start[geo_xtrack_idx] = (int) xtrack_coords[0]; 216 geo_count[geo_track_idx] = (int) ((track_coords[1] - track_coords[0])/track_coords[2] + 1f); 217 geo_count[geo_xtrack_idx] = (int) ((xtrack_coords[1] - xtrack_coords[0])/xtrack_coords[2] + 1f); 218 } 219 } 220 221 222 if (ratio/(float)stride[0] <= 1) { 223 geo_stride[geo_track_idx] = Math.round((1f/(track_ratio/((float)stride[geo_track_idx])))); 224 geo_stride[geo_xtrack_idx] = Math.round((1f/(xtrack_ratio/((float)stride[geo_xtrack_idx])))); 225 } 226 else { 227 geo_stride[geo_track_idx] = 1; 228 geo_stride[geo_xtrack_idx] = 1; 229 } 230 231 int geo_track_start = (int) Math.ceil((track_coords[0] - track_offset)/track_ratio); 232 int geo_xtrack_start = (int) Math.ceil((xtrack_coords[0] - xtrack_offset)/xtrack_ratio); 233 234 int geo_track_end = (int) ((track_coords[1] - track_offset)/((double)track_ratio)); 235 int geo_xtrack_end = (int) ((xtrack_coords[1] - xtrack_offset)/((double)xtrack_ratio)); 236 237 geo_count[geo_track_idx] = (int) ((geo_track_end - geo_track_start)/geo_stride[geo_track_idx]) + 1; 238 geo_count[geo_xtrack_idx] = (int) ((geo_xtrack_end - geo_xtrack_start)/geo_stride[geo_xtrack_idx]) + 1; 239 240 geo_track_end = geo_track_start + (geo_count[geo_track_idx]-1)*geo_stride[geo_track_idx]; 241 geo_xtrack_end = geo_xtrack_start + (geo_count[geo_xtrack_idx]-1)*geo_stride[geo_xtrack_idx]; 242 243 geo_start[geo_track_idx] = geo_track_start; 244 geo_start[geo_xtrack_idx] = geo_xtrack_start; 245 246 //-- convert back track/xtrack coords: 247 int new_track_start = (int) (geo_track_start*track_ratio + (float)track_offset); 248 int new_xtrack_start = (int) (geo_xtrack_start*xtrack_ratio + (float)xtrack_offset); 249 int new_track_end = (int) (geo_track_end*track_ratio + (float)track_offset); 250 int new_xtrack_end = (int) (geo_xtrack_end*xtrack_ratio + (float)xtrack_offset); 251 252 253 //- these must be only 2D (Swath dimensions) 254 double[] first = new double[2]; 255 double[] last = new double[2]; 256 int[] length = new int[2]; 257 258 int track_idx; 259 int xtrack_idx; 260 if (geo_track_idx < geo_xtrack_idx) { 261 track_idx = 1; 262 xtrack_idx = 0; 263 } else { 264 track_idx = 0; 265 xtrack_idx = 1; 266 } 267 268 first[track_idx] = new_track_start; 269 first[xtrack_idx] = new_xtrack_start; 270 last[track_idx] = new_track_end; 271 last[xtrack_idx] = new_xtrack_end; 272 length[track_idx] = (int) ((last[track_idx] - first[track_idx])/stride[geo_track_idx] + 1); 273 length[xtrack_idx] = (int) ((last[xtrack_idx] - first[xtrack_idx])/stride[geo_xtrack_idx] + 1); 274 275 domainSet = new Linear2DSet(first[0], last[0], length[0], first[1], last[1], length[1]); 276 277 Gridded2DSet gset = null; 278 279 gset = createInterpSet(); 280 281 CoordinateSystem cs = new LongitudeLatitudeCoordinateSystem(domainSet, gset); 282 283 return cs; 284 } 285 286 Gridded2DSet createInterpSet() throws Exception { 287 Gridded2DSet gset = null; 288 if (type == Float.TYPE) { 289 float[] lonValues = reader.getFloatArray(lon_array_name, geo_start, geo_count, geo_stride); 290 float[] latValues = reader.getFloatArray(lat_array_name, geo_start, geo_count, geo_stride); 291 292 gset = new Gridded2DSet(RealTupleType.SpatialEarth2DTuple, 293 new float[][] {lonValues, latValues}, 294 geo_count[idx_order[0]], geo_count[idx_order[1]], 295 null, null, null, false, false); 296 } 297 else if (type == Double.TYPE) { 298 double[] lonValues = reader.getDoubleArray(lon_array_name, geo_start, geo_count, geo_stride); 299 double[] latValues = reader.getDoubleArray(lat_array_name, geo_start, geo_count, geo_stride); 300 301 gset = new Gridded2DDoubleSet(RealTupleType.SpatialEarth2DTuple, 302 new double[][] {lonValues, latValues}, 303 geo_count[idx_order[0]], geo_count[idx_order[1]], 304 null, null, null, false); 305 } 306 else if (type == Short.TYPE) { 307 short[] values = reader.getShortArray(lon_array_name, geo_start, geo_count, geo_stride); 308 HashMap metadata = new HashMap(); 309 metadata.put(SwathAdapter.array_name, lon_array_name); 310 metadata.put(SwathAdapter.scale_name, scale_name); 311 metadata.put(SwathAdapter.offset_name, offset_name); 312 metadata.put(SwathAdapter.fill_value_name, fillValue_name); 313 RangeProcessor rangeProcessor = RangeProcessor.createRangeProcessor(reader, metadata); 314 float[] lonValues = rangeProcessor.processRange(values, null); 315 316 values = reader.getShortArray(lat_array_name, geo_start, geo_count, geo_stride); 317 metadata = new HashMap(); 318 metadata.put(SwathAdapter.array_name, lat_array_name); 319 metadata.put(SwathAdapter.scale_name, scale_name); 320 metadata.put(SwathAdapter.offset_name, offset_name); 321 metadata.put(SwathAdapter.fill_value_name, fillValue_name); 322 rangeProcessor = RangeProcessor.createRangeProcessor(reader, metadata); 323 float[] latValues = rangeProcessor.processRange(values, null); 324 325 326 gset = new Gridded2DSet(RealTupleType.SpatialEarth2DTuple, 327 new float[][] {lonValues, latValues}, 328 geo_count[idx_order[0]], geo_count[idx_order[1]], 329 null, null, null, false, false); 330 331 } 332 return gset; 333 } 334 335 336 337 public static Linear2DSet getNavigationDomain(double data_x_start, double data_x_stop, double data_x_stride, 338 double data_y_start, double data_y_stop, double data_y_stride, 339 double ratio_x, double ratio_y, 340 double offset_x, double offset_y, 341 int[] geo_start, int[] geo_count, int[] geo_stride) 342 throws Exception { 343 344 int geo_track_idx = 1; 345 int geo_xtrack_idx = 0; 346 double track_ratio = ratio_y; 347 double xtrack_ratio = ratio_x; 348 double track_offset = offset_y; 349 double xtrack_offset = offset_x; 350 351 double[] track_coords = new double[3]; 352 double[] xtrack_coords = new double[3]; 353 354 xtrack_coords[0] = data_x_start; 355 xtrack_coords[1] = data_x_stop; 356 track_coords[0] = data_y_start; 357 track_coords[1] = data_y_stop; 358 359 double[] stride = new double[2]; 360 stride[geo_track_idx] = data_y_stride; 361 stride[geo_xtrack_idx] = data_x_stride; 362 363 if (track_ratio/(float)stride[0] <= 1) { 364 geo_stride[geo_track_idx] = (int) Math.round((1/(track_ratio/(stride[1])))); 365 geo_stride[geo_xtrack_idx] = (int) Math.round((1/(xtrack_ratio/(stride[0])))); 366 } 367 else { 368 geo_stride[0] = 1; 369 geo_stride[1] = 1; 370 } 371 372 int geo_track_start = (int) Math.ceil((track_coords[0] - track_offset)/track_ratio); 373 int geo_xtrack_start = (int) Math.ceil((xtrack_coords[0] - xtrack_offset)/xtrack_ratio); 374 375 int geo_track_end = (int) ((track_coords[1] - track_offset)/((double)track_ratio)); 376 int geo_xtrack_end = (int) ((xtrack_coords[1] - xtrack_offset)/((double)xtrack_ratio)); 377 378 geo_count[geo_track_idx] = (int) ((geo_track_end - geo_track_start)/geo_stride[geo_track_idx]) + 1; 379 geo_count[geo_xtrack_idx] = (int) ((geo_xtrack_end - geo_xtrack_start)/geo_stride[geo_xtrack_idx]) + 1; 380 381 geo_track_end = geo_track_start + (geo_count[geo_track_idx]-1)*geo_stride[geo_track_idx]; 382 geo_xtrack_end = geo_xtrack_start + (geo_count[geo_xtrack_idx]-1)*geo_stride[geo_xtrack_idx]; 383 384 geo_start[geo_track_idx] = geo_track_start; 385 geo_start[geo_xtrack_idx] = geo_xtrack_start; 386 387 //-- convert back track/xtrack coords: 388 int new_track_start = (int) (geo_track_start*track_ratio + (float)track_offset); 389 int new_xtrack_start = (int) (geo_xtrack_start*xtrack_ratio + (float)xtrack_offset); 390 int new_track_end = (int) (geo_track_end*track_ratio + (float)track_offset); 391 int new_xtrack_end = (int) (geo_xtrack_end*xtrack_ratio + (float)xtrack_offset); 392 393 394 double[] first = new double[2]; 395 double[] last = new double[2]; 396 int[] length = new int[2]; 397 first[geo_track_idx] = new_track_start; 398 first[geo_xtrack_idx] = new_xtrack_start; 399 last[geo_track_idx] = new_track_end; 400 last[geo_xtrack_idx] = new_xtrack_end; 401 length[geo_track_idx] = (int) ((last[geo_track_idx] - first[geo_track_idx])/stride[geo_track_idx] + 1); 402 length[geo_xtrack_idx] = (int) ((last[geo_xtrack_idx] - first[geo_xtrack_idx])/stride[geo_xtrack_idx] + 1); 403 404 return new Linear2DSet(first[0], last[0], length[0], first[1], last[1], length[1]); 405 406 } 407 408 409 }