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