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