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 }