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