001 /*
002 * $Id: SwathAdapter.java,v 1.23 2012/03/29 20:21:29 rink 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 java.util.HashMap;
034
035 import visad.CoordinateSystem;
036 import visad.FunctionType;
037 import visad.Linear2DSet;
038 import visad.RealTupleType;
039 import visad.RealType;
040 import visad.Set;
041 import visad.Unit;
042
043 public class SwathAdapter extends MultiDimensionAdapter {
044
045 String nav_type = "Interp";
046 boolean lon_lat_trusted = true;
047
048 private int TrackLen;
049 private int XTrackLen;
050
051 static String longitude_name = "Longitude";
052 static String latitude_name = "Latitude";
053 static String track_name = "Track";
054 static String xtrack_name = "XTrack";
055 static String geo_track_name = "geo_Track";
056 static String geo_xtrack_name = "geo_XTrack";
057 static String array_name = "array_name";
058 static String array_dimension_names = "array_dimension_names";
059 static String lon_array_name = "lon_array_name";
060 static String lat_array_name = "lat_array_name";
061 static String lon_array_dimension_names = "lon_array_dimension_names";
062 static String lat_array_dimension_names = "lat_array_dimension_names";
063 static String range_name = "range_name";
064 static String product_name = "product_name";
065 static String scale_name = "scale_name";
066 static String offset_name = "offset_name";
067 static String fill_value_name = "fill_value_name";
068 static String geo_track_offset_name = "geoTrack_offset";
069 static String geo_xtrack_offset_name = "geoXTrack_offset";
070 static String geo_track_skip_name = "geoTrack_skip";
071 static String geo_xtrack_skip_name = "geoXTrack_skip";
072 static String geo_scale_name = "geo_scale_name";
073 static String geo_offset_name = "geo_scale_name";
074 static String geo_fillValue_name = "geo_fillValue_name";
075 static String multiScaleDimensionIndex = "multiScaleDimensionIndex";
076
077 String[] rangeName_s = null;
078 Class[] arrayType_s = null;
079 Unit[] rangeUnit_s = new Unit[] {null};
080
081 String rangeName = null;
082
083 RealType track = RealType.getRealType(track_name);
084 RealType xtrack = RealType.getRealType(xtrack_name);
085 RealType[] domainRealTypes = new RealType[2];
086
087 int track_idx = -1;
088 int xtrack_idx = -1;
089 int lon_track_idx = -1;
090 int lon_xtrack_idx = -1;
091 int lat_track_idx = -1;
092 int lat_xtrack_idx = -1;
093 int range_rank = -1;
094
095 int geo_track_offset = 0;
096 int geo_track_skip = 1;
097 int geo_xtrack_offset = 0;
098 int geo_xtrack_skip = 1;
099
100 int track_tup_idx;
101 int xtrack_tup_idx;
102
103 private SwathNavigation navigation;
104
105 private Linear2DSet swathDomain;
106 private Linear2DSet domainSet_save;
107
108 private Object last_subset;
109
110 int default_stride = 1;
111
112 public static HashMap getEmptySubset() {
113 HashMap<String, double[]> subset = new HashMap<String, double[]>();
114 subset.put(track_name, new double[3]);
115 subset.put(xtrack_name, new double[3]);
116 return subset;
117 }
118
119 public static HashMap<String, Object> getEmptyMetadataTable() {
120 HashMap<String, Object> metadata = new HashMap<String, Object>();
121 metadata.put(array_name, null);
122 metadata.put(array_dimension_names, null);
123 metadata.put(track_name, null);
124 metadata.put(xtrack_name, null);
125 metadata.put(geo_track_name, null);
126 metadata.put(geo_xtrack_name, null);
127 metadata.put(lon_array_name, null);
128 metadata.put(lat_array_name, null);
129 metadata.put(lon_array_dimension_names, null);
130 metadata.put(lat_array_dimension_names, null);
131 metadata.put(scale_name, null);
132 metadata.put(offset_name, null);
133 metadata.put(fill_value_name, null);
134 metadata.put(range_name, null);
135 metadata.put(product_name, null);
136 metadata.put(geo_track_offset_name, null);
137 metadata.put(geo_xtrack_offset_name, null);
138 metadata.put(geo_track_skip_name, null);
139 metadata.put(geo_xtrack_skip_name, null);
140 metadata.put(multiScaleDimensionIndex, null);
141 return metadata;
142 }
143
144 public SwathAdapter() {
145
146 }
147
148 public SwathAdapter(MultiDimensionReader reader, HashMap metadata) {
149 super(reader, metadata);
150 this.init();
151 }
152
153 private void init() {
154 for (int k=0; k<array_rank;k++) {
155 if ( ((String)metadata.get(track_name)).equals(array_dim_names[k]) ) {
156 track_idx = k;
157 }
158 if ( ((String)metadata.get(xtrack_name)).equals(array_dim_names[k]) ) {
159 xtrack_idx = k;
160 }
161 }
162
163 int[] lengths = new int[2];
164
165 if (track_idx < xtrack_idx) {
166 domainRealTypes[0] = xtrack;
167 domainRealTypes[1] = track;
168 lengths[0] = array_dim_lengths[xtrack_idx];
169 lengths[1] = array_dim_lengths[track_idx];
170 track_tup_idx = 1;
171 xtrack_tup_idx = 0;
172 }
173 else {
174 domainRealTypes[0] = track;
175 domainRealTypes[1] = xtrack;
176 lengths[0] = array_dim_lengths[track_idx];
177 lengths[1] = array_dim_lengths[xtrack_idx];
178 track_tup_idx = 0;
179 xtrack_tup_idx = 1;
180 }
181
182 TrackLen = array_dim_lengths[track_idx];
183 XTrackLen = array_dim_lengths[xtrack_idx];
184
185 setLengths();
186
187 lengths[track_tup_idx] = TrackLen;
188 lengths[xtrack_tup_idx] = XTrackLen;
189
190 if (metadata.get(range_name) != null) {
191 rangeName = (String)metadata.get(range_name);
192 }
193 else {
194 rangeName = (String)metadata.get(array_name);
195 }
196
197 rangeType = RealType.getRealType(rangeName, rangeUnit_s[0]);
198
199 /** TODO could be a mis-match between supplied unit, and default
200 unit of an existing RealType with same name. */
201 if (rangeType == null) {
202 rangeType = RealType.getRealType(rangeName);
203 }
204
205 try {
206 RangeProcessor rangeProcessor = RangeProcessor.createRangeProcessor(reader, metadata);
207 if ( !(reader instanceof GranuleAggregation) ) {
208 setRangeProcessor(rangeProcessor);
209 }
210 }
211 catch (Exception e) {
212 System.out.println("RangeProcessor failed to create");
213 e.printStackTrace();
214 }
215
216 try {
217 navigation = SwathNavigation.createNavigation(this);
218 RealTupleType domainTupType = new RealTupleType(domainRealTypes[0], domainRealTypes[1]);
219 swathDomain = new Linear2DSet(domainTupType, 0, lengths[0]-1, lengths[0], 0, lengths[1]-1, lengths[1]);
220 }
221 catch (Exception e) {
222 System.out.println("Navigation failed to create");
223 e.printStackTrace();
224 }
225
226 if (XTrackLen <= 256) {
227 default_stride = 1;
228 }
229 else {
230 default_stride = (int) XTrackLen/256;
231 }
232
233 /* force default stride even */
234 if (default_stride > 1) {
235 default_stride = (default_stride/2)*2;
236 }
237
238 }
239
240 protected void setLengths() {
241 }
242
243 public int getTrackLength() {
244 return TrackLen;
245 }
246
247 public int getXTrackLength() {
248 return XTrackLen;
249 }
250
251 public SwathNavigation getNavigation() {
252 return navigation;
253 }
254
255 protected void setTrackLength(int len) {
256 TrackLen = len;
257 }
258
259 protected void setXTrackLength(int len) {
260 XTrackLen = len;
261 }
262
263 public Set makeDomain(Object subset) throws Exception {
264 if (last_subset != null) {
265 if (spatialEquals(last_subset, subset)) return domainSet_save;
266 }
267 last_subset = subset;
268
269 double[] first = new double[2];
270 double[] last = new double[2];
271 int[] length = new int[2];
272
273 HashMap<String, double[]> domainSubset = new HashMap<String, double[]>();
274 domainSubset.put(track_name, (double[]) ((HashMap)subset).get(track_name));
275 domainSubset.put(xtrack_name, (double[]) ((HashMap)subset).get(xtrack_name));
276
277 domainSubset.put(track_name, new double[] {0,0,0});
278 domainSubset.put(xtrack_name, new double[] {0,0,0});
279
280 // compute coordinates for the Linear2D domainSet
281 for (int kk=0; kk<2; kk++) {
282 RealType rtype = domainRealTypes[kk];
283 String name = rtype.getName();
284 double[] coords = (double[]) ((HashMap)subset).get(name);
285 first[kk] = coords[0];
286 last[kk] = coords[1];
287 length[kk] = (int) ((last[kk] - first[kk])/coords[2] + 1);
288 last[kk] = first[kk] + (length[kk]-1)*coords[2];
289
290 double[] new_coords = domainSubset.get(name);
291 new_coords[0] = first[kk];
292 new_coords[1] = last[kk];
293 new_coords[2] = coords[2];
294 }
295
296 Linear2DSet domainSet = new Linear2DSet(first[0], last[0], length[0], first[1], last[1], length[1]);
297 //CoordinateSystem cs = navigation.getVisADCoordinateSystem(domainSet, domainSubset);
298 CoordinateSystem cs = navigation.getVisADCoordinateSystem(domainSet, subset);
299
300 RealTupleType domainTupType = new RealTupleType(domainRealTypes[0], domainRealTypes[1], cs, null);
301 domainSet_save = new Linear2DSet(domainTupType, first[0], last[0], length[0], first[1], last[1], length[1]);
302
303 return domainSet_save;
304 }
305
306 public String getArrayName() {
307 return rangeName;
308 }
309
310 public FunctionType getMathType() {
311 return null;
312 }
313
314 public RealType[] getDomainRealTypes() {
315 return domainRealTypes;
316 }
317
318 public Linear2DSet getSwathDomain() {
319 return swathDomain;
320 }
321
322 public boolean spatialEquals(Object last_subset, Object subset) {
323 double[] last_coords = (double[]) ((HashMap)last_subset).get(track_name);
324 double[] coords = (double[]) ((HashMap)subset).get(track_name);
325
326 for (int k=0; k<coords.length; k++) {
327 if (coords[k] != last_coords[k]) {
328 return false;
329 }
330 }
331
332 last_coords = (double[]) ((HashMap)last_subset).get(xtrack_name);
333 coords = (double[]) ((HashMap)subset).get(xtrack_name);
334
335 for (int k=0; k<coords.length; k++) {
336 if (coords[k] != last_coords[k]) {
337 return false;
338 }
339 }
340
341 return true;
342 }
343
344 public void setDefaultStride(int stride) {
345 default_stride = stride;
346 }
347
348 public HashMap getDefaultSubset() {
349 HashMap subset = SwathAdapter.getEmptySubset();
350
351 double[] coords = (double[])subset.get("Track");
352 coords[0] = 0.0;
353 coords[1] = TrackLen - 1;
354 coords[2] = (double)default_stride;
355 subset.put("Track", coords);
356
357 coords = (double[])subset.get("XTrack");
358 coords[0] = 0.0;
359 coords[1] = XTrackLen - 1 ;
360 coords[2] = (double)default_stride;
361 subset.put("XTrack", coords);
362 return subset;
363 }
364 }