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