001/*
002 * $Id: MultiSpectralDataSource.java,v 1.37 2011/03/24 16:06:33 davep Exp $
003 *
004 * This file is part of McIDAS-V
005 *
006 * Copyright 2007-2011
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
031package edu.wisc.ssec.mcidasv.data.hydra;
032
033import java.awt.BorderLayout;
034import java.awt.FlowLayout;
035import java.awt.geom.Rectangle2D;
036
037import java.io.File;
038
039import java.rmi.RemoteException;
040
041import java.util.ArrayList;
042import java.util.Collections;
043import java.util.Enumeration;
044import java.util.HashMap;
045import java.util.Hashtable;
046import java.util.List;
047
048import javax.swing.JComponent;
049import javax.swing.JLabel;
050import javax.swing.JPanel;
051import javax.swing.JSplitPane;
052
053import org.slf4j.Logger;
054import org.slf4j.LoggerFactory;
055
056import ucar.unidata.data.DataCategory;
057import ucar.unidata.data.DataChoice;
058import ucar.unidata.data.DataSelection;
059import ucar.unidata.data.DataSelectionComponent;
060import ucar.unidata.data.DataSourceDescriptor;
061import ucar.unidata.data.DirectDataChoice;
062import ucar.unidata.data.GeoLocationInfo;
063import ucar.unidata.data.GeoSelection;
064import ucar.unidata.util.Misc;
065
066import visad.Data;
067import visad.FlatField;
068import visad.VisADException;
069import visad.georef.MapProjection;
070
071import edu.wisc.ssec.mcidasv.Constants;
072import edu.wisc.ssec.mcidasv.control.LambertAEA;
073import edu.wisc.ssec.mcidasv.data.ComboDataChoice;
074import edu.wisc.ssec.mcidasv.data.HydraDataSource;
075import edu.wisc.ssec.mcidasv.data.PreviewSelection;
076import edu.wisc.ssec.mcidasv.display.hydra.MultiSpectralDisplay;
077
078/**
079 * A data source for Multi Dimension Data 
080 */
081
082public class MultiSpectralDataSource extends HydraDataSource {
083
084        private static final Logger logger = LoggerFactory.getLogger(MultiSpectralDataSource.class);
085        
086        /** Sources file */
087    protected String filename;
088
089    protected MultiDimensionReader reader;
090
091    protected MultiDimensionAdapter[] adapters = null;
092
093    private static final String DATA_DESCRIPTION = "Multi Dimension Data";
094
095
096    private HashMap defaultSubset;
097    private SwathAdapter swathAdapter;
098    private SpectrumAdapter spectrumAdapter;
099    private MultiSpectralData multiSpectData;
100
101    private ArrayList<MultiSpectralData> multiSpectData_s = new ArrayList<MultiSpectralData>();
102    private HashMap<String, MultiSpectralData> adapterMap = new HashMap<String, MultiSpectralData>();
103
104    private List categories;
105    private boolean hasImagePreview = false;
106    private boolean hasChannelSelect = false;
107
108    private boolean doAggregation = false;
109
110    private ComboDataChoice comboChoice;
111
112    private PreviewSelection previewSelection = null;
113    private FlatField previewImage = null;
114
115    public static final String paramKey = "paramKey";
116
117    /**
118     * Zero-argument constructor for construction via unpersistence.
119     */
120    public MultiSpectralDataSource() {}
121
122    /**
123     * Construct a new HYDRA hdf data source.
124     * @param  descriptor  descriptor for this <code>DataSource</code>
125     * @param  fileName  name of the hdf file to read
126     * @param  properties  hashtable of properties
127     *
128     * @throws VisADException problem creating data
129     */
130    public MultiSpectralDataSource(DataSourceDescriptor descriptor,
131                                 String fileName, Hashtable properties)
132            throws VisADException {
133        this(descriptor, Misc.newList(fileName), properties);
134    }
135
136    /**
137     * Construct a new HYDRA hdf data source.
138     * @param  descriptor  descriptor for this <code>DataSource</code>
139     * @param  sources   List of filenames
140     * @param  properties  hashtable of properties
141     *
142     * @throws VisADException problem creating data
143     */
144    public MultiSpectralDataSource(DataSourceDescriptor descriptor,
145                                 List newSources, Hashtable properties)
146            throws VisADException {
147        super(descriptor, newSources, DATA_DESCRIPTION, properties);
148
149        this.filename = (String)sources.get(0);
150
151        try {
152          setup();
153        }
154        catch (Exception e) {
155          e.printStackTrace();
156          throw new VisADException();
157        }
158    }
159
160    public void setup() throws Exception {
161        String name = (new File(filename)).getName();
162        // aggregations will use sets of NetCDFFile readers
163        ArrayList<NetCDFFile> ncdfal = new ArrayList<NetCDFFile>();
164
165        try {
166          if (name.startsWith("NSS.HRPT.NP") && name.endsWith("obs.hdf")) { // get file union
167            reader = NetCDFFile.makeUnion(filename);
168          }
169          else {
170                  if (sources.size() > 1) {
171                          for (int i = 0; i < sources.size(); i++) {
172                                  String s = (String) sources.get(i);
173                                  ncdfal.add(new NetCDFFile(s));
174                          }
175                          doAggregation = true;
176                  } else {
177                          reader = new NetCDFFile(filename);
178                  }
179          }
180        }
181        catch (Exception e) {
182          e.printStackTrace();
183          System.out.println("cannot create NetCDF reader for file: "+filename);
184        }
185                                                                                                                                                     
186        Hashtable<String, String[]> properties = new Hashtable<String, String[]>(); 
187
188
189        multiSpectData_s.clear();
190
191        if ( name.startsWith("AIRS")) {
192          HashMap table = SpectrumAdapter.getEmptyMetadataTable();
193          table.put(SpectrumAdapter.array_name, "L1B_AIRS_Science/Data Fields/radiances");
194          table.put(SpectrumAdapter.range_name, "radiances");
195          table.put(SpectrumAdapter.channelIndex_name, "Channel");
196          table.put(SpectrumAdapter.ancillary_file_name, "/edu/wisc/ssec/mcidasv/data/hydra/resources/airs/L2.chan_prop.2003.11.19.v6.6.9.anc");
197          table.put(SpectrumAdapter.x_dim_name, "GeoXTrack");
198          table.put(SpectrumAdapter.y_dim_name, "GeoTrack");
199          spectrumAdapter = new AIRS_L1B_Spectrum(reader, table);
200                                                                                                                                                     
201          table = SwathAdapter.getEmptyMetadataTable();
202          table.put("array_name", "L1B_AIRS_Science/Data Fields/radiances");
203          table.put(SwathAdapter.range_name, "radiances");
204          table.put("lon_array_name", "L1B_AIRS_Science/Geolocation Fields/Longitude");
205          table.put("lat_array_name", "L1B_AIRS_Science/Geolocation Fields/Latitude");
206          table.put("XTrack", "GeoXTrack");
207          table.put("Track", "GeoTrack");
208          table.put("geo_Track", "GeoTrack");
209          table.put("geo_XTrack", "GeoXTrack");
210          table.put(SpectrumAdapter.channelIndex_name, "Channel"); //- think about this?
211
212          swathAdapter = new SwathAdapter(reader, table);
213          HashMap subset = swathAdapter.getDefaultSubset();
214          subset.put(SpectrumAdapter.channelIndex_name, new double[] {793,793,1});
215          defaultSubset = subset;
216          multiSpectData = new MultiSpectralData(swathAdapter, spectrumAdapter);
217          DataCategory.createCategory("MultiSpectral");
218          categories = DataCategory.parseCategories("MultiSpectral;MultiSpectral;IMAGE");
219          hasChannelSelect = true;
220          multiSpectData.init_wavenumber = 919.5f; 
221          multiSpectData_s.add(multiSpectData);
222       }
223       else if ( name.startsWith("IASI_xxx_1C") && name.endsWith("h5")) {
224          HashMap table = SpectrumAdapter.getEmptyMetadataTable();
225          table.put(SpectrumAdapter.array_name, "U-MARF/EPS/IASI_xxx_1C/DATA/SPECT_DATA");
226          table.put(SpectrumAdapter.channelIndex_name, "dim2");
227          table.put(SpectrumAdapter.x_dim_name, "dim1");
228          table.put(SpectrumAdapter.y_dim_name, "dim0");
229          spectrumAdapter = new IASI_L1C_Spectrum(reader, table);
230                                                                                                                                             
231          table = SwathAdapter.getEmptyMetadataTable();
232          table.put("array_name", "U-MARF/EPS/IASI_xxx_1C/DATA/SPECT_DATA");
233          table.put("lon_array_name", "U-MARF/EPS/IASI_xxx_1C/DATA/SPECT_LON_ARRAY");
234          table.put("lat_array_name", "U-MARF/EPS/IASI_xxx_1C/DATA/SPECT_LAT_ARRAY");
235          table.put("XTrack", "dim1");
236          table.put("Track", "dim0");
237          table.put("geo_XTrack", "dim1");
238          table.put("geo_Track", "dim0");
239          table.put("product_name", "IASI_L1C_xxx");
240          table.put(SpectrumAdapter.channelIndex_name, "dim2");
241          swathAdapter = new IASI_L1C_SwathAdapter(reader, table);
242          HashMap subset = swathAdapter.getDefaultSubset();
243          subset.put(SpectrumAdapter.channelIndex_name, new double[] {793,793,1});
244          defaultSubset = subset;
245          multiSpectData = new MultiSpectralData(swathAdapter, spectrumAdapter);
246          DataCategory.createCategory("MultiSpectral");
247          categories = DataCategory.parseCategories("MultiSpectral;MultiSpectral;");
248          multiSpectData.init_wavenumber = 919.5f; 
249          hasChannelSelect = true;
250          multiSpectData_s.add(multiSpectData);
251       }
252       else if ( name.startsWith("IASI")) {
253          HashMap table = SpectrumAdapter.getEmptyMetadataTable();
254          table.put(SpectrumAdapter.array_name, "observations");
255          table.put(SpectrumAdapter.channelIndex_name, "obsChannelIndex");
256          table.put(SpectrumAdapter.x_dim_name, "obsElement");
257          table.put(SpectrumAdapter.y_dim_name, "obsLine");
258          table.put(SpectrumAdapter.channels_name, "observationChannels");
259          spectrumAdapter = new SpectrumAdapter(reader, table);
260
261          table = SwathAdapter.getEmptyMetadataTable();
262          table.put("array_name", "observations");
263          table.put("lon_array_name", "obsLongitude");
264          table.put("lat_array_name", "obsLatitude");
265          table.put("XTrack", "obsElement");
266          table.put("Track", "obsLine");
267          table.put("geo_XTrack", "obsElement");
268          table.put("geo_Track", "obsLine");
269          table.put(SpectrumAdapter.channelIndex_name, "obsChannelIndex"); //- think about this?
270          swathAdapter = new SwathAdapter(reader, table);
271          HashMap subset = swathAdapter.getDefaultSubset();
272          subset.put(SpectrumAdapter.channelIndex_name, new double[] {793,793,1});
273          defaultSubset = subset;
274          multiSpectData = new MultiSpectralData(swathAdapter, spectrumAdapter);
275          DataCategory.createCategory("MultiSpectral");
276          categories = DataCategory.parseCategories("MultiSpectral;MultiSpectral;");
277          multiSpectData.init_wavenumber = 919.5f; 
278          multiSpectData_s.add(multiSpectData);
279          hasChannelSelect = true;
280       }
281       else if (name.startsWith("MOD021KM") || name.startsWith("MYD021KM") || 
282               (name.startsWith("a1") && (name.indexOf("1000m") > 0)) || 
283               (name.startsWith("t1") && (name.indexOf("1000m") > 0)) ) {
284         HashMap table = SwathAdapter.getEmptyMetadataTable();
285         table.put("array_name", "MODIS_SWATH_Type_L1B/Data Fields/EV_1KM_Emissive");
286         table.put("lon_array_name", "MODIS_SWATH_Type_L1B/Geolocation Fields/Longitude");
287         table.put("lat_array_name", "MODIS_SWATH_Type_L1B/Geolocation Fields/Latitude");
288         table.put("XTrack", "Max_EV_frames");
289         table.put("Track", "10*nscans");
290         table.put("geo_Track", "2*nscans");
291         table.put("geo_XTrack", "1KM_geo_dim");
292         table.put("scale_name", "radiance_scales");
293         table.put("offset_name", "radiance_offsets");
294         table.put("fill_value_name", "_FillValue");
295         table.put("range_name", "Emissive_Bands");
296         table.put(SpectrumAdapter.channelIndex_name, "Band_1KM_Emissive");
297         table.put(SwathAdapter.geo_track_offset_name, Double.toString(2.0));
298         table.put(SwathAdapter.geo_xtrack_offset_name, Double.toString(2.0));
299         table.put(SwathAdapter.geo_track_skip_name, Double.toString(5.0));
300         table.put(SwathAdapter.geo_xtrack_skip_name, Double.toString(5.0));
301         
302         // initialize the aggregation reader object
303         logger.debug("Trying to create MODIS 1K GranuleAggregation reader...");
304         if (doAggregation) {
305                 try {
306                         reader = new GranuleAggregation(ncdfal, 2030, "10*nscans", "Max_EV_frames");
307                 } catch (Exception e) {
308                         throw new VisADException("Unable to initialize aggregation reader");
309                 }
310         }
311
312         swathAdapter = new SwathAdapter(reader, table);
313         swathAdapter.setDefaultStride(10);
314         logger.debug("Trying to create MODIS 1K SwathAdapter..."); 
315
316         HashMap subset = swathAdapter.getDefaultSubset();
317
318         table = SpectrumAdapter.getEmptyMetadataTable();
319         table.put(SpectrumAdapter.array_name, "MODIS_SWATH_Type_L1B/Data Fields/EV_1KM_Emissive");
320         table.put(SpectrumAdapter.channelIndex_name, "Band_1KM_Emissive");
321         table.put(SpectrumAdapter.x_dim_name, "Max_EV_frames");
322         table.put(SpectrumAdapter.y_dim_name, "10*nscans");
323         table.put(SpectrumAdapter.channelValues, new float[]
324           {3.799f,3.992f,3.968f,4.070f,4.476f,4.549f,6.784f,7.345f,8.503f,
325            9.700f,11.000f,12.005f,13.351f,13.717f,13.908f,14.205f});
326         table.put(SpectrumAdapter.bandNames, new String[] 
327           {"20","21","22","23","24","25","27","28","29",
328            "30","31","32","33","34","35","36"});
329         table.put(SpectrumAdapter.channelType, "wavelength");
330         SpectrumAdapter spectrumAdapter = new SpectrumAdapter(reader, table);
331
332         multiSpectData = new MultiSpectralData(swathAdapter, spectrumAdapter, "MODIS", "Aqua");
333         multiSpectData.setInitialWavenumber(11.0f);
334         defaultSubset = multiSpectData.getDefaultSubset();
335
336         previewImage = multiSpectData.getImage(defaultSubset);
337         multiSpectData_s.add(multiSpectData);
338
339         //--- aggregate reflective bands
340         table = SwathAdapter.getEmptyMetadataTable();
341
342         table.put("array_name", "MODIS_SWATH_Type_L1B/Data Fields/EV_1KM_RefSB");
343         table.put("lon_array_name", "MODIS_SWATH_Type_L1B/Geolocation Fields/Longitude");
344         table.put("lat_array_name", "MODIS_SWATH_Type_L1B/Geolocation Fields/Latitude");
345         table.put("XTrack", "Max_EV_frames");
346         table.put("Track", "10*nscans");
347         table.put("geo_Track", "2*nscans");
348         table.put("geo_XTrack", "1KM_geo_dim");
349         table.put("scale_name", "reflectance_scales");
350         table.put("offset_name", "reflectance_offsets");
351         table.put("fill_value_name", "_FillValue");
352         table.put("range_name", "EV_1KM_RefSB");
353         table.put(SpectrumAdapter.channelIndex_name, "Band_1KM_RefSB");
354
355         table.put(SwathAdapter.geo_track_offset_name, Double.toString(2.0));
356         table.put(SwathAdapter.geo_xtrack_offset_name, Double.toString(2.0));
357         table.put(SwathAdapter.geo_track_skip_name, Double.toString(5.0));
358         table.put(SwathAdapter.geo_xtrack_skip_name, Double.toString(5.0));
359
360         SwathAdapter sadapt0 = new SwathAdapter(reader, table);
361         sadapt0.setDefaultStride(10);
362
363         table = SpectrumAdapter.getEmptyMetadataTable();
364         table.put(SpectrumAdapter.array_name, "MODIS_SWATH_Type_L1B/Data Fields/EV_1KM_RefSB");
365         table.put(SpectrumAdapter.channelIndex_name, "Band_1KM_RefSB");
366         table.put(SpectrumAdapter.x_dim_name, "Max_EV_frames");
367         table.put(SpectrumAdapter.y_dim_name, "10*nscans");
368         table.put(SpectrumAdapter.channelValues, new float[]
369            {.412f,.450f,.487f,.531f,.551f,.666f,.668f,.677f,.679f,.748f,
370             .869f,.905f,.936f,.940f,1.375f});
371         table.put(SpectrumAdapter.bandNames, new String[]
372            {"8","9","10","11","12","13lo","13hi","14lo","14hi","15",
373             "16","17","18","19","26"});
374         table.put(SpectrumAdapter.channelType, "wavelength");
375         SpectrumAdapter specadap0 = new SpectrumAdapter(reader, table);
376         MultiSpectralData multispec0 = new MultiSpectralData(sadapt0, specadap0, "Reflectance", "Reflectance", "MODIS", "Aqua");
377
378         DataCategory.createCategory("MultiSpectral");
379         categories = DataCategory.parseCategories("MultiSpectral;MultiSpectral;IMAGE");
380         hasImagePreview = true;
381         hasChannelSelect = true;
382
383         table = SwathAdapter.getEmptyMetadataTable();
384
385         table.put("array_name", "MODIS_SWATH_Type_L1B/Data Fields/EV_250_Aggr1km_RefSB");
386         table.put("lon_array_name", "MODIS_SWATH_Type_L1B/Geolocation Fields/Longitude");
387         table.put("lat_array_name", "MODIS_SWATH_Type_L1B/Geolocation Fields/Latitude");
388         table.put("XTrack", "Max_EV_frames");
389         table.put("Track", "10*nscans");
390         table.put("geo_Track", "2*nscans");
391         table.put("geo_XTrack", "1KM_geo_dim");
392         table.put("scale_name", "reflectance_scales");
393         table.put("offset_name", "reflectance_offsets");
394         table.put("fill_value_name", "_FillValue");
395         table.put("range_name", "Reflective_Bands");
396         table.put(SpectrumAdapter.channelIndex_name, "Band_250M");
397
398         table.put(SwathAdapter.geo_track_offset_name, Double.toString(2.0));
399         table.put(SwathAdapter.geo_xtrack_offset_name, Double.toString(2.0));
400         table.put(SwathAdapter.geo_track_skip_name, Double.toString(5.0));
401         table.put(SwathAdapter.geo_xtrack_skip_name, Double.toString(5.0));
402
403         SwathAdapter sadapt1 = new SwathAdapter(reader, table);
404
405         table = SpectrumAdapter.getEmptyMetadataTable();
406         table.put(SpectrumAdapter.array_name, "MODIS_SWATH_Type_L1B/Data Fields/EV_250_Aggr1km_RefSB");
407         table.put(SpectrumAdapter.channelIndex_name, "Band_250M");
408         table.put(SpectrumAdapter.x_dim_name, "Max_EV_frames");
409         table.put(SpectrumAdapter.y_dim_name, "10*nscans");
410         table.put(SpectrumAdapter.channelValues, new float[]
411            {.650f,.855f});
412         table.put(SpectrumAdapter.bandNames, new String[]
413            {"1","2"});
414         table.put(SpectrumAdapter.channelType, "wavelength");
415         SpectrumAdapter specadap1 = new SpectrumAdapter(reader, table);
416         MultiSpectralData multispec1 = new MultiSpectralData(sadapt1, specadap1, "Reflectance", "Reflectance", "MODIS", "Aqua");
417
418         table = SwathAdapter.getEmptyMetadataTable();
419
420         table.put("array_name", "MODIS_SWATH_Type_L1B/Data Fields/EV_500_Aggr1km_RefSB");
421         table.put("lon_array_name", "MODIS_SWATH_Type_L1B/Geolocation Fields/Longitude");
422         table.put("lat_array_name", "MODIS_SWATH_Type_L1B/Geolocation Fields/Latitude");
423         table.put("XTrack", "Max_EV_frames");
424         table.put("Track", "10*nscans");
425         table.put("geo_Track", "2*nscans");
426         table.put("geo_XTrack", "1KM_geo_dim");
427         table.put("scale_name", "reflectance_scales");
428         table.put("offset_name", "reflectance_offsets");
429         table.put("fill_value_name", "_FillValue");
430         table.put("range_name", "EV_500_Aggr1km_RefSB");
431         table.put(SpectrumAdapter.channelIndex_name, "Band_500M");
432         table.put(SwathAdapter.geo_track_offset_name, Double.toString(2.0));
433         table.put(SwathAdapter.geo_xtrack_offset_name, Double.toString(2.0));
434         table.put(SwathAdapter.geo_track_skip_name, Double.toString(5.0));
435         table.put(SwathAdapter.geo_xtrack_skip_name, Double.toString(5.0));
436
437         SwathAdapter sadapt2 = new SwathAdapter(reader, table);
438
439         table = SpectrumAdapter.getEmptyMetadataTable();
440         table.put(SpectrumAdapter.array_name, "MODIS_SWATH_Type_L1B/Data Fields/EV_500_Aggr1km_RefSB");
441         table.put(SpectrumAdapter.channelIndex_name, "Band_500M");
442         table.put(SpectrumAdapter.x_dim_name, "Max_EV_frames");
443         table.put(SpectrumAdapter.y_dim_name, "10*nscans");
444         table.put(SpectrumAdapter.channelValues, new float[]
445            {.470f,.555f,1.240f,1.638f,2.130f});
446         table.put(SpectrumAdapter.bandNames, new String[]
447            {"3","4","5","6","7"});
448         table.put(SpectrumAdapter.channelType, "wavelength");
449         SpectrumAdapter specadap2 = new SpectrumAdapter(reader, table);
450         MultiSpectralData multispec2 = new MultiSpectralData(sadapt2, specadap2, "Reflectance", "Reflectance", "MODIS", "Aqua");
451
452         MultiSpectralAggr aggr = new MultiSpectralAggr(new MultiSpectralData[] {multispec1, multispec2, multispec0});
453         aggr.setInitialWavenumber(0.650f);
454         aggr.setDataRange(new float[] {0f, 0.8f});
455         multiSpectData_s.add(aggr);
456       }
457       else if (name.startsWith("MOD02QKM") || name.startsWith("MYD02QKM") ||
458               (name.startsWith("a1") && (name.indexOf("250m") > 0)) ||
459               (name.startsWith("t1") && (name.indexOf("250m") > 0)) ) {
460         HashMap table = SwathAdapter.getEmptyMetadataTable();
461         table.put("array_name", "MODIS_SWATH_Type_L1B/Data Fields/EV_250_RefSB");
462         table.put("lon_array_name", "MODIS_SWATH_Type_L1B/Geolocation Fields/Longitude");
463         table.put("lat_array_name", "MODIS_SWATH_Type_L1B/Geolocation Fields/Latitude");
464         table.put("XTrack", "4*Max_EV_frames");
465         table.put("Track", "40*nscans");
466         table.put("geo_Track", "10*nscans");
467         table.put("geo_XTrack", "Max_EV_frames");
468         table.put("scale_name", "reflectance_scales");
469         table.put("offset_name", "reflectance_offsets");
470         table.put("fill_value_name", "_FillValue");
471         table.put("range_name", "Reflective_Bands");
472         table.put(SpectrumAdapter.channelIndex_name, "Band_250M");
473         table.put(SwathAdapter.geo_track_offset_name, Double.toString(0.0));
474         table.put(SwathAdapter.geo_xtrack_offset_name, Double.toString(0.0));
475         table.put(SwathAdapter.geo_track_skip_name, Double.toString(4.0));
476         table.put(SwathAdapter.geo_xtrack_skip_name, Double.toString(4.0));
477
478         swathAdapter = new SwathAdapter(reader, table);
479         swathAdapter.setDefaultStride(40);
480
481         table = SpectrumAdapter.getEmptyMetadataTable();
482         table.put(SpectrumAdapter.array_name, "MODIS_SWATH_Type_L1B/Data Fields/EV_250_RefSB");
483         table.put(SpectrumAdapter.channelIndex_name, "Band_250M");
484         table.put(SpectrumAdapter.x_dim_name, "4*Max_EV_frames");
485         table.put(SpectrumAdapter.y_dim_name, "40*nscans");
486         table.put(SpectrumAdapter.channelValues, new float[]
487            {.650f,.855f});
488         table.put(SpectrumAdapter.bandNames, new String[]
489            {"1","2"});
490         table.put(SpectrumAdapter.channelType, "wavelength");
491         SpectrumAdapter spectrumAdapter = new SpectrumAdapter(reader, table);
492
493         multiSpectData = new MultiSpectralData(swathAdapter, spectrumAdapter, "Reflectance", "Reflectance", "MODIS", "Aqua");
494         multiSpectData.setInitialWavenumber(0.650f);
495         multiSpectData.setDataRange(new float[] {0f, 0.8f});
496         defaultSubset = multiSpectData.getDefaultSubset();
497         previewImage = multiSpectData.getImage(defaultSubset);
498         multiSpectData_s.add(multiSpectData);
499
500         DataCategory.createCategory("MultiSpectral");
501         categories = DataCategory.parseCategories("MultiSpectral;MultiSpectral;IMAGE");
502         hasImagePreview = true;
503         hasChannelSelect = true;
504       }
505       else if (name.startsWith("MOD02HKM") || name.startsWith("MYD02HKM") ||
506               (name.startsWith("a1") && (name.indexOf("500m") > 0)) ||
507               (name.startsWith("t1") && (name.indexOf("500m") > 0)) ) {
508         HashMap table = SwathAdapter.getEmptyMetadataTable();
509         table.put("array_name", "MODIS_SWATH_Type_L1B/Data Fields/EV_250_Aggr500_RefSB");
510         table.put("lon_array_name", "MODIS_SWATH_Type_L1B/Geolocation Fields/Longitude");
511         table.put("lat_array_name", "MODIS_SWATH_Type_L1B/Geolocation Fields/Latitude");
512         table.put("XTrack", "2*Max_EV_frames");
513         table.put("Track", "20*nscans");
514         table.put("geo_Track", "10*nscans");
515         table.put("geo_XTrack", "Max_EV_frames");
516         table.put("scale_name", "reflectance_scales");
517         table.put("offset_name", "reflectance_offsets");
518         table.put("fill_value_name", "_FillValue");
519         table.put("range_name", "Reflective_Bands");
520         table.put(SpectrumAdapter.channelIndex_name, "Band_250M");
521         table.put(SwathAdapter.geo_track_offset_name, Double.toString(0.0));
522         table.put(SwathAdapter.geo_xtrack_offset_name, Double.toString(0.0));
523         table.put(SwathAdapter.geo_track_skip_name, Double.toString(2.0));
524         table.put(SwathAdapter.geo_xtrack_skip_name, Double.toString(2.0));
525
526         SwathAdapter swathAdapter0 = new SwathAdapter(reader, table);
527         swathAdapter0.setDefaultStride(20);
528
529         table = SpectrumAdapter.getEmptyMetadataTable();
530         table.put(SpectrumAdapter.array_name, "MODIS_SWATH_Type_L1B/Data Fields/EV_250_Aggr500_RefSB");
531         table.put(SpectrumAdapter.channelIndex_name, "Band_250M");
532         table.put(SpectrumAdapter.x_dim_name, "2*Max_EV_frames");
533         table.put(SpectrumAdapter.y_dim_name, "20*nscans");
534         table.put(SpectrumAdapter.channelValues, new float[]
535            {.650f,.855f});
536         table.put(SpectrumAdapter.bandNames, new String[]
537            {"1","2"});
538         table.put(SpectrumAdapter.channelType, "wavelength");
539         SpectrumAdapter spectrumAdapter0 = new SpectrumAdapter(reader, table);
540
541         MultiSpectralData multiSpectData0 = new MultiSpectralData(swathAdapter0, spectrumAdapter0, "Reflectance", "Reflectance", "MODIS", "Aqua");
542
543         table = SwathAdapter.getEmptyMetadataTable();
544         table.put("array_name", "MODIS_SWATH_Type_L1B/Data Fields/EV_500_RefSB");
545         table.put("lon_array_name", "MODIS_SWATH_Type_L1B/Geolocation Fields/Longitude");
546         table.put("lat_array_name", "MODIS_SWATH_Type_L1B/Geolocation Fields/Latitude");
547         table.put("XTrack", "2*Max_EV_frames");
548         table.put("Track", "20*nscans");
549         table.put("geo_Track", "10*nscans");
550         table.put("geo_XTrack", "Max_EV_frames");
551         table.put("scale_name", "reflectance_scales");
552         table.put("offset_name", "reflectance_offsets");
553         table.put("fill_value_name", "_FillValue");
554         table.put("range_name", "Reflective_Bands");
555         table.put(SpectrumAdapter.channelIndex_name, "Band_500M");
556         table.put(SwathAdapter.geo_track_offset_name, Double.toString(0.0));
557         table.put(SwathAdapter.geo_xtrack_offset_name, Double.toString(0.0));
558         table.put(SwathAdapter.geo_track_skip_name, Double.toString(2.0));
559         table.put(SwathAdapter.geo_xtrack_skip_name, Double.toString(2.0));
560
561         SwathAdapter swathAdapter1 = new SwathAdapter(reader, table);
562         swathAdapter1.setDefaultStride(20);
563
564         table = SpectrumAdapter.getEmptyMetadataTable();
565         table.put(SpectrumAdapter.array_name, "MODIS_SWATH_Type_L1B/Data Fields/EV_500_RefSB");
566         table.put(SpectrumAdapter.channelIndex_name, "Band_500M");
567         table.put(SpectrumAdapter.x_dim_name, "2*Max_EV_frames");
568         table.put(SpectrumAdapter.y_dim_name, "20*nscans");
569         table.put(SpectrumAdapter.channelValues, new float[]
570            {.470f,.555f,1.240f,1.638f,2.130f});
571         table.put(SpectrumAdapter.bandNames, new String[]
572            {"3","4","5","6","7"});
573         table.put(SpectrumAdapter.channelType, "wavelength");
574         SpectrumAdapter spectrumAdapter1 = new SpectrumAdapter(reader, table);
575
576         MultiSpectralData multiSpectData1 = new MultiSpectralData(swathAdapter1, spectrumAdapter1, "Reflectance", "Reflectance", "MODIS", "Aqua");
577
578         MultiSpectralAggr aggr = 
579            new MultiSpectralAggr(new MultiSpectralData[] {multiSpectData0, multiSpectData1});
580         aggr.setInitialWavenumber(0.650f);
581         aggr.setDataRange(new float[] {0f, 0.8f});
582         multiSpectData_s.add(aggr);
583         multiSpectData = aggr;
584         defaultSubset = aggr.getDefaultSubset();
585         previewImage = aggr.getImage(defaultSubset);
586
587         DataCategory.createCategory("MultiSpectral");
588         categories = DataCategory.parseCategories("MultiSpectral;MultiSpectral;IMAGE");
589         hasImagePreview = true;
590         hasChannelSelect = true;
591       }
592       else if (name.startsWith("NSS")) {
593         HashMap swthTable = SwathAdapter.getEmptyMetadataTable();
594         swthTable.put("array_name", "ch3b_temperature");
595         swthTable.put("lon_array_name", "pixel_longitude");
596         swthTable.put("lat_array_name", "pixel_latitude");
597         swthTable.put("XTrack", "pixels_across_track");
598         swthTable.put("Track", "scan_lines_along_track");
599         swthTable.put("geo_Track", "scan_lines_along_track");
600         swthTable.put("geo_XTrack", "pixels_across_track");
601         swthTable.put("scale_name", "SCALE_FACTOR");
602         swthTable.put("offset_name", "ADD_OFFSET");
603         swthTable.put("fill_value_name", "_FILLVALUE");
604         swthTable.put("range_name", "Emmissive_Bands");
605         swthTable.put("unpack", "unpack");
606
607         SwathAdapter swathAdapter0 = new SwathAdapter(reader, swthTable);
608         swathAdapter0.setDefaultStride(10);
609         HashMap subset = swathAdapter0.getDefaultSubset();
610         defaultSubset = subset;
611
612         HashMap specTable = SpectrumAdapter.getEmptyMetadataTable();
613         specTable.put(SpectrumAdapter.array_name, "ch3b_temperature");
614         specTable.put(SpectrumAdapter.x_dim_name, "pixels_across_track");
615         specTable.put(SpectrumAdapter.y_dim_name, "scan_lines_along_track");
616         specTable.put(SpectrumAdapter.channelValues, new float[] {3.740f});
617         specTable.put(SpectrumAdapter.bandNames, new String[] {"ch3b"});
618         specTable.put(SpectrumAdapter.channelType, "wavelength");
619         SpectrumAdapter spectrumAdapter0 = new SpectrumAdapter(reader, specTable);
620
621         MultiSpectralData multiSpectData0 = new MultiSpectralData(swathAdapter0, spectrumAdapter0, "BrightnessTemp", "BrightnessTemp", null, null);
622
623         HashMap table = SwathAdapter.getEmptyMetadataTable();
624         table.put("array_name", "ch4_temperature");
625         table.put("lon_array_name", "pixel_longitude");
626         table.put("lat_array_name", "pixel_latitude");
627         table.put("XTrack", "pixels_across_track");
628         table.put("Track", "scan_lines_along_track");
629         table.put("geo_Track", "scan_lines_along_track");
630         table.put("geo_XTrack", "pixels_across_track");
631         table.put("scale_name", "SCALE_FACTOR");
632         table.put("offset_name", "ADD_OFFSET");
633         table.put("fill_value_name", "_FILLVALUE");
634         table.put("range_name", "Emmissive_Bands");
635         table.put("unpack", "unpack");
636
637
638         SwathAdapter swathAdapter1 = new SwathAdapter(reader, table);
639         swathAdapter1.setDefaultStride(10);
640
641         table = SpectrumAdapter.getEmptyMetadataTable();
642         table.put(SpectrumAdapter.array_name, "ch4_temperature");
643         table.put(SpectrumAdapter.x_dim_name, "pixels_across_track");
644         table.put(SpectrumAdapter.y_dim_name, "scan_lines_along_track");
645         table.put(SpectrumAdapter.channelValues, new float[] {10.80f});
646         table.put(SpectrumAdapter.bandNames, new String[] {"ch4"});
647         table.put(SpectrumAdapter.channelType, "wavelength");
648         SpectrumAdapter spectrumAdapter1 = new SpectrumAdapter(reader, table);
649
650         MultiSpectralData multiSpectData1 = new MultiSpectralData(swathAdapter1, spectrumAdapter1, "BrightnessTemp", "BrightnessTemp", null, null);
651
652         table = SwathAdapter.getEmptyMetadataTable();
653         table.put("array_name", "ch5_temperature");
654         table.put("lon_array_name", "pixel_longitude");
655         table.put("lat_array_name", "pixel_latitude");
656         table.put("XTrack", "pixels_across_track");
657         table.put("Track", "scan_lines_along_track");
658         table.put("geo_Track", "scan_lines_along_track");
659         table.put("geo_XTrack", "pixels_across_track");
660         table.put("scale_name", "SCALE_FACTOR");
661         table.put("offset_name", "ADD_OFFSET");
662         table.put("fill_value_name", "_FILLVALUE");
663         table.put("range_name", "Emmissive_Bands");
664         table.put("unpack", "unpack");
665
666
667         SwathAdapter swathAdapter2 = new SwathAdapter(reader, table);
668         swathAdapter2.setDefaultStride(10);
669
670         table = SpectrumAdapter.getEmptyMetadataTable();
671         table.put(SpectrumAdapter.array_name, "ch5_temperature");
672         table.put(SpectrumAdapter.x_dim_name, "pixels_across_track");
673         table.put(SpectrumAdapter.y_dim_name, "scan_lines_along_track");
674         table.put(SpectrumAdapter.channelValues, new float[] {12.00f});
675         table.put(SpectrumAdapter.bandNames, new String[] {"ch5"});
676         table.put(SpectrumAdapter.channelType, "wavelength");
677         SpectrumAdapter spectrumAdapter2 = new SpectrumAdapter(reader, table);
678
679         MultiSpectralData multiSpectData2 = new MultiSpectralData(swathAdapter2, spectrumAdapter2, "BrightnessTemp", "BrightnessTemp", null, null);
680
681
682         MultiSpectralAggr aggr = new MultiSpectralAggr(new MultiSpectralData[] {multiSpectData0, multiSpectData1, multiSpectData2});
683         aggr.setInitialWavenumber(3.740f);
684         aggr.setDataRange(new float[] {180f, 340f});
685         multiSpectData = aggr;
686         multiSpectData_s.add(aggr);
687         defaultSubset = aggr.getDefaultSubset();
688         previewImage = aggr.getImage(defaultSubset);
689
690         //- now do the reflective bands
691         swthTable.put("array_name", "ch1_reflectance");
692         swthTable.put("range_name", "Reflective_Bands");
693
694         swathAdapter0 = new SwathAdapter(reader, swthTable);
695         swathAdapter0.setDefaultStride(10);
696
697         specTable.put(SpectrumAdapter.array_name, "ch1_reflectance");
698         specTable.put(SpectrumAdapter.channelValues, new float[] {0.630f});
699         specTable.put(SpectrumAdapter.bandNames, new String[] {"ch1"});
700         spectrumAdapter0 = new SpectrumAdapter(reader, specTable);
701
702         multiSpectData0 = new MultiSpectralData(swathAdapter0, spectrumAdapter0, "Reflectance", "Reflectance", null, null);
703
704         swthTable.put("array_name", "ch2_reflectance");
705         swthTable.put("range_name", "Reflective_Bands");
706         
707         swathAdapter1 = new SwathAdapter(reader, swthTable);
708         swathAdapter1.setDefaultStride(10);
709         
710         specTable.put(SpectrumAdapter.array_name, "ch2_reflectance");
711         specTable.put(SpectrumAdapter.channelValues, new float[] {0.862f});
712         specTable.put(SpectrumAdapter.bandNames, new String[] {"ch2"});
713         spectrumAdapter1 = new SpectrumAdapter(reader, specTable);
714
715         multiSpectData1 = new MultiSpectralData(swathAdapter1, spectrumAdapter1, "Reflectance", "Reflectance", null, null);
716
717         swthTable.put("array_name", "ch3ab_reflectance");
718         swthTable.put("range_name", "Reflective_Bands");
719         
720         swathAdapter2 = new SwathAdapter(reader, swthTable);
721         swathAdapter2.setDefaultStride(10);
722         subset = swathAdapter2.getDefaultSubset();
723         defaultSubset = subset;
724         
725         specTable.put(SpectrumAdapter.array_name, "ch3ab_reflectance");
726         specTable.put(SpectrumAdapter.channelValues, new float[] {1.610f});
727         specTable.put(SpectrumAdapter.bandNames, new String[] {"ch3ab"});
728         spectrumAdapter2 = new SpectrumAdapter(reader, specTable);
729
730         multiSpectData2 = new MultiSpectralData(swathAdapter2, spectrumAdapter2, "Reflectance", "Reflectance", null, null);
731
732         aggr = new MultiSpectralAggr(new MultiSpectralData[] {multiSpectData0, multiSpectData1, multiSpectData2});
733         aggr.setInitialWavenumber(0.630f);
734         aggr.setDataRange(new float[] {0f, 100f});
735         multiSpectData_s.add(aggr);
736
737         categories = DataCategory.parseCategories("MultiSpectral;MultiSpectral;IMAGE");
738
739         hasImagePreview = true;
740         hasChannelSelect = true;
741       }
742       else {
743          HashMap table = SwathAdapter.getEmptyMetadataTable();
744          table.put("array_name", "MODIS_SWATH_Type_L1B/Data Fields/EV_1KM_Emissive");
745          table.put("lon_array_name", "pixel_longitude");
746          table.put("lat_array_name", "pixel_latitude");
747          table.put("XTrack", "elements");
748          table.put("Track", "lines");
749          table.put("geo_Track", "lines");
750          table.put("geo_XTrack", "elements");
751          table.put("scale_name", "scale_factor");
752          table.put("offset_name", "add_offset");
753          table.put("fill_value_name", "_FillValue");
754          swathAdapter = new SwathAdapter(reader, table);
755          categories = DataCategory.parseCategories("2D grid;GRID-2D;");
756          defaultSubset = swathAdapter.getDefaultSubset();
757       }
758       setProperties(properties);
759    }
760
761    public void initAfterUnpersistence() {
762      try {
763        setup();
764      } 
765      catch (Exception e) {
766      }
767    }
768
769    /**
770     * Make and insert the <code>DataChoice</code>-s for this
771     * <code>DataSource</code>.
772     */
773    public void doMakeDataChoices() {
774        try {
775          for (int k=0; k<multiSpectData_s.size(); k++) {
776            MultiSpectralData adapter = multiSpectData_s.get(k);
777            DataChoice choice = doMakeDataChoice(k, adapter);
778            adapterMap.put(choice.getName(), adapter);
779            addDataChoice(choice);
780          }
781        }
782        catch(Exception e) {
783          e.printStackTrace();
784        }
785    }
786
787    public void addChoice(String name, Data data) {
788        ComboDataChoice combo = new ComboDataChoice(name + hashCode(), name, new Hashtable(), data);
789        addDataChoice(combo);
790        getDataContext().dataSourceChanged(this);
791    }
792
793    private DataChoice doMakeDataChoice(int idx, MultiSpectralData adapter) throws Exception {
794        String name = adapter.getName();
795        DataSelection dataSel = new MultiDimensionSubset(defaultSubset);
796        Hashtable subset = new Hashtable();
797        subset.put(MultiDimensionSubset.key, dataSel);
798        subset.put(MultiSpectralDataSource.paramKey, adapter.getParameter());
799        DirectDataChoice ddc = new DirectDataChoice(this, new Integer(idx), name, name, categories, subset);
800        ddc.setProperties(subset);
801        return ddc;
802    }
803
804    /**
805     * Check to see if this <code>HDFHydraDataSource</code> is equal to the object
806     * in question.
807     * @param o  object in question
808     * @return true if they are the same or equivalent objects
809     */
810    public boolean equals(Object o) {
811        if ( !(o instanceof MultiSpectralDataSource)) {
812            return false;
813        }
814        return (this == (MultiSpectralDataSource) o);
815    }
816
817    public MultiSpectralData getMultiSpectralData() {
818      return multiSpectData;
819    }
820
821    public MultiSpectralData getMultiSpectralData(DataChoice choice) {
822      return adapterMap.get(choice.getName());
823    }
824
825    public String getDatasetName() {
826      return filename;
827    }
828
829    public void setDatasetName(String name) {
830      filename = name;
831    }
832
833    public ComboDataChoice getComboDataChoice() {
834      return comboChoice;
835    }
836
837    /**
838     * Called by the IDV's persistence manager in an effort to collect all of
839     * the files that should be included in a zipped bundle.
840     * 
841     * @return Singleton list containing the file that this data source came from.
842     */
843    @Override public List getDataPaths() {
844        return Collections.singletonList(filename);
845    }
846
847    public HashMap getSubsetFromLonLatRect(MultiDimensionSubset select, GeoSelection geoSelection) {
848      GeoLocationInfo ginfo = geoSelection.getBoundingBox();
849      return adapters[0].getSubsetFromLonLatRect(select.getSubset(), ginfo.getMinLat(), ginfo.getMaxLat(),
850                                        ginfo.getMinLon(), ginfo.getMaxLon());
851    }
852
853
854    public synchronized Data getData(DataChoice dataChoice, DataCategory category,
855                                DataSelection dataSelection, Hashtable requestProperties)
856                                throws VisADException, RemoteException {
857       return this.getDataInner(dataChoice, category, dataSelection, requestProperties);
858
859    }
860
861    protected Data getDataInner(DataChoice dataChoice, DataCategory category,
862                                DataSelection dataSelection, Hashtable requestProperties)
863                                throws VisADException, RemoteException {
864
865        //- this hack keeps the HydraImageProbe from doing a getData()
866        //- TODO: need to use categories?
867        if (requestProperties != null) {
868          if ((requestProperties.toString()).contains("ReadoutProbe")) {
869            return null;
870          }
871        }
872
873        GeoLocationInfo ginfo = null;
874        GeoSelection geoSelection = null;
875        
876        if ((dataSelection != null) && (dataSelection.getGeoSelection() != null)) {
877          if (dataSelection.getGeoSelection().getBoundingBox() != null) {
878            geoSelection = dataSelection.getGeoSelection();
879          }
880          else if (dataChoice.getDataSelection() != null) {
881            geoSelection = dataChoice.getDataSelection().getGeoSelection();
882          }
883        }
884
885        if (geoSelection != null) {
886          ginfo = geoSelection.getBoundingBox();
887        }
888
889        Data data = null;
890
891        try {
892            HashMap subset = null;
893            if (ginfo != null) {
894              subset = swathAdapter.getSubsetFromLonLatRect(ginfo.getMinLat(), ginfo.getMaxLat(),
895                                        ginfo.getMinLon(), ginfo.getMaxLon());
896            }
897            else {
898              MultiDimensionSubset select = null;
899              Hashtable table = dataChoice.getProperties();
900              Enumeration keys = table.keys();
901              while (keys.hasMoreElements()) {
902                Object key = keys.nextElement();
903                if (key instanceof MultiDimensionSubset) {
904                  select = (MultiDimensionSubset) table.get(key);
905                }
906              }  
907              if (select != null) {
908                subset = select.getSubset();
909              }
910
911              if (dataSelection != null) {
912                  Hashtable props = dataSelection.getProperties();
913                  if (props != null) {
914                    if (props.containsKey(MultiDimensionSubset.key)) {
915                      subset = (HashMap)((MultiDimensionSubset)props.get(MultiDimensionSubset.key)).getSubset();
916                    }
917                    else {
918                      subset = defaultSubset;
919                    }
920                    if (props.containsKey(SpectrumAdapter.channelIndex_name)) {
921                      int idx = ((Integer) props.get(SpectrumAdapter.channelIndex_name)).intValue();
922                      double[] coords = (double[]) subset.get(SpectrumAdapter.channelIndex_name);
923                      if (coords == null) {
924                        coords = new double[] {(double)idx, (double)idx, (double)1};
925                        subset.put(SpectrumAdapter.channelIndex_name, coords);
926                      }
927                      else {
928                        coords[0] = (double)idx;
929                        coords[1] = (double)idx;
930                        coords[2] = (double)1;
931                      }
932                   }
933                 }
934               }
935            }
936
937            if (subset != null) {
938              MultiSpectralData multiSpectData = getMultiSpectralData(dataChoice);
939              if (multiSpectData != null) {
940                data = multiSpectData.getImage(subset);
941                data = applyProperties(data, requestProperties, subset);
942              }
943            }
944        } catch (Exception e) {
945            e.printStackTrace();
946            System.out.println("getData exception e=" + e);
947        }
948        return data;
949    }
950
951    public MapProjection getDataProjection(HashMap subset) {
952      MapProjection mp = null;
953      try {
954        Rectangle2D rect =  multiSpectData.getLonLatBoundingBox(subset);
955        mp = new LambertAEA(rect);
956      }
957      catch (Exception e) {
958        logException("MultiSpectralDataSource.getDataProjection", e);
959      }
960      return mp;
961    }
962
963    protected Data applyProperties(Data data, Hashtable requestProperties, HashMap subset) 
964          throws VisADException, RemoteException {
965      Data new_data = data;
966
967      if (requestProperties == null) {
968        new_data = data;
969        return new_data;
970      }
971      return new_data;
972    }
973
974    protected void initDataSelectionComponents(
975         List<DataSelectionComponent> components,
976             final DataChoice dataChoice) {
977
978      if (System.getProperty("os.name").equals("Mac OS X") && hasImagePreview && hasChannelSelect) {
979        try {
980          components.add(new ImageChannelSelection(new PreviewSelection(dataChoice, previewImage, null), new ChannelSelection(dataChoice)));
981        } catch (Exception e) {
982          e.printStackTrace();
983        }
984      }
985      else {
986        if (hasImagePreview) {
987          try {
988            previewSelection = new PreviewSelection(dataChoice, previewImage, null);
989            components.add(previewSelection);
990          } catch (Exception e) {
991            System.out.println("Can't make PreviewSelection: "+e);
992            e.printStackTrace();
993          }
994        }
995        if (hasChannelSelect) {
996          try {
997            components.add(new ChannelSelection(dataChoice));
998          } 
999          catch (Exception e) {
1000            e.printStackTrace();
1001          }
1002        }
1003      }
1004    }
1005
1006
1007
1008    /***  Save, but move to better place
1009  public static MapProjection getDataProjection(FlatField fltField) throws Exception {
1010    Rectangle2D rect = MultiSpectralData.getLonLatBoundingBox(fltField);
1011    MapProjection mp = new LambertAEA(rect);
1012    return mp;
1013  }
1014
1015
1016
1017  public static Linear2DSet makeGrid(MapProjection mp, float res) throws Exception {
1018    Rectangle2D rect = mp.getDefaultMapArea();
1019
1020    int xLen = (int) (rect.getWidth()/res);
1021    int yLen = (int) (rect.getHeight()/res);
1022
1023    RealType xmap = RealType.getRealType("xmap", CommonUnit.meter);
1024    RealType ymap = RealType.getRealType("ymap", CommonUnit.meter);
1025
1026    RealTupleType rtt = new visad.RealTupleType(xmap, ymap, mp, null);
1027
1028    Linear2DSet grid = new Linear2DSet(rtt, rect.getX(), (xLen-1)*res, xLen,
1029                                            rect.getY(), (yLen-1)*res, yLen);
1030    return grid;
1031  }
1032
1033 public static FlatField swathToGrid(Linear2DSet grid, FlatField swath) throws Exception {
1034    FunctionType ftype = (FunctionType) swath.getType();
1035    Linear2DSet swathDomain = (Linear2DSet) swath.getDomainSet();
1036    int[] lens = swathDomain.getLengths();
1037    float[][] swathRange = swath.getFloats(false);
1038    int trackLen = lens[1];
1039    int xtrackLen = lens[0];
1040    lens = grid.getLengths();
1041    int gridXLen = lens[0];
1042    int gridYLen = lens[1];
1043
1044    CoordinateSystem swathCoordSys = swathDomain.getCoordinateSystem();
1045    CoordinateSystem gridCoordSys = grid.getCoordinateSystem();
1046
1047    RealTupleType rtt = ((SetType)grid.getType()).getDomain();
1048    FlatField grdFF = new FlatField(new FunctionType(rtt, ftype.getRange()), grid);
1049    float[][] gridRange = grdFF.getFloats(false);
1050
1051    for (int j=0; j < trackLen; j++) {
1052       for (int i=0; i < xtrackLen; i++) {
1053         int idx = j*xtrackLen + i;
1054
1055         float[][] swathCoord = swathDomain.indexToValue(new int[] {idx});
1056         float[][] swathEarthCoord = swathCoordSys.toReference(swathCoord);
1057
1058
1059         float[][] gridCoord = gridCoordSys.fromReference(swathEarthCoord);
1060         int grdIdx = (grid.valueToIndex(gridCoord))[0];
1061
1062         float val = swathRange[0][idx];
1063         for (int n=0; n<2; n++) {
1064           for ( int m=0; m<2; m++) {
1065              int k = grdIdx + (m + n*gridXLen);
1066
1067              if (!(Float.isNaN(val)) && 
1068                  (k >= 0 && (k < gridXLen*gridYLen))) {
1069                float grdVal = gridRange[0][k];
1070                if (Float.isNaN(grdVal)) {
1071                  gridRange[0][k] = val;
1072                }
1073
1074              }
1075           }
1076         }
1077         //if (!(Float.isNaN(val)) && (grdIdx != -1)) {
1078         //  gridRange[0][grdIdx] = val;
1079         //}
1080       }
1081    }
1082    
1083   grdFF.setSamples(gridRange);
1084   return grdFF;
1085 }
1086 ***/
1087
1088
1089}
1090
1091
1092class ChannelSelection extends DataSelectionComponent {
1093
1094  DataChoice dataChoice;
1095  MultiSpectralDisplay display;
1096
1097  ChannelSelection(DataChoice dataChoice) throws Exception {
1098     super("Channels");
1099     this.dataChoice = dataChoice;
1100     display = new MultiSpectralDisplay((DirectDataChoice)dataChoice);
1101     display.showChannelSelector();
1102  }
1103
1104  protected JComponent doMakeContents() {
1105    try {
1106      JPanel panel = new JPanel(new BorderLayout());
1107      panel.add("Center", display.getDisplayComponent());
1108      if (display.getBandSelectComboBox() != null) {
1109        JPanel bandPanel = new JPanel(new FlowLayout());
1110        bandPanel.add(new JLabel("Band: "));
1111        bandPanel.add(display.getBandSelectComboBox());
1112        panel.add("South", bandPanel);
1113      }
1114      return panel;
1115    }
1116    catch (Exception e) {
1117      System.out.println(e);
1118    }
1119    return null;
1120  }
1121
1122  public void applyToDataSelection(DataSelection dataSelection) {
1123      try {
1124        dataSelection.putProperty(Constants.PROP_CHAN, display.getWaveNumber());
1125        dataSelection.putProperty(SpectrumAdapter.channelIndex_name, display.getChannelIndex());
1126      } catch (Exception e) {
1127        e.printStackTrace();
1128      }
1129  }
1130}
1131
1132class ImageChannelSelection extends DataSelectionComponent {
1133   PreviewSelection previewSelection;
1134   ChannelSelection channelSelection;
1135
1136   ImageChannelSelection(PreviewSelection previewSelection, ChannelSelection channelSelection) {
1137     super("MultiSpectral");
1138     this.previewSelection = previewSelection;
1139     this.channelSelection = channelSelection;
1140   }
1141
1142   protected JComponent doMakeContents() {
1143      JSplitPane splitpane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
1144      splitpane.add(previewSelection.doMakeContents());
1145      splitpane.add(channelSelection.doMakeContents());
1146      splitpane.setContinuousLayout(true);
1147      splitpane.setOneTouchExpandable(true);
1148      splitpane.setResizeWeight(1);
1149      splitpane.setDividerSize(12);
1150      return splitpane;
1151   }
1152
1153   public void applyToDataSelection(DataSelection dataSelection) {
1154     previewSelection.applyToDataSelection(dataSelection);
1155     channelSelection.applyToDataSelection(dataSelection);
1156   }
1157
1158
1159}