001    /*
002     * $Id: MultiDimensionDataSource.java,v 1.37 2012/02/19 17:35:40 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 java.awt.BorderLayout;
034    import java.awt.Color;
035    import java.awt.FlowLayout;
036    import java.awt.event.ActionEvent;
037    import java.awt.event.ActionListener;
038    import java.io.File;
039    import java.net.URL;
040    import java.rmi.RemoteException;
041    import java.util.Enumeration;
042    import java.util.HashMap;
043    import java.util.Hashtable;
044    import java.util.List;
045    
046    import javax.swing.JComponent;
047    import javax.swing.JLabel;
048    import javax.swing.JPanel;
049    import javax.swing.JTextField;
050    
051    import visad.CellImpl;
052    import visad.Data;
053    import visad.FlatField;
054    import visad.Gridded2DSet;
055    import visad.GriddedSet;
056    import visad.RealTupleType;
057    import visad.RealType;
058    import visad.SampledSet;
059    import visad.UnionSet;
060    import visad.VisADException;
061    import visad.data.mcidas.BaseMapAdapter;
062    import visad.georef.MapProjection;
063    
064    import ucar.unidata.data.DataCategory;
065    import ucar.unidata.data.DataChoice;
066    import ucar.unidata.data.DataSelection;
067    import ucar.unidata.data.DataSelectionComponent;
068    import ucar.unidata.data.DataSourceDescriptor;
069    import ucar.unidata.data.DirectDataChoice;
070    import ucar.unidata.data.GeoLocationInfo;
071    import ucar.unidata.data.GeoSelection;
072    import ucar.unidata.geoloc.projection.LatLonProjection;
073    import ucar.unidata.util.Misc;
074    import ucar.unidata.view.geoloc.MapProjectionDisplay;
075    import ucar.unidata.view.geoloc.MapProjectionDisplayJ3D;
076    import ucar.visad.ProjectionCoordinateSystem;
077    import ucar.visad.display.DisplayMaster;
078    import ucar.visad.display.LineDrawing;
079    import ucar.visad.display.MapLines;
080    import ucar.visad.display.RubberBandBox;
081    
082    import edu.wisc.ssec.mcidasv.data.HydraDataSource;
083    import edu.wisc.ssec.mcidasv.data.PreviewSelection;
084    
085    /**
086     * A data source for Multi Dimension Data 
087     */
088    
089    public class MultiDimensionDataSource extends HydraDataSource {
090    
091        /** Sources file */
092        protected String filename;
093    
094        protected MultiDimensionReader reader;
095    
096        protected MultiDimensionAdapter[] adapters = null;
097        protected HashMap[] defaultSubsets = null;
098        private HashMap<String, MultiDimensionAdapter> adapterMap = new HashMap<String, MultiDimensionAdapter>();
099        protected Hashtable[] propsArray = null;
100        protected List[] categoriesArray = null;
101    
102    
103        protected SpectrumAdapter spectrumAdapter;
104    
105        private static final String DATA_DESCRIPTION = "Multi Dimension Data";
106    
107        private HashMap defaultSubset;
108        public TrackAdapter track_adapter;
109        private MultiSpectralData multiSpectData;
110    
111        private List categories;
112        private boolean hasImagePreview = false;
113        private boolean hasTrackPreview = false;
114    
115        /**
116         * Zero-argument constructor for construction via unpersistence.
117         */
118        public MultiDimensionDataSource() {}
119    
120        /**
121         * Construct a new HYDRA hdf data source.
122         * @param  descriptor  descriptor for this <code>DataSource</code>
123         * @param  fileName  name of the hdf file to read
124         * @param  properties  hashtable of properties
125         *
126         * @throws VisADException problem creating data
127         */
128        public MultiDimensionDataSource(DataSourceDescriptor descriptor,
129                                     String fileName, Hashtable properties)
130                throws VisADException {
131            this(descriptor, Misc.newList(fileName), properties);
132        }
133    
134        /**
135         * Construct a new HYDRA hdf data source.
136         * @param  descriptor  descriptor for this <code>DataSource</code>
137         * @param  sources   List of filenames
138         * @param  properties  hashtable of properties
139         *
140         * @throws VisADException problem creating data
141         */
142        public MultiDimensionDataSource(DataSourceDescriptor descriptor,
143                                     List newSources, Hashtable properties)
144                throws VisADException {
145            super(descriptor, newSources, DATA_DESCRIPTION, properties);
146    
147            this.filename = (String)sources.get(0);
148    
149            try {
150              setup();
151            }
152            catch (Exception e) {
153              e.printStackTrace();
154              throw new VisADException();
155            }
156        }
157    
158        public void setup() throws Exception {
159    
160            try {
161              if (filename.contains("MYD02SSH")) { // get file union
162                String other = (String) sources.get(1);
163                if (filename.endsWith("nav.hdf")) {
164                  String tmp = filename;
165                  filename = other;
166                  other = tmp;
167                }
168                reader = NetCDFFile.makeUnion(filename, other);
169              }
170              else {
171                reader = new NetCDFFile(filename);
172              }
173            }
174            catch (Exception e) {
175              e.printStackTrace();
176              System.out.println("cannot create NetCDF reader for file: "+filename);
177            }
178    
179            adapters = new MultiDimensionAdapter[2];
180            defaultSubsets = new HashMap[2]; 
181            Hashtable<String, String[]> properties = new Hashtable<String, String[]>(); 
182            
183            String name = (new File(filename)).getName();
184    
185            if ( name.startsWith("MOD04") || name.startsWith("MYD04")) {
186              HashMap table = SwathAdapter.getEmptyMetadataTable();
187              table.put("array_name", "mod04/Data Fields/Optical_Depth_Land_And_Ocean");
188              table.put("lon_array_name", "mod04/Geolocation Fields/Longitude");
189              table.put("lat_array_name", "mod04/Geolocation Fields/Latitude");
190              table.put("XTrack", "Cell_Across_Swath");
191              table.put("Track", "Cell_Along_Swath");
192              table.put("geo_Track", "Cell_Along_Swath");
193              table.put("geo_XTrack", "Cell_Across_Swath");
194              table.put("scale_name", "scale_factor");
195              table.put("offset_name", "add_offset");
196              table.put("fill_value_name", "_FillValue");
197              table.put("range_name", "Optical_Depth_Land_And_Ocean");
198              adapters[0] = new SwathAdapter(reader, table);
199              categories = DataCategory.parseCategories("2D grid;GRID-2D;");
200              defaultSubset = adapters[0].getDefaultSubset();
201              defaultSubsets[0] = defaultSubset;
202            }
203            else if ( name.startsWith("MOD06") || name.startsWith("MYD06")) {
204              hasImagePreview = true;
205              String path = "mod06/Data Fields/";
206              String[] arrayNames = new String[] {"Cloud_Optical_Thickness", "Cloud_Effective_Radius", "Cloud_Water_Path"};
207              String[] arrayNames_5km = new String[] {"Cloud_Top_Pressure", "Cloud_Top_Temperature", "Cloud_Fraction"};
208      
209              adapters = new MultiDimensionAdapter[arrayNames.length+arrayNames_5km.length];
210              defaultSubsets = new HashMap[arrayNames.length+arrayNames_5km.length];
211              categoriesArray = new List[adapters.length];
212    
213              
214              for (int k=0; k<arrayNames.length; k++) {
215                HashMap table = SwathAdapter.getEmptyMetadataTable();
216                table.put("array_name", path.concat(arrayNames[k]));
217                table.put("lon_array_name", "mod06/Geolocation Fields/Longitude");
218                table.put("lat_array_name", "mod06/Geolocation Fields/Latitude");
219                table.put("XTrack", "Cell_Across_Swath_1km");
220                table.put("Track", "Cell_Along_Swath_1km");
221                table.put("geo_Track", "Cell_Along_Swath_5km");
222                table.put("geo_XTrack", "Cell_Across_Swath_5km");
223                table.put("scale_name", "scale_factor");
224                table.put("offset_name", "add_offset");
225                table.put("fill_value_name", "_FillValue");
226                table.put("range_name", arrayNames[k]);
227    
228                table.put(SwathAdapter.geo_track_offset_name, Double.toString(2.0));
229                table.put(SwathAdapter.geo_xtrack_offset_name, Double.toString(2.0));
230                table.put(SwathAdapter.geo_track_skip_name, Double.toString(5.0));
231                table.put(SwathAdapter.geo_xtrack_skip_name, Double.toString(5.0148148148));
232    
233                SwathAdapter swathAdapter = new SwathAdapter(reader, table);
234                swathAdapter.setDefaultStride(10);
235                defaultSubset = swathAdapter.getDefaultSubset();
236                adapters[k] = swathAdapter;
237                defaultSubsets[k] = defaultSubset;
238                categoriesArray[k] = DataCategory.parseCategories("1km swath;GRID-2D;");
239              }
240    
241              for (int k=0; k<arrayNames_5km.length; k++) {
242                HashMap table = SwathAdapter.getEmptyMetadataTable();
243                table.put("array_name", path.concat(arrayNames_5km[k]));
244                table.put("lon_array_name", "mod06/Geolocation Fields/Longitude");
245                table.put("lat_array_name", "mod06/Geolocation Fields/Latitude");
246                table.put("XTrack", "Cell_Across_Swath_5km");
247                table.put("Track", "Cell_Along_Swath_5km");
248                table.put("geo_Track", "Cell_Along_Swath_5km");
249                table.put("geo_XTrack", "Cell_Across_Swath_5km");
250                table.put("scale_name", "scale_factor");
251                table.put("offset_name", "add_offset");
252                table.put("fill_value_name", "_FillValue");
253                table.put("range_name", arrayNames_5km[k]);
254    
255                SwathAdapter swathAdapter = new SwathAdapter(reader, table);
256                defaultSubset = swathAdapter.getDefaultSubset();
257                adapters[arrayNames.length+k] = swathAdapter;
258                defaultSubsets[arrayNames.length+k] = defaultSubset;
259                categoriesArray[arrayNames.length+k] = DataCategory.parseCategories("5km swath;GRID-2D;");
260              }
261           }
262           else if (name.startsWith("a1") && name.contains("mod06")) {
263              hasImagePreview = true;
264              String[] arrayNames = new String[] {"Cloud_Optical_Thickness", "Cloud_Effective_Radius", "Cloud_Water_Path"};
265              String[] arrayNames_5km = new String[] {"Cloud_Top_Pressure", "Cloud_Top_Temperature", "Cloud_Fraction"};
266    
267              adapters = new MultiDimensionAdapter[arrayNames.length+arrayNames_5km.length];
268              defaultSubsets = new HashMap[arrayNames.length+arrayNames_5km.length];
269              categoriesArray = new List[adapters.length];
270    
271    
272              for (int k=0; k<arrayNames.length; k++) {
273                HashMap table = SwathAdapter.getEmptyMetadataTable();
274                table.put("array_name", arrayNames[k]);
275                table.put("lon_array_name", "Longitude");
276                table.put("lat_array_name", "Latitude");
277                table.put("array_dimension_names", new String[] {"Cell_Along_Swath_1km", "Cell_Across_Swath_1km"});
278                table.put("lon_array_dimension_names", new String[] {"Cell_Along_Swath_1km", "Cell_Across_Swath_1km"});
279                table.put("lat_array_dimension_names", new String[] {"Cell_Along_Swath_1km", "Cell_Across_Swath_1km"});
280                table.put("XTrack", "Cell_Across_Swath_1km");
281                table.put("Track", "Cell_Along_Swath_1km");
282                table.put("geo_Track", "Cell_Along_Swath_5km");
283                table.put("geo_XTrack", "Cell_Across_Swath_5km");
284                table.put("scale_name", "scale_factor");
285                table.put("offset_name", "add_offset");
286                table.put("fill_value_name", "_FillValue");
287                table.put("range_name", arrayNames[k]);
288    
289                table.put(SwathAdapter.geo_track_offset_name, Double.toString(2.0));
290                table.put(SwathAdapter.geo_xtrack_offset_name, Double.toString(2.0));
291                table.put(SwathAdapter.geo_track_skip_name, Double.toString(5.0));
292                table.put(SwathAdapter.geo_xtrack_skip_name, Double.toString(5.0148148148));
293    
294                SwathAdapter swathAdapter = new SwathAdapter(reader, table);
295                swathAdapter.setDefaultStride(10);
296                defaultSubset = swathAdapter.getDefaultSubset();
297                adapters[k] = swathAdapter;
298                defaultSubsets[k] = defaultSubset;
299                categoriesArray[k] = DataCategory.parseCategories("1km swath;GRID-2D;");
300              }
301    
302              for (int k=0; k<arrayNames_5km.length; k++) {
303                HashMap table = SwathAdapter.getEmptyMetadataTable();
304                table.put("array_name", arrayNames_5km[k]);
305                table.put("lon_array_name", "Longitude");
306                table.put("lat_array_name", "Latitude");
307                table.put("array_dimension_names", new String[] {"Cell_Along_Swath_5km", "Cell_Across_Swath_5km"});
308                table.put("lon_array_dimension_names", new String[] {"Cell_Along_Swath_5km", "Cell_Across_Swath_5km"});
309                table.put("lat_array_dimension_names", new String[] {"Cell_Along_Swath_5km", "Cell_Across_Swath_5km"});
310                table.put("XTrack", "Cell_Across_Swath_5km");
311                table.put("Track", "Cell_Along_Swath_5km");
312                table.put("geo_Track", "Cell_Along_Swath_5km");
313                table.put("geo_XTrack", "Cell_Across_Swath_5km");
314                table.put("scale_name", "scale_factor");
315                table.put("offset_name", "add_offset");
316                table.put("fill_value_name", "_FillValue");
317                table.put("range_name", arrayNames_5km[k]);
318    
319                SwathAdapter swathAdapter = new SwathAdapter(reader, table);
320                defaultSubset = swathAdapter.getDefaultSubset();
321                adapters[arrayNames.length+k] = swathAdapter;
322                defaultSubsets[arrayNames.length+k] = defaultSubset;
323                categoriesArray[arrayNames.length+k] = DataCategory.parseCategories("5km swath;GRID-2D;");
324              }
325           }
326           else if (name.startsWith("CAL_LID_L1")) {
327             String[] arrayNames = null;
328             adapters = new MultiDimensionAdapter[4];
329             defaultSubsets = new HashMap[4];
330             propsArray = new Hashtable[4]; 
331             
332             
333             HashMap table = ProfileAlongTrack.getEmptyMetadataTable();
334             table.put(ProfileAlongTrack.array_name, "Total_Attenuated_Backscatter_532");
335             table.put(ProfileAlongTrack.ancillary_file_name, "/edu/wisc/ssec/mcidasv/data/hydra/resources/calipso/altitude");
336             table.put(ProfileAlongTrack.trackDim_name, "dim0");
337             table.put(ProfileAlongTrack.vertDim_name, "dim1");
338             table.put(ProfileAlongTrack.profileTime_name, "Profile_Time");
339             table.put(ProfileAlongTrack.longitude_name, "Longitude");
340             table.put(ProfileAlongTrack.latitude_name, "Latitude");
341             ProfileAlongTrack adapter = new Calipso2D(reader, table);
342             ProfileAlongTrack3D adapter3D = new ProfileAlongTrack3D(adapter);
343             HashMap subset = adapter.getDefaultSubset();
344             adapters[0] = adapter3D;
345             defaultSubset = subset;
346             defaultSubsets[0] = defaultSubset;
347             DataCategory.createCategory("ProfileAlongTrack");
348             categories = DataCategory.parseCategories("ProfileAlongTrack;ProfileAlongTrack;");
349    
350             properties.put("medianFilter", new String[] {Double.toString(8), Double.toString(16)});
351             properties.put("setBelowSfcMissing", new String[] {"true"});
352             propsArray[0] = properties;
353    
354    
355             ArrayAdapter[] adapter_s = new ArrayAdapter[3];
356             table = ProfileAlongTrack.getEmptyMetadataTable();
357             table.put(ProfileAlongTrack.array_name, "Latitude");
358             table.put(ProfileAlongTrack.trackDim_name, "dim0");
359             table.put(ProfileAlongTrack.vertDim_name, "dim1");
360             adapter_s[0] = new ArrayAdapter(reader, table);
361    
362             table = ProfileAlongTrack.getEmptyMetadataTable();
363             table.put(ProfileAlongTrack.array_name, "Surface_Elevation");
364             table.put(ProfileAlongTrack.trackDim_name, "dim0");
365             table.put(ProfileAlongTrack.vertDim_name, "dim1");
366             adapter_s[1] = new ArrayAdapter(reader, table);
367    
368             table = ProfileAlongTrack.getEmptyMetadataTable();
369             table.put(ProfileAlongTrack.array_name, "Longitude");
370             table.put(ProfileAlongTrack.trackDim_name, "dim0");
371             table.put(ProfileAlongTrack.vertDim_name, "dim1");
372             adapter_s[2] = new ArrayAdapter(reader, table);
373    
374             TrackDomain track_domain = new TrackDomain(adapter_s[2], adapter_s[0], adapter_s[1]);
375             track_adapter = new TrackAdapter(track_domain, adapter_s[1]);
376    
377             table = ProfileAlongTrack.getEmptyMetadataTable();
378             table.put(ProfileAlongTrack.array_name, "Tropopause_Height");
379             table.put(ProfileAlongTrack.trackDim_name, "dim0");
380             table.put(ProfileAlongTrack.vertDim_name, "dim1");
381             ArrayAdapter trop_height = new ArrayAdapter(reader, table);
382             track_domain = new TrackDomain(adapter_s[2], adapter_s[0], trop_height);
383             adapters[1] = new TrackAdapter(track_domain, trop_height);
384             defaultSubsets[1] = adapters[1].getDefaultSubset();
385    
386             adapters[2] = new TrackAdapter(new TrackDomain(adapter_s[2], adapter_s[0], adapter_s[1]), adapter_s[1]);
387             ((TrackAdapter)adapters[2]).setName("Track3D");
388             defaultSubsets[2] = adapters[2].getDefaultSubset();
389    
390             adapters[3] = new TrackAdapter(new TrackDomain(adapter_s[2], adapter_s[0]), adapter_s[1]);
391             ((TrackAdapter)adapters[3]).setName("Track2D");
392             defaultSubsets[3] = adapters[3].getDefaultSubset();
393             
394    
395             hasTrackPreview = true;
396           }
397           else if (name.startsWith("CAL_LID_L2")) {
398             adapters = new MultiDimensionAdapter[4];
399             defaultSubsets = new HashMap[4];
400             propsArray = new Hashtable[4];
401    
402             ArrayAdapter[] adapter_s = new ArrayAdapter[3];
403    
404             HashMap table = ProfileAlongTrack.getEmptyMetadataTable();
405             table.put(ProfileAlongTrack.array_name, "Longitude");
406             table.put(ProfileAlongTrack.trackDim_name, "dim0");
407             table.put(ProfileAlongTrack.vertDim_name, "dim1");
408             adapter_s[0] = new ArrayAdapter(reader, table);
409    
410             table = ProfileAlongTrack.getEmptyMetadataTable();
411             table.put(ProfileAlongTrack.array_name, "Latitude");
412             table.put(ProfileAlongTrack.trackDim_name, "dim0");
413             table.put(ProfileAlongTrack.vertDim_name, "dim1");
414             adapter_s[1] = new ArrayAdapter(reader, table);
415    
416             table = ProfileAlongTrack.getEmptyMetadataTable();
417             table.put(ProfileAlongTrack.array_name, "DEM_Surface_Elevation");
418             table.put(ProfileAlongTrack.trackDim_name, "dim0");
419             table.put(ProfileAlongTrack.vertDim_name, "dim1");
420             adapter_s[2] = new ArrayAdapter(reader, table);
421    
422             TrackDomain track_domain = new TrackDomain(adapter_s[0], adapter_s[1], adapter_s[2]);
423             track_adapter = new TrackAdapter(track_domain, adapter_s[2]);
424             adapters[1] = track_adapter;
425             defaultSubsets[1] = track_adapter.getDefaultSubset();
426    
427             table = ProfileAlongTrack.getEmptyMetadataTable();
428             table.put(ProfileAlongTrack.array_name, "Layer_Top_Altitude");
429             table.put(ProfileAlongTrack.trackDim_name, "dim0");
430             table.put(ProfileAlongTrack.vertDim_name, "dim1");
431             ArrayAdapter layer_top_altitude = new ArrayAdapter(reader, table);
432             RangeProcessor rngProcessor =
433                 new RangeProcessor(1.0f, 0.0f, -Float.MAX_VALUE, Float.MAX_VALUE, -9999.0f);
434             layer_top_altitude.setRangeProcessor(rngProcessor);
435    
436             track_domain = new TrackDomain(adapter_s[0], adapter_s[1], layer_top_altitude);
437             adapters[0] = new TrackAdapter(track_domain, layer_top_altitude);
438             defaultSubsets[0] = adapters[0].getDefaultSubset();
439    
440             /** another layer, how to show all?
441             adapters[2] = new TrackAdapter(track_domain, layer_top_altitude);
442             ((TrackAdapter)adapters[2]).setListIndex(1);
443             defaultSubsets[2] = adapters[2].getDefaultSubset();
444             */
445    
446             adapters[2] = new TrackAdapter(new TrackDomain(adapter_s[0], adapter_s[1]), adapter_s[2]);
447             ((TrackAdapter)adapters[2]).setName("Track2D");
448             defaultSubsets[2] = adapters[2].getDefaultSubset();
449    
450             adapters[3] = new TrackAdapter(new TrackDomain(adapter_s[0], adapter_s[1], adapter_s[2]), adapter_s[2]);
451             ((TrackAdapter)adapters[3]).setName("Track3D");
452             defaultSubsets[3] = adapters[3].getDefaultSubset();
453    
454             DataCategory.createCategory("ProfileAlongTrack");
455             categories = DataCategory.parseCategories("ProfileAlongTrack;ProfileAlongTrack;");
456    
457             hasTrackPreview = true;
458           }
459           else if (name.indexOf("2B-GEOPROF") > 0) {
460             adapters = new MultiDimensionAdapter[2];
461             defaultSubsets = new HashMap[2];
462             propsArray = new Hashtable[2];
463    
464             HashMap table = ProfileAlongTrack.getEmptyMetadataTable();
465             table.put(ProfileAlongTrack.array_name, "2B-GEOPROF/Data Fields/Radar_Reflectivity");
466             table.put(ProfileAlongTrack.range_name, "2B-GEOPROF_RadarReflectivity");
467             table.put(ProfileAlongTrack.scale_name, "factor");
468             table.put(ProfileAlongTrack.offset_name, "offset");
469             table.put(ProfileAlongTrack.fill_value_name, "_FillValue");
470             table.put(ProfileAlongTrack.valid_range, "valid_range");
471             table.put(ProfileAlongTrack.ancillary_file_name, "/edu/wisc/ssec/mcidasv/data/hydra/resources/cloudsat/altitude");
472             table.put(ProfileAlongTrack.trackDim_name, "nray");
473             table.put(ProfileAlongTrack.vertDim_name, "nbin");
474             table.put(ProfileAlongTrack.profileTime_name, "2B-GEOPROF/Geolocation Fields/Profile_Time");
475             table.put(ProfileAlongTrack.longitude_name, "2B-GEOPROF/Geolocation Fields/Longitude");
476             table.put(ProfileAlongTrack.latitude_name, "2B-GEOPROF/Geolocation Fields/Latitude");
477             table.put(ProfileAlongTrack.product_name, "2B-GEOPROF");
478             ProfileAlongTrack adapter = new CloudSat2D(reader, table);
479             ProfileAlongTrack3D adapter3D = new ProfileAlongTrack3D(adapter);
480             HashMap subset = adapter.getDefaultSubset();
481             adapters[0] = adapter3D;
482             defaultSubset = subset;
483             defaultSubsets[0] = defaultSubset;
484             DataCategory.createCategory("ProfileAlongTrack");
485             categories = DataCategory.parseCategories("ProfileAlongTrack;ProfileAlongTrack;");
486    
487             ArrayAdapter[] adapter_s = new ArrayAdapter[3];
488             table = ProfileAlongTrack.getEmptyMetadataTable();
489             table.put(ProfileAlongTrack.array_name, "2B-GEOPROF/Geolocation Fields/Latitude");
490             table.put(ProfileAlongTrack.range_name, "Latitude");
491             table.put(ProfileAlongTrack.trackDim_name, "nray");
492             adapter_s[0] = new ArrayAdapter(reader, table);
493    
494             table = ProfileAlongTrack.getEmptyMetadataTable();
495             table.put(ProfileAlongTrack.array_name, "2B-GEOPROF/Geolocation Fields/DEM_elevation");
496             table.put(ProfileAlongTrack.range_name, "DEM_elevation");
497             table.put(ProfileAlongTrack.trackDim_name, "nray");
498             adapter_s[1] = new ArrayAdapter(reader, table);
499    
500             table = ProfileAlongTrack.getEmptyMetadataTable();
501             table.put(ProfileAlongTrack.array_name, "2B-GEOPROF/Geolocation Fields/Longitude");
502             table.put(ProfileAlongTrack.range_name, "Longitude");
503             table.put(ProfileAlongTrack.trackDim_name, "nray");
504             adapter_s[2] = new ArrayAdapter(reader, table);
505    
506             TrackDomain track_domain = new TrackDomain(adapter_s[2], adapter_s[0], adapter_s[1]);
507             track_adapter = new TrackAdapter(track_domain, adapter_s[1]);
508    
509             /*
510             adapters[2] = new TrackAdapter(new TrackDomain(adapter_s[2], adapter_s[0], adapter_s[1]), adapter_s[1]);
511             ((TrackAdapter)adapters[2]).setName("Track3D");
512             defaultSubsets[2] = adapters[2].getDefaultSubset();
513             */
514    
515             adapters[1] = new TrackAdapter(new TrackDomain(adapter_s[2], adapter_s[0]), adapter_s[1]);
516             ((TrackAdapter)adapters[1]).setName("Track2D");
517             defaultSubsets[1] = adapters[1].getDefaultSubset();
518    
519    
520             properties.put("medianFilter", new String[] {Double.toString(6), Double.toString(14)});
521             properties.put("setBelowSfcMissing", new String[] {"true"});
522             hasTrackPreview = true;
523           }
524           else if ( name.startsWith("MHSx_xxx_1B") && name.endsWith("h5")) {
525              HashMap table = SwathAdapter.getEmptyMetadataTable();
526              table.put("array_name", "U-MARF/EPS/MHSx_xxx_1B/DATA/Channel1");
527              table.put("lon_array_name", "U-MARF/EPS/IASI_xxx_1C/DATA/IMAGE_LON_ARRAY");
528              table.put("lat_array_name", "U-MARF/EPS/IASI_xxx_1C/DATA/IMAGE_LAT_ARRAY");
529              table.put("XTrack", "dim1");
530              table.put("Track", "dim0");
531              table.put("geo_XTrack", "dim1");
532              table.put("geo_Track", "dim0");
533              table.put("product_name", "MHSx_xxx_1B");
534              SwathAdapter swathAdapter = new SwathAdapter(reader, table);
535              adapters[0] = swathAdapter;
536              HashMap subset = swathAdapter.getDefaultSubset();
537              defaultSubset = subset;
538              defaultSubsets[0] = defaultSubset;
539              categories = DataCategory.parseCategories("2D grid;GRID-2D;");
540           }
541           else if ( name.startsWith("MYD02SSH") ) {
542             String[] arrayNames = null;
543    
544             if (name.endsWith("level2.hdf")) {
545               arrayNames = new String[] {"cld_press_acha", "cld_temp_acha", "cld_height_acha", "cloud_type",
546                                                 "cloud_albedo_0_65um_nom", "cloud_transmission_0_65um_nom", "cloud_fraction"};
547             }
548             else if (name.endsWith("obs.hdf")) {
549               arrayNames = new String[] {"refl_0_65um_nom", "refl_0_86um_nom", "refl_3_75um_nom", "refl_1_60um_nom", "refl_1_38um_nom",
550                                          "temp_3_75um_nom", "temp_11_0um_nom", "temp_12_0um_nom", "temp_6_7um_nom",
551                                          "temp_8_5um_nom", "temp_13_3um_nom"};
552             }
553      
554             adapters = new MultiDimensionAdapter[arrayNames.length];
555             defaultSubsets = new HashMap[arrayNames.length];
556             propsArray = new Hashtable[arrayNames.length]; 
557    
558             for (int k=0; k<arrayNames.length; k++) {
559               HashMap swthTable = SwathAdapter.getEmptyMetadataTable();
560               swthTable.put("array_name", arrayNames[k]);
561               swthTable.put("lon_array_name", "pixel_longitude");
562               swthTable.put("lat_array_name", "pixel_latitude");
563               swthTable.put("XTrack", "pixel_elements_along_scan_direction");
564               swthTable.put("Track", "scan_lines_along_track_direction");
565               swthTable.put("geo_Track", "scan_lines_along_track_direction");
566               swthTable.put("geo_XTrack", "pixel_elements_along_scan_direction");
567               swthTable.put("scale_name", "SCALE_FACTOR");
568               swthTable.put("offset_name", "ADD_OFFSET");
569               swthTable.put("fill_value_name", "_FILLVALUE");
570               swthTable.put("geo_scale_name", "SCALE_FACTOR");
571               swthTable.put("geo_offset_name", "ADD_OFFSET");
572               swthTable.put("geo_fillValue_name", "_FILLVALUE");
573               swthTable.put("range_name", arrayNames[k]);
574               swthTable.put("unpack", "unpack");
575    
576               SwathAdapter swathAdapter0 = new SwathAdapter(reader, swthTable);
577               HashMap subset = swathAdapter0.getDefaultSubset();
578               defaultSubset = subset;
579               adapters[k] = swathAdapter0;
580               defaultSubsets[k] = defaultSubset;
581             }
582             categories = DataCategory.parseCategories("2D grid;GRID-2D;");
583             hasImagePreview = true;
584           }
585           else if (name.contains("AWG_OZONE") ) {
586             String[] arrayNames = new String[] {"ColumnOzone"};
587    
588             adapters = new MultiDimensionAdapter[arrayNames.length];
589             defaultSubsets = new HashMap[arrayNames.length];
590             propsArray = new Hashtable[arrayNames.length];
591             
592             for (int k=0; k<arrayNames.length; k++) {
593               HashMap swthTable = SwathAdapter.getEmptyMetadataTable();
594               swthTable.put("array_name", arrayNames[k]);
595               swthTable.put("lon_array_name", "Longitude");
596               swthTable.put("lat_array_name", "Latitude");
597               swthTable.put("XTrack", "Columns");
598               swthTable.put("Track", "Rows");
599               swthTable.put("fill_value_name", "_FillValue");
600               swthTable.put("geo_Track", "Rows");
601               swthTable.put("geo_XTrack", "Columns");
602               swthTable.put("geo_fillValue_name", "_FillValue");
603               swthTable.put("range_name", arrayNames[k]);
604    
605               SwathAdapter swathAdapter0 = new SwathAdapter(reader, swthTable);
606               swathAdapter0.setDefaultStride(5);
607               HashMap subset = swathAdapter0.getDefaultSubset();
608               defaultSubset = subset;
609               adapters[k] = swathAdapter0;
610               defaultSubsets[k] = defaultSubset;
611             }
612    
613             categories = DataCategory.parseCategories("2D grid;GRID-2D;");
614             hasImagePreview = true;
615           }
616           else if (name.contains("AWG_CLOUD_MASK") ) {
617             String[] arrayNames = new String[] {"CloudMask"};
618    
619             adapters = new MultiDimensionAdapter[arrayNames.length];
620             defaultSubsets = new HashMap[arrayNames.length];
621             propsArray = new Hashtable[arrayNames.length];
622    
623             for (int k=0; k<arrayNames.length; k++) {
624               HashMap swthTable = SwathAdapter.getEmptyMetadataTable();
625               swthTable.put("array_name", arrayNames[k]);
626               swthTable.put("lon_array_name", "Longitude");
627               swthTable.put("lat_array_name", "Latitude");
628               swthTable.put("XTrack", "Columns");
629               swthTable.put("Track", "Rows");
630               swthTable.put("fill_value_name", "_FillValue");
631               swthTable.put("geo_Track", "Rows");
632               swthTable.put("geo_XTrack", "Columns");
633               swthTable.put("geo_fillValue_name", "_FillValue");
634               swthTable.put("range_name", arrayNames[k]);
635    
636               SwathAdapter swathAdapter0 = new SwathAdapter(reader, swthTable);
637               swathAdapter0.setDefaultStride(5);
638               HashMap subset = swathAdapter0.getDefaultSubset();
639               defaultSubset = subset;
640               adapters[k] = swathAdapter0;
641               defaultSubsets[k] = defaultSubset;
642             }
643    
644             categories = DataCategory.parseCategories("2D grid;GRID-2D;");
645             hasImagePreview = true;
646           }
647           else if (name.contains("AWG_CLOUD_HEIGHT")) {
648             String[] arrayNames = new String[] {"CldTopTemp", "CldTopPres", "CldTopHght"};
649    
650             adapters = new MultiDimensionAdapter[arrayNames.length];
651             defaultSubsets = new HashMap[arrayNames.length];
652             propsArray = new Hashtable[arrayNames.length];
653    
654             for (int k=0; k<arrayNames.length; k++) {
655               HashMap swthTable = SwathAdapter.getEmptyMetadataTable();
656               swthTable.put("array_name", arrayNames[k]);
657               swthTable.put("lon_array_name", "Longitude");
658               swthTable.put("lat_array_name", "Latitude");
659               swthTable.put("XTrack", "Columns");
660               swthTable.put("Track", "Rows");
661               swthTable.put("scale_name", "scale_factor");
662               swthTable.put("offset_name", "add_offset");
663               swthTable.put("fill_value_name", "_FillValue");
664               swthTable.put("geo_Track", "Rows");
665               swthTable.put("geo_XTrack", "Columns");
666               swthTable.put("geo_scale_name", "scale_factor");
667               swthTable.put("geo_offset_name", "add_offset");
668               swthTable.put("geo_fillValue_name", "_FillValue");
669               swthTable.put("range_name", arrayNames[k]);
670               swthTable.put("unpack", "unpack");
671    
672               SwathAdapter swathAdapter0 = new SwathAdapter(reader, swthTable);
673               swathAdapter0.setDefaultStride(5);
674               HashMap subset = swathAdapter0.getDefaultSubset();
675               defaultSubset = subset;
676               adapters[k] = swathAdapter0;
677               defaultSubsets[k] = defaultSubset;
678             }
679             categories = DataCategory.parseCategories("2D grid;GRID-2D;");
680             hasImagePreview = true;
681           }
682           else if (name.startsWith("geocatL2") && name.endsWith("ci.hdf")) {
683             String[] arrayNames = new String[] {"box_average_11um_ctc", "box_average_11um_ctc_scaled", "conv_init", "cloud_type"};
684    
685             adapters = new MultiDimensionAdapter[arrayNames.length];
686             defaultSubsets = new HashMap[arrayNames.length];
687             propsArray = new Hashtable[arrayNames.length];
688    
689             for (int k=0; k<arrayNames.length; k++) {
690               HashMap swthTable = SwathAdapter.getEmptyMetadataTable();
691               swthTable.put("array_name", arrayNames[k]);
692               swthTable.put("lon_array_name", "lon");
693               swthTable.put("lat_array_name", "lat");
694               swthTable.put("XTrack", "Elements");
695               swthTable.put("Track", "Lines");
696               swthTable.put("geo_Track", "Lines");
697               swthTable.put("geo_XTrack", "Elements");
698               swthTable.put("range_name", arrayNames[k]);
699    
700               SwathAdapter swathAdapter0 = new SwathAdapter(reader, swthTable);
701               swathAdapter0.setDefaultStride(1);
702               HashMap subset = swathAdapter0.getDefaultSubset();
703               defaultSubset = subset;
704               adapters[k] = swathAdapter0;
705               defaultSubsets[k] = defaultSubset;
706             }
707             categories = DataCategory.parseCategories("2D grid;GRID-2D;");
708             hasImagePreview = true;
709           } 
710           else {
711             String[] arrayNames = new String[] {"baseline_cmask_seviri_cloud_mask", "baseline_ctype_seviri_cloud_type",
712                                                 "baseline_ctype_seviri_cloud_phase", "baseline_cld_hght_seviri_cloud_top_pressure",
713                                                 "baseline_cld_hght_seviri_cloud_top_height"};
714    
715             adapters = new MultiDimensionAdapter[arrayNames.length];
716             defaultSubsets = new HashMap[arrayNames.length];
717             propsArray = new Hashtable[arrayNames.length]; 
718    
719             for (int k=0; k<arrayNames.length; k++) {
720               HashMap swthTable = SwathAdapter.getEmptyMetadataTable();
721               swthTable.put("array_name", arrayNames[k]);
722               swthTable.put("lon_array_name", "pixel_longitude");
723               swthTable.put("lat_array_name", "pixel_latitude");
724               swthTable.put("XTrack", "elements");
725               swthTable.put("Track", "lines");
726               swthTable.put("scale_name", "scale_factor");
727               swthTable.put("offset_name", "add_offset");
728               swthTable.put("fill_value_name", "_FillValue");
729               swthTable.put("geo_Track", "lines");
730               swthTable.put("geo_XTrack", "elements");
731               swthTable.put("geo_scale_name", "scale_factor");
732               swthTable.put("geo_offset_name", "add_offset");
733               swthTable.put("geo_fillValue_name", "_FillValue");
734               swthTable.put("range_name", arrayNames[k]);
735               swthTable.put("unpack", "unpack");
736    
737               SwathAdapter swathAdapter0 = new SwathAdapter(reader, swthTable);
738               swathAdapter0.setDefaultStride(2);
739               HashMap subset = swathAdapter0.getDefaultSubset();
740               defaultSubset = subset;
741               adapters[k] = swathAdapter0;
742               defaultSubsets[k] = defaultSubset;
743             }
744             categories = DataCategory.parseCategories("2D grid;GRID-2D;");
745             hasImagePreview = true;
746           }
747    
748           setProperties(properties);
749        }
750    
751        public void initAfterUnpersistence() {
752          try {
753            setup();
754          } 
755          catch (Exception e) {
756          }
757        }
758    
759        /**
760         * Make and insert the <code>DataChoice</code>-s for this
761         * <code>DataSource</code>.
762         */
763        public void doMakeDataChoices() {
764            DataChoice choice = null;
765            if (adapters != null) {
766              for (int idx=0; idx<adapters.length; idx++) {
767                 try {
768                   String arrayName = (adapters[idx] == null) ? "_     " : adapters[idx].getArrayName();
769                   choice = doMakeDataChoice(idx, arrayName);
770                   adapterMap.put(choice.getName(), adapters[idx]);
771                 } 
772                 catch (Exception e) {
773                   e.printStackTrace();
774                   System.out.println("doMakeDataChoice failed");
775                 }
776    
777                 if (choice != null) {
778                   addDataChoice(choice);
779                 }
780              }
781            }
782        }
783    
784        private DataChoice doMakeDataChoice(int idx, String var) throws Exception {
785            String name = var;
786            DataSelection dataSel = (defaultSubsets[idx] == null) ? new MultiDimensionSubset() : new MultiDimensionSubset(defaultSubsets[idx]);
787            Hashtable props = new Hashtable();
788            props.put(new MultiDimensionSubset(), dataSel);
789    
790            if (propsArray != null) {
791              if (propsArray[idx] != null) {
792                propsArray[idx].put(new MultiDimensionSubset(), dataSel);
793                props = propsArray[idx];
794              }
795            }
796            DirectDataChoice ddc = null;
797    
798            if (categories != null) {
799               ddc = new DirectDataChoice(this, idx, name, name, categories, props);
800            }
801            else {
802               ddc = new DirectDataChoice(this, idx, name, name, categoriesArray[idx], props);
803            }
804    
805            return ddc;
806        }
807    
808        /**
809         * Check to see if this <code>HDFHydraDataSource</code> is equal to the object
810         * in question.
811         * @param o  object in question
812         * @return true if they are the same or equivalent objects
813         */
814        public boolean equals(Object o) {
815            if ( !(o instanceof MultiDimensionDataSource)) {
816                return false;
817            }
818            return (this == (MultiDimensionDataSource) o);
819        }
820    
821        public MultiSpectralData getMultiSpectralData() {
822          return multiSpectData;
823        }
824    
825        public String getDatasetName() {
826          return filename;
827        }
828    
829        public void setDatasetName(String name) {
830          filename = name;
831        }
832    
833        public HashMap getSubsetFromLonLatRect(MultiDimensionSubset select, GeoSelection geoSelection) {
834          GeoLocationInfo ginfo = geoSelection.getBoundingBox();
835          return adapters[0].getSubsetFromLonLatRect(select.getSubset(), ginfo.getMinLat(), ginfo.getMaxLat(),
836                                            ginfo.getMinLon(), ginfo.getMaxLon());
837        }
838    
839        public synchronized Data getData(DataChoice dataChoice, DataCategory category,
840                                    DataSelection dataSelection, Hashtable requestProperties)
841                                    throws VisADException, RemoteException {
842           return this.getDataInner(dataChoice, category, dataSelection, requestProperties);
843        }
844    
845    
846        protected Data getDataInner(DataChoice dataChoice, DataCategory category,
847                                    DataSelection dataSelection, Hashtable requestProperties)
848                                    throws VisADException, RemoteException {
849    
850            MultiDimensionAdapter adapter = null;
851            adapter = adapterMap.get(dataChoice.getName());
852    
853            Hashtable dataChoiceProps = dataChoice.getProperties();
854    
855            //- this hack keeps the HydraImageProbe from doing a getData()
856            //- TODO: need to use categories?
857            if (requestProperties != null) {
858              if ((requestProperties.toString()).equals("{prop.requester=MultiSpectral}")) {
859                return null;
860              }
861            }
862    
863            GeoLocationInfo ginfo = null;
864            GeoSelection geoSelection = null;
865            
866            if ((dataSelection != null) && (dataSelection.getGeoSelection() != null)) {
867              geoSelection = (dataSelection.getGeoSelection().getBoundingBox() != null) ? dataSelection.getGeoSelection() :
868                                        dataChoice.getDataSelection().getGeoSelection();
869            }
870    
871            if (geoSelection != null) {
872              ginfo = geoSelection.getBoundingBox();
873            }
874    
875            Data data = null;
876            if (adapters == null) {
877              return data;
878            }
879    
880            HashMap subset = null;
881            MultiDimensionSubset select = null;
882    
883            Hashtable table = dataChoice.getProperties();
884            Enumeration keys = table.keys();
885            while (keys.hasMoreElements()) {
886               Object key = keys.nextElement();
887               if (key instanceof MultiDimensionSubset) {
888                  select = (MultiDimensionSubset) table.get(key);
889               }
890            }
891    
892    
893            try {
894                subset = null;
895                if (ginfo != null) {
896                  subset = adapter.getSubsetFromLonLatRect(ginfo.getMinLat(), ginfo.getMaxLat(),
897                                                           ginfo.getMinLon(), ginfo.getMaxLon(),
898                                                           geoSelection.getXStride(),
899                                                           geoSelection.getYStride(),
900                                                           geoSelection.getZStride());
901                  if (subset == null && select != null) {
902                    subset = select.getSubset();
903                  }
904                }
905                else {
906                  if (select != null) {
907                    subset = select.getSubset();
908                  }
909                  
910                  if (dataSelection != null) {
911                    Hashtable props = dataSelection.getProperties();
912                  }
913                }
914                
915                if (subset != null) {
916                  data = adapter.getData(subset);
917                  data = applyProperties(data, dataChoiceProps, subset);
918                }
919            } catch (Exception e) {
920                e.printStackTrace();
921                System.out.println("getData exception e=" + e);
922            }
923    
924            return data;
925        }
926    
927        protected Data applyProperties(Data data, Hashtable requestProperties, HashMap subset) 
928              throws VisADException, RemoteException {
929          Data new_data = data;
930    
931          if (requestProperties == null) {
932            new_data = data;
933            return new_data;
934          }
935    
936          if (requestProperties.containsKey("medianFilter")) {
937            String[] items = (String[]) requestProperties.get("medianFilter");
938            double window_lenx = Double.parseDouble(items[0]);
939            double window_leny = Double.parseDouble(items[1]);
940            GriddedSet domainSet = (GriddedSet) ((FlatField)data).getDomainSet();
941            int[] lens = domainSet.getLengths();
942            float[] range_values = (((FlatField)data).getFloats())[0];
943            range_values =
944               ProfileAlongTrack.medianFilter(range_values, lens[0], lens[1],
945                                   (int)window_lenx, (int)window_leny);
946            ((FlatField)new_data).setSamples(new float[][] {range_values});
947          }
948          if (requestProperties.containsKey("setBelowSfcMissing")) {
949            FlatField track = (FlatField) track_adapter.getData(subset);
950            float[] sfcElev = (track.getFloats())[0];
951            FlatField field = (FlatField) new_data;
952            GriddedSet gset = (GriddedSet) field.getDomainSet();
953            float[][] samples = gset.getSamples(false);
954            int[] lens = gset.getLengths();
955            float[] range_values = (field.getFloats())[0];
956    
957            int trkIdx = ((ProfileAlongTrack3D)adapters[0]).adapter2D.getTrackTupIdx();
958            int vrtIdx = ((ProfileAlongTrack3D)adapters[0]).adapter2D.getVertTupIdx();
959    
960            int k = 0;
961            for (int j=0; j<lens[trkIdx]; j++) {
962              float val = sfcElev[j]*1000f; // convert to meters
963              for (int i=0; i<lens[vrtIdx]; i++) {
964                if (vrtIdx < trkIdx) k = i + j*lens[0];
965                if (trkIdx < vrtIdx) k = j + i*lens[0];
966                if (samples[2][k] <= val || samples[2][k] < 0.0) {
967                  range_values[k] = Float.NaN;
968                }
969              }
970            }
971            field.setSamples(new float[][] {range_values});
972          }
973          return new_data;
974        }
975    
976        protected void initDataSelectionComponents(
977             List<DataSelectionComponent> components,
978                 final DataChoice dataChoice) {
979    
980          if (hasImagePreview) {
981            try {
982              FlatField image = (FlatField) getDataInner(dataChoice, null, null, null);
983              components.add(new PreviewSelection(dataChoice, image, null));
984              //components.add(new edu.wisc.ssec.mcidasv.data.PreviewSelectionNew(dataChoice, image));
985            } catch (Exception e) {
986              System.out.println("Can't make PreviewSelection: "+e);
987              e.printStackTrace();
988            }
989          }
990          if (hasTrackPreview) {
991            try {
992              FlatField track = track_adapter.getData(track_adapter.getDefaultSubset());
993              components.add(new TrackSelection(dataChoice, track));
994            } catch (Exception e) {
995              System.out.println("Can't make PreviewSelection: "+e);
996              e.printStackTrace();
997            }
998          }
999        }
1000    }
1001    
1002    class TrackSelection extends DataSelectionComponent {
1003          DataChoice dataChoice;
1004          FlatField track;
1005    
1006          double[] x_coords = new double[2];
1007          double[] y_coords = new double[2];
1008          boolean hasSubset = true;
1009          MapProjectionDisplayJ3D mapProjDsp;
1010          DisplayMaster dspMaster;
1011    
1012          int trackStride;
1013          int verticalStride;
1014    
1015          JTextField trkStr;
1016          JTextField vrtStr;
1017    
1018    
1019       TrackSelection(DataChoice dataChoice, FlatField track) throws VisADException, RemoteException {
1020            super("track");
1021            this.dataChoice = dataChoice;
1022            this.track = track;
1023            mapProjDsp = new MapProjectionDisplayJ3D(MapProjectionDisplay.MODE_2Din3D);
1024            mapProjDsp.enableRubberBanding(false);
1025            dspMaster = mapProjDsp;
1026            mapProjDsp.setMapProjection(getDataProjection());
1027            LineDrawing trackDsp = new LineDrawing("track");
1028            trackDsp.setLineWidth(2f);
1029            trackDsp.setData(track);
1030            mapProjDsp.addDisplayable(trackDsp);
1031    
1032    
1033            MapLines mapLines  = new MapLines("maplines");
1034            URL      mapSource =
1035            mapProjDsp.getClass().getResource("/auxdata/maps/OUTLSUPU");
1036            try {
1037                BaseMapAdapter mapAdapter = new BaseMapAdapter(mapSource);
1038                mapLines.setMapLines(mapAdapter.getData());
1039                mapLines.setColor(java.awt.Color.cyan);
1040                mapProjDsp.addDisplayable(mapLines);
1041            } catch (Exception excp) {
1042                System.out.println("Can't open map file " + mapSource);
1043                System.out.println(excp);
1044            }
1045                                                                                                                                                         
1046            mapLines  = new MapLines("maplines");
1047            mapSource =
1048            mapProjDsp.getClass().getResource("/auxdata/maps/OUTLSUPW");
1049            try {
1050                BaseMapAdapter mapAdapter = new BaseMapAdapter(mapSource);
1051                mapLines.setMapLines(mapAdapter.getData());
1052                mapLines.setColor(java.awt.Color.cyan);
1053                mapProjDsp.addDisplayable(mapLines);
1054            } catch (Exception excp) {
1055                System.out.println("Can't open map file " + mapSource);
1056                System.out.println(excp);
1057            }
1058                                                                                                                                                         
1059            mapLines  = new MapLines("maplines");
1060            mapSource =
1061            mapProjDsp.getClass().getResource("/auxdata/maps/OUTLHPOL");
1062            try {
1063                BaseMapAdapter mapAdapter = new BaseMapAdapter(mapSource);
1064                mapLines.setMapLines(mapAdapter.getData());
1065                mapLines.setColor(java.awt.Color.cyan);
1066                mapProjDsp.addDisplayable(mapLines);
1067            } catch (Exception excp) {
1068                System.out.println("Can't open map file " + mapSource);
1069                System.out.println(excp);
1070            }
1071    
1072            final LineDrawing selectBox = new LineDrawing("select");
1073            selectBox.setColor(Color.green);
1074    
1075            final RubberBandBox rbb =
1076                new RubberBandBox(RealType.Longitude, RealType.Latitude, 1);
1077            rbb.setColor(Color.green);
1078            rbb.addAction(new CellImpl() {
1079              public void doAction()
1080                 throws VisADException, RemoteException
1081               {
1082                  Gridded2DSet set = rbb.getBounds();
1083                  float[] low = set.getLow();
1084                  float[] hi = set.getHi();
1085                  x_coords[0] = low[0];
1086                  x_coords[1] = hi[0];
1087                  y_coords[0] = low[1];
1088                  y_coords[1] = hi[1];
1089                  
1090                  SampledSet[] sets = new SampledSet[4];
1091                  sets[0] = new Gridded2DSet(RealTupleType.SpatialEarth2DTuple, new float[][] {{low[0], hi[0]}, {low[1], low[1]}}, 2);
1092                  sets[1] = new Gridded2DSet(RealTupleType.SpatialEarth2DTuple, new float[][] {{hi[0], hi[0]}, {low[1], hi[1]}}, 2);
1093                  sets[2] = new Gridded2DSet(RealTupleType.SpatialEarth2DTuple, new float[][] {{hi[0], low[0]}, {hi[1], hi[1]}}, 2);
1094                  sets[3] = new Gridded2DSet(RealTupleType.SpatialEarth2DTuple, new float[][] {{low[0], low[0]}, {hi[1], low[1]}}, 2);
1095                  UnionSet uset = new UnionSet(sets);
1096                  selectBox.setData(uset);
1097               }
1098            });
1099            dspMaster.addDisplayable(rbb);
1100            dspMaster.addDisplayable(selectBox);
1101    
1102            dspMaster.draw();
1103       }
1104    
1105           public MapProjection getDataProjection() {
1106             MapProjection mp = null;
1107             try {
1108               mp = new ProjectionCoordinateSystem(new LatLonProjection());
1109             } catch (Exception e) {
1110                 System.out.println(" getDataProjection"+e);
1111             }
1112             return mp;
1113           }
1114    
1115          protected JComponent doMakeContents() {
1116            try {
1117              JPanel panel = new JPanel(new BorderLayout());
1118              panel.add("Center", dspMaster.getDisplayComponent());
1119    
1120              JPanel stridePanel = new JPanel(new FlowLayout());
1121              trkStr = new JTextField(Integer.toString(5), 3);
1122              vrtStr = new JTextField(Integer.toString(2), 3);
1123              trkStr.addActionListener(new ActionListener() {
1124                  public void actionPerformed(ActionEvent ae) {
1125                    setTrackStride(Integer.valueOf(trkStr.getText().trim()));
1126                  }
1127              });
1128              vrtStr.addActionListener(new ActionListener() {
1129                  public void actionPerformed(ActionEvent ae) {
1130                    setVerticalStride(Integer.valueOf(vrtStr.getText().trim()));
1131                  }
1132              });
1133    
1134              stridePanel.add(new JLabel("track stride: "));
1135              stridePanel.add(trkStr);
1136              stridePanel.add(new JLabel("vertical stride: "));
1137              stridePanel.add(vrtStr);
1138              panel.add("South", stridePanel);
1139    
1140              return panel;
1141            }
1142            catch (Exception e) {
1143              System.out.println(e);
1144            }
1145            return null;
1146          }
1147                                                                                                                                                         
1148          public void setTrackStride(int stride) {
1149            trackStride = stride;
1150          }
1151    
1152          public void setVerticalStride(int stride) {
1153            verticalStride = stride;
1154          }
1155    
1156          public void setTrackStride() {
1157            trackStride = Integer.valueOf(trkStr.getText().trim());
1158          }
1159    
1160          public void setVerticalStride() {
1161            verticalStride = Integer.valueOf(vrtStr.getText().trim());
1162          }
1163    
1164          public void applyToDataSelection(DataSelection dataSelection) {
1165             setTrackStride();
1166             setVerticalStride();
1167             if (hasSubset) {
1168               GeoSelection geoSelect = new GeoSelection(
1169                    new GeoLocationInfo(y_coords[1], x_coords[0], y_coords[0], x_coords[1]));
1170               geoSelect.setXStride(trackStride);
1171               geoSelect.setYStride(verticalStride);
1172               dataSelection.setGeoSelection(geoSelect);
1173             }
1174          }
1175    }