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 }