001 /* 002 * $Id: SwathNavigation.java,v 1.17 2012/02/19 17:35:42 davep Exp $ 003 * 004 * This file is part of McIDAS-V 005 * 006 * Copyright 2007-2012 007 * Space Science and Engineering Center (SSEC) 008 * University of Wisconsin - Madison 009 * 1225 W. Dayton Street, Madison, WI 53706, USA 010 * https://www.ssec.wisc.edu/mcidas 011 * 012 * All Rights Reserved 013 * 014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 015 * some McIDAS-V source code is based on IDV and VisAD source code. 016 * 017 * McIDAS-V is free software; you can redistribute it and/or modify 018 * it under the terms of the GNU Lesser Public License as published by 019 * the Free Software Foundation; either version 3 of the License, or 020 * (at your option) any later version. 021 * 022 * McIDAS-V is distributed in the hope that it will be useful, 023 * but WITHOUT ANY WARRANTY; without even the implied warranty of 024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 025 * GNU Lesser Public License for more details. 026 * 027 * You should have received a copy of the GNU Lesser Public License 028 * along with this program. If not, see http://www.gnu.org/licenses. 029 */ 030 031 package edu.wisc.ssec.mcidasv.data.hydra; 032 033 import visad.Set; 034 import visad.Gridded2DSet; 035 import visad.Gridded2DDoubleSet; 036 import visad.Linear2DSet; 037 import visad.CoordinateSystem; 038 import visad.GridCoordinateSystem; 039 import visad.RealTupleType; 040 import java.util.HashMap; 041 042 public class SwathNavigation implements Navigation { 043 044 public static SwathNavigation createNavigation(SwathAdapter swathAdapter) throws Exception { 045 String product_name = null; 046 SwathNavigation swathNav = null; 047 048 product_name = (String) ((HashMap)swathAdapter.getMetadata()).get(SwathAdapter.product_name); 049 050 if (product_name == null) { 051 swathNav = new SwathNavigation(swathAdapter); 052 } 053 else if (product_name == "IASI_L1C_xxx") { 054 swathNav = new IASI_L1C_LonLatNavigation(swathAdapter); 055 } 056 else if (product_name == "CrIS_SDR") { 057 swathNav = new CrIS_SDR_LonLatNavigation(swathAdapter); 058 } 059 else { 060 swathNav = new SwathNavigation(swathAdapter); 061 } 062 063 return swathNav; 064 } 065 066 int geo_track_idx; 067 int geo_xtrack_idx; 068 int geoTrackLen; 069 int geoXTrackLen; 070 071 SwathAdapter swathAdapter; 072 MultiDimensionReader reader; 073 String lon_array_name; 074 String lat_array_name; 075 int[] idx_order = new int[2]; 076 float ratio = 1; 077 float track_ratio = 1; 078 float xtrack_ratio = 1; 079 double track_offset = 0; 080 double xtrack_offset = 0; 081 int track_idx; 082 int xtrack_idx; 083 int[] geo_stride = new int[2]; 084 int[] geo_count = new int[2]; 085 int[] geo_start = new int[2]; 086 087 String scale_name = "SCALE_NAME"; 088 String offset_name = "OFFSET_NAME"; 089 String fillValue_name = "_FILLVALUE"; 090 091 092 int numDims = 2; 093 094 Class type; 095 096 public SwathNavigation(SwathAdapter swathAdapter) throws Exception { 097 098 HashMap metadata = (HashMap) swathAdapter.getMetadata(); 099 reader = swathAdapter.getReader(); 100 this.swathAdapter = swathAdapter; 101 track_idx = swathAdapter.track_idx; 102 xtrack_idx = swathAdapter.xtrack_idx; 103 104 lon_array_name = (String)metadata.get(SwathAdapter.lon_array_name); 105 lat_array_name = (String)metadata.get(SwathAdapter.lat_array_name); 106 107 String[] lon_dim_names = null; 108 String[] lat_dim_names = null; 109 110 String[] lonDimNames = (String[]) metadata.get(SwathAdapter.lon_array_dimension_names); 111 String[] latDimNames = (String[]) metadata.get(SwathAdapter.lat_array_dimension_names); 112 113 if (lonDimNames != null) { 114 lon_dim_names = lonDimNames; 115 lat_dim_names = latDimNames; 116 } 117 else { 118 lon_dim_names = reader.getDimensionNames(lon_array_name); 119 lat_dim_names = reader.getDimensionNames(lat_array_name); 120 } 121 122 int[] lon_dim_lengths = reader.getDimensionLengths(lon_array_name); 123 int[] lat_dim_lengths = reader.getDimensionLengths(lat_array_name); 124 125 numDims = lon_dim_lengths.length; 126 geo_stride = new int[numDims]; 127 geo_count = new int[numDims]; 128 geo_start = new int[numDims]; 129 130 131 String geo_track_name = (String) metadata.get(SwathAdapter.geo_track_name); 132 String geo_xtrack_name = (String) metadata.get(SwathAdapter.geo_xtrack_name); 133 134 for (int k=0; k<numDims;k++) { 135 if ( geo_track_name.equals(lon_dim_names[k]) ) { 136 geo_track_idx = k; 137 } 138 if ( geo_xtrack_name.equals(lon_dim_names[k]) ) { 139 geo_xtrack_idx = k; 140 } 141 } 142 143 if (geo_track_idx < geo_xtrack_idx) { 144 idx_order[0] = geo_xtrack_idx; 145 idx_order[1] = geo_track_idx; 146 } 147 else { 148 idx_order[0] = geo_track_idx; 149 idx_order[1] = geo_xtrack_idx; 150 } 151 152 geoTrackLen = lon_dim_lengths[geo_track_idx]; 153 geoXTrackLen = lon_dim_lengths[geo_xtrack_idx]; 154 155 String str = (String) metadata.get(SwathAdapter.geo_track_skip_name); 156 157 if (str != null) { 158 track_ratio = (float) Double.parseDouble(str); 159 ratio = track_ratio; 160 } 161 str = (String) metadata.get(SwathAdapter.geo_xtrack_skip_name); 162 if (str != null) { 163 xtrack_ratio = (float) Double.parseDouble(str); 164 } 165 str = (String) metadata.get(SwathAdapter.geo_track_offset_name); 166 if (str != null) { 167 track_offset = Double.parseDouble(str); 168 } 169 str = (String) metadata.get(SwathAdapter.geo_xtrack_offset_name); 170 if (str != null) { 171 xtrack_offset = Double.parseDouble(str); 172 } 173 174 str = (String) metadata.get(SwathAdapter.geo_scale_name); 175 if (str != null) { 176 scale_name = str; 177 } 178 179 str = (String) metadata.get(SwathAdapter.geo_offset_name); 180 if (str != null) { 181 offset_name = str; 182 } 183 184 str = (String) metadata.get(SwathAdapter.geo_fillValue_name); 185 if (str != null) { 186 fillValue_name = str; 187 } 188 189 type = reader.getArrayType(lon_array_name); 190 } 191 192 public CoordinateSystem getVisADCoordinateSystem(Linear2DSet domainSet, Object domainSubset) throws Exception 193 { 194 Subset select = swathAdapter.getIndexes((HashMap)domainSubset); 195 196 double[] track_coords = (double[]) ((HashMap)domainSubset).get(SwathAdapter.track_name); 197 double[] xtrack_coords = (double[]) ((HashMap)domainSubset).get(SwathAdapter.xtrack_name); 198 199 int[] stride = new int[numDims]; 200 stride[geo_track_idx] = (int) track_coords[2]; 201 stride[geo_xtrack_idx] = (int) xtrack_coords[2]; 202 203 204 if (numDims > 2) { // initialize geo arrays, then recompute xtrack/track dimensions below 205 if (numDims == select.getRank()) { 206 int[] start = select.getStart(); 207 int[] count = select.getCount(); 208 stride = select.getStride(); 209 for (int i=0; i<numDims; i++) { 210 geo_start[i] = start[i]; 211 geo_count[i] = count[i]; 212 geo_stride[i] = stride[i]; 213 } 214 } 215 else { 216 geo_start[geo_track_idx] = (int) track_coords[0]; 217 geo_start[geo_xtrack_idx] = (int) xtrack_coords[0]; 218 geo_count[geo_track_idx] = (int) ((track_coords[1] - track_coords[0])/track_coords[2] + 1f); 219 geo_count[geo_xtrack_idx] = (int) ((xtrack_coords[1] - xtrack_coords[0])/xtrack_coords[2] + 1f); 220 } 221 } 222 223 224 if (ratio/(float)stride[0] <= 1) { 225 geo_stride[geo_track_idx] = Math.round((1f/(track_ratio/((float)stride[geo_track_idx])))); 226 geo_stride[geo_xtrack_idx] = Math.round((1f/(xtrack_ratio/((float)stride[geo_xtrack_idx])))); 227 } 228 else { 229 geo_stride[geo_track_idx] = 1; 230 geo_stride[geo_xtrack_idx] = 1; 231 } 232 233 int geo_track_start = (int) Math.ceil((track_coords[0] - track_offset)/track_ratio); 234 int geo_xtrack_start = (int) Math.ceil((xtrack_coords[0] - xtrack_offset)/xtrack_ratio); 235 236 int geo_track_end = (int) ((track_coords[1] - track_offset)/((double)track_ratio)); 237 int geo_xtrack_end = (int) ((xtrack_coords[1] - xtrack_offset)/((double)xtrack_ratio)); 238 239 geo_count[geo_track_idx] = (int) ((geo_track_end - geo_track_start)/geo_stride[geo_track_idx]) + 1; 240 geo_count[geo_xtrack_idx] = (int) ((geo_xtrack_end - geo_xtrack_start)/geo_stride[geo_xtrack_idx]) + 1; 241 242 geo_track_end = geo_track_start + (geo_count[geo_track_idx]-1)*geo_stride[geo_track_idx]; 243 geo_xtrack_end = geo_xtrack_start + (geo_count[geo_xtrack_idx]-1)*geo_stride[geo_xtrack_idx]; 244 245 geo_start[geo_track_idx] = geo_track_start; 246 geo_start[geo_xtrack_idx] = geo_xtrack_start; 247 248 //-- convert back track/xtrack coords: 249 int new_track_start = (int) (geo_track_start*track_ratio + (float)track_offset); 250 int new_xtrack_start = (int) (geo_xtrack_start*xtrack_ratio + (float)xtrack_offset); 251 int new_track_end = (int) (geo_track_end*track_ratio + (float)track_offset); 252 int new_xtrack_end = (int) (geo_xtrack_end*xtrack_ratio + (float)xtrack_offset); 253 254 255 //- these must be only 2D (Swath dimensions) 256 double[] first = new double[2]; 257 double[] last = new double[2]; 258 int[] length = new int[2]; 259 260 int track_idx; 261 int xtrack_idx; 262 if (geo_track_idx < geo_xtrack_idx) { 263 track_idx = 1; 264 xtrack_idx = 0; 265 } else { 266 track_idx = 0; 267 xtrack_idx = 1; 268 } 269 270 first[track_idx] = new_track_start; 271 first[xtrack_idx] = new_xtrack_start; 272 last[track_idx] = new_track_end; 273 last[xtrack_idx] = new_xtrack_end; 274 length[track_idx] = (int) ((last[track_idx] - first[track_idx])/stride[geo_track_idx] + 1); 275 length[xtrack_idx] = (int) ((last[xtrack_idx] - first[xtrack_idx])/stride[geo_xtrack_idx] + 1); 276 277 domainSet = new Linear2DSet(first[0], last[0], length[0], first[1], last[1], length[1]); 278 279 Gridded2DSet gset = null; 280 281 gset = createInterpSet(); 282 283 CoordinateSystem cs = new LongitudeLatitudeCoordinateSystem(domainSet, gset); 284 285 return cs; 286 } 287 288 Gridded2DSet createInterpSet() throws Exception { 289 Gridded2DSet gset = null; 290 if (type == Float.TYPE) { 291 float[] lonValues = reader.getFloatArray(lon_array_name, geo_start, geo_count, geo_stride); 292 float[] latValues = reader.getFloatArray(lat_array_name, geo_start, geo_count, geo_stride); 293 294 gset = new Gridded2DSet(RealTupleType.SpatialEarth2DTuple, 295 new float[][] {lonValues, latValues}, 296 geo_count[idx_order[0]], geo_count[idx_order[1]], 297 null, null, null, false, false); 298 } 299 else if (type == Double.TYPE) { 300 double[] lonValues = reader.getDoubleArray(lon_array_name, geo_start, geo_count, geo_stride); 301 double[] latValues = reader.getDoubleArray(lat_array_name, geo_start, geo_count, geo_stride); 302 303 gset = new Gridded2DDoubleSet(RealTupleType.SpatialEarth2DTuple, 304 new double[][] {lonValues, latValues}, 305 geo_count[idx_order[0]], geo_count[idx_order[1]], 306 null, null, null, false); 307 } 308 else if (type == Short.TYPE) { 309 short[] values = reader.getShortArray(lon_array_name, geo_start, geo_count, geo_stride); 310 HashMap metadata = new HashMap(); 311 metadata.put(SwathAdapter.array_name, lon_array_name); 312 metadata.put(SwathAdapter.scale_name, scale_name); 313 metadata.put(SwathAdapter.offset_name, offset_name); 314 metadata.put(SwathAdapter.fill_value_name, fillValue_name); 315 RangeProcessor rangeProcessor = RangeProcessor.createRangeProcessor(reader, metadata); 316 float[] lonValues = rangeProcessor.processRange(values, null); 317 318 values = reader.getShortArray(lat_array_name, geo_start, geo_count, geo_stride); 319 metadata = new HashMap(); 320 metadata.put(SwathAdapter.array_name, lat_array_name); 321 metadata.put(SwathAdapter.scale_name, scale_name); 322 metadata.put(SwathAdapter.offset_name, offset_name); 323 metadata.put(SwathAdapter.fill_value_name, fillValue_name); 324 rangeProcessor = RangeProcessor.createRangeProcessor(reader, metadata); 325 float[] latValues = rangeProcessor.processRange(values, null); 326 327 328 gset = new Gridded2DSet(RealTupleType.SpatialEarth2DTuple, 329 new float[][] {lonValues, latValues}, 330 geo_count[idx_order[0]], geo_count[idx_order[1]], 331 null, null, null, false, false); 332 333 } 334 return gset; 335 } 336 337 338 339 public static Linear2DSet getNavigationDomain(double data_x_start, double data_x_stop, double data_x_stride, 340 double data_y_start, double data_y_stop, double data_y_stride, 341 double ratio_x, double ratio_y, 342 double offset_x, double offset_y, 343 int[] geo_start, int[] geo_count, int[] geo_stride) 344 throws Exception { 345 346 int geo_track_idx = 1; 347 int geo_xtrack_idx = 0; 348 double track_ratio = ratio_y; 349 double xtrack_ratio = ratio_x; 350 double track_offset = offset_y; 351 double xtrack_offset = offset_x; 352 353 double[] track_coords = new double[3]; 354 double[] xtrack_coords = new double[3]; 355 356 xtrack_coords[0] = data_x_start; 357 xtrack_coords[1] = data_x_stop; 358 track_coords[0] = data_y_start; 359 track_coords[1] = data_y_stop; 360 361 double[] stride = new double[2]; 362 stride[geo_track_idx] = data_y_stride; 363 stride[geo_xtrack_idx] = data_x_stride; 364 365 if (track_ratio/(float)stride[0] <= 1) { 366 geo_stride[geo_track_idx] = (int) Math.round((1/(track_ratio/(stride[1])))); 367 geo_stride[geo_xtrack_idx] = (int) Math.round((1/(xtrack_ratio/(stride[0])))); 368 } 369 else { 370 geo_stride[0] = 1; 371 geo_stride[1] = 1; 372 } 373 374 int geo_track_start = (int) Math.ceil((track_coords[0] - track_offset)/track_ratio); 375 int geo_xtrack_start = (int) Math.ceil((xtrack_coords[0] - xtrack_offset)/xtrack_ratio); 376 377 int geo_track_end = (int) ((track_coords[1] - track_offset)/((double)track_ratio)); 378 int geo_xtrack_end = (int) ((xtrack_coords[1] - xtrack_offset)/((double)xtrack_ratio)); 379 380 geo_count[geo_track_idx] = (int) ((geo_track_end - geo_track_start)/geo_stride[geo_track_idx]) + 1; 381 geo_count[geo_xtrack_idx] = (int) ((geo_xtrack_end - geo_xtrack_start)/geo_stride[geo_xtrack_idx]) + 1; 382 383 geo_track_end = geo_track_start + (geo_count[geo_track_idx]-1)*geo_stride[geo_track_idx]; 384 geo_xtrack_end = geo_xtrack_start + (geo_count[geo_xtrack_idx]-1)*geo_stride[geo_xtrack_idx]; 385 386 geo_start[geo_track_idx] = geo_track_start; 387 geo_start[geo_xtrack_idx] = geo_xtrack_start; 388 389 //-- convert back track/xtrack coords: 390 int new_track_start = (int) (geo_track_start*track_ratio + (float)track_offset); 391 int new_xtrack_start = (int) (geo_xtrack_start*xtrack_ratio + (float)xtrack_offset); 392 int new_track_end = (int) (geo_track_end*track_ratio + (float)track_offset); 393 int new_xtrack_end = (int) (geo_xtrack_end*xtrack_ratio + (float)xtrack_offset); 394 395 396 double[] first = new double[2]; 397 double[] last = new double[2]; 398 int[] length = new int[2]; 399 first[geo_track_idx] = new_track_start; 400 first[geo_xtrack_idx] = new_xtrack_start; 401 last[geo_track_idx] = new_track_end; 402 last[geo_xtrack_idx] = new_xtrack_end; 403 length[geo_track_idx] = (int) ((last[geo_track_idx] - first[geo_track_idx])/stride[geo_track_idx] + 1); 404 length[geo_xtrack_idx] = (int) ((last[geo_xtrack_idx] - first[geo_xtrack_idx])/stride[geo_xtrack_idx] + 1); 405 406 return new Linear2DSet(first[0], last[0], length[0], first[1], last[1], length[1]); 407 408 } 409 410 411 }