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.FlowLayout;
033    import java.awt.geom.Rectangle2D;
034    
035    import java.io.File;
036    
037    import java.rmi.RemoteException;
038    
039    import java.util.ArrayList;
040    import java.util.Collections;
041    import java.util.Enumeration;
042    import java.util.HashMap;
043    import java.util.Hashtable;
044    import java.util.LinkedHashSet;
045    import java.util.List;
046    
047    import javax.swing.JComponent;
048    import javax.swing.JLabel;
049    import javax.swing.JPanel;
050    import javax.swing.JSplitPane;
051    
052    import org.slf4j.Logger;
053    import org.slf4j.LoggerFactory;
054    
055    import ucar.unidata.data.DataCategory;
056    import ucar.unidata.data.DataChoice;
057    import ucar.unidata.data.DataSelection;
058    import ucar.unidata.data.DataSelectionComponent;
059    import ucar.unidata.data.DataSourceDescriptor;
060    import ucar.unidata.data.DirectDataChoice;
061    import ucar.unidata.data.GeoLocationInfo;
062    import ucar.unidata.data.GeoSelection;
063    import ucar.unidata.util.Misc;
064    
065    import visad.Data;
066    import visad.FlatField;
067    import visad.VisADException;
068    import visad.FunctionType;
069    import visad.RealType;
070    import visad.RealTupleType;
071    import visad.Linear2DSet;
072    import visad.Gridded2DSet;
073    import visad.CoordinateSystem;
074    import visad.CommonUnit;
075    import visad.SetType;
076    import visad.georef.MapProjection;
077    
078    import edu.wisc.ssec.mcidasv.Constants;
079    import edu.wisc.ssec.mcidasv.control.LambertAEA;
080    import edu.wisc.ssec.mcidasv.data.ComboDataChoice;
081    import edu.wisc.ssec.mcidasv.data.HydraDataSource;
082    import edu.wisc.ssec.mcidasv.data.PreviewSelection;
083    import edu.wisc.ssec.mcidasv.display.hydra.MultiSpectralDisplay;
084    
085    /**
086     * A data source for Multi Dimension Data 
087     */
088    
089    public class MultiSpectralDataSource extends HydraDataSource {
090    
091            private static final Logger logger = LoggerFactory.getLogger(MultiSpectralDataSource.class);
092            
093            /** Sources file */
094        protected String filename;
095    
096        protected MultiDimensionReader reader;
097    
098        protected MultiDimensionAdapter[] adapters = null;
099    
100        private static final String DATA_DESCRIPTION = "Multi Dimension Data";
101    
102    
103        private HashMap defaultSubset;
104        private SwathAdapter swathAdapter;
105        private SpectrumAdapter spectrumAdapter;
106        private MultiSpectralData multiSpectData;
107    
108        private ArrayList<MultiSpectralData> multiSpectData_s = new ArrayList<MultiSpectralData>();
109        private HashMap<String, MultiSpectralData> adapterMap = new HashMap<String, MultiSpectralData>();
110    
111        private List categories;
112        private boolean hasImagePreview = false;
113        private boolean hasChannelSelect = false;
114    
115        private boolean doAggregation = false;
116    
117        private ComboDataChoice comboChoice;
118    
119        private PreviewSelection previewSelection = null;
120        private FlatField previewImage = null;
121    
122        public static final String paramKey = "paramKey";
123    
124        /**
125         * Zero-argument constructor for construction via unpersistence.
126         */
127        public MultiSpectralDataSource() {}
128    
129        public MultiSpectralDataSource(String fileName) throws VisADException {
130          this(null, Misc.newList(fileName), null);
131        }
132    
133        /**
134         * Construct a new HYDRA hdf data source.
135         * @param  descriptor  descriptor for this <code>DataSource</code>
136         * @param  fileName  name of the hdf file to read
137         * @param  properties  hashtable of properties
138         *
139         * @throws VisADException problem creating data
140         */
141        public MultiSpectralDataSource(DataSourceDescriptor descriptor,
142                                     String fileName, Hashtable properties)
143                throws VisADException {
144            this(descriptor, Misc.newList(fileName), properties);
145        }
146    
147        /**
148         * Construct a new HYDRA hdf data source.
149         * @param  descriptor  descriptor for this <code>DataSource</code>
150         * @param  sources   List of filenames
151         * @param  properties  hashtable of properties
152         *
153         * @throws VisADException problem creating data
154         */
155        public MultiSpectralDataSource(DataSourceDescriptor descriptor,
156                                     List newSources, Hashtable properties)
157                throws VisADException {
158            super(descriptor, newSources, DATA_DESCRIPTION, properties);
159    
160            this.filename = (String)sources.get(0);
161    
162            try {
163              setup();
164            }
165            catch (Exception e) {
166              e.printStackTrace();
167              throw new VisADException();
168            }
169        }
170    
171        public void setup() throws Exception {
172            String name = (new File(filename)).getName();
173            // aggregations will use sets of NetCDFFile readers
174            ArrayList<NetCDFFile> ncdfal = new ArrayList<NetCDFFile>();
175    
176            try {
177              if (name.startsWith("NSS.HRPT.NP") && name.endsWith("obs.hdf")) { // get file union
178                String other = new String(filename);
179                other = other.replace("obs", "nav");
180                reader = NetCDFFile.makeUnion(filename, other);
181              }
182              /**
183              else if (name.startsWith("MYD021KM")) { //hack test code
184                //reader = new NetCDFFileUnion(new String[] {filename, "/Users/rink/Downloads/MYD03.A2011331.0405.005.2011332200700.hdf"}); 
185                reader = new NetCDFFile(filename);
186              }
187              */
188              else {
189                      if (sources.size() > 1) {
190                              for (int i = 0; i < sources.size(); i++) {
191                                      String s = (String) sources.get(i);
192                                      ncdfal.add(new NetCDFFile(s));
193                              }
194                              doAggregation = true;
195                      } else {
196                              reader = new NetCDFFile(filename);
197                      }
198              }
199            }
200            catch (Exception e) {
201                    e.printStackTrace();
202                    logger.error("Cannot create NetCDF reader for file: " + filename);
203            }
204                                                                                                                                                         
205            Hashtable<String, String[]> properties = new Hashtable<String, String[]>(); 
206    
207            multiSpectData_s.clear();
208    
209            if ( name.startsWith("AIRS")) {
210              HashMap table = SpectrumAdapter.getEmptyMetadataTable();
211              table.put(SpectrumAdapter.array_name, "L1B_AIRS_Science/Data_Fields/radiances");
212              table.put(SpectrumAdapter.range_name, "radiances");
213              table.put(SpectrumAdapter.channelIndex_name, "Channel");
214              table.put(SpectrumAdapter.ancillary_file_name, "/edu/wisc/ssec/mcidasv/data/hydra/resources/airs/L2.chan_prop.2003.11.19.v6.6.9.anc");
215              table.put(SpectrumAdapter.x_dim_name, "GeoXTrack");
216              table.put(SpectrumAdapter.y_dim_name, "GeoTrack");
217              spectrumAdapter = new AIRS_L1B_Spectrum(reader, table);
218                                                                                                                                                         
219              table = SwathAdapter.getEmptyMetadataTable();
220              table.put("array_name", "L1B_AIRS_Science/Data_Fields/radiances");
221              table.put(SwathAdapter.range_name, "radiances");
222              table.put("lon_array_name", "L1B_AIRS_Science/Geolocation_Fields/Longitude");
223              table.put("lat_array_name", "L1B_AIRS_Science/Geolocation_Fields/Latitude");
224              table.put("XTrack", "GeoXTrack");
225              table.put("Track", "GeoTrack");
226              table.put("geo_Track", "GeoTrack");
227              table.put("geo_XTrack", "GeoXTrack");
228              table.put(SpectrumAdapter.channelIndex_name, "Channel"); //- think about this?
229    
230              swathAdapter = new SwathAdapter(reader, table);
231              HashMap subset = swathAdapter.getDefaultSubset();
232              subset.put(SpectrumAdapter.channelIndex_name, new double[] {793,793,1});
233              defaultSubset = subset;
234              multiSpectData = new MultiSpectralData(swathAdapter, spectrumAdapter);
235              DataCategory.createCategory("MultiSpectral");
236              categories = DataCategory.parseCategories("MultiSpectral;MultiSpectral;IMAGE");
237              hasChannelSelect = true;
238              multiSpectData.init_wavenumber = 919.5f; 
239              multiSpectData_s.add(multiSpectData);
240           }
241           else if ( name.startsWith("IASI_xxx_1C") && name.endsWith("h5")) {
242              HashMap table = SpectrumAdapter.getEmptyMetadataTable();
243              table.put(SpectrumAdapter.array_name, "U-MARF/EPS/IASI_xxx_1C/DATA/SPECT_DATA");
244              table.put(SpectrumAdapter.channelIndex_name, "dim2");
245              table.put(SpectrumAdapter.x_dim_name, "dim1");
246              table.put(SpectrumAdapter.y_dim_name, "dim0");
247              spectrumAdapter = new IASI_L1C_Spectrum(reader, table);
248                                                                                                                                                 
249              table = SwathAdapter.getEmptyMetadataTable();
250              table.put("array_name", "U-MARF/EPS/IASI_xxx_1C/DATA/SPECT_DATA");
251              table.put("lon_array_name", "U-MARF/EPS/IASI_xxx_1C/DATA/SPECT_LON_ARRAY");
252              table.put("lat_array_name", "U-MARF/EPS/IASI_xxx_1C/DATA/SPECT_LAT_ARRAY");
253              table.put("XTrack", "dim1");
254              table.put("Track", "dim0");
255              table.put("geo_XTrack", "dim1");
256              table.put("geo_Track", "dim0");
257              table.put("product_name", "IASI_L1C_xxx");
258              table.put(SpectrumAdapter.channelIndex_name, "dim2");
259              swathAdapter = new IASI_L1C_SwathAdapter(reader, table);
260              HashMap subset = swathAdapter.getDefaultSubset();
261              subset.put(SpectrumAdapter.channelIndex_name, new double[] {793,793,1});
262              defaultSubset = subset;
263              multiSpectData = new MultiSpectralData(swathAdapter, spectrumAdapter);
264              DataCategory.createCategory("MultiSpectral");
265              categories = DataCategory.parseCategories("MultiSpectral;MultiSpectral;");
266              multiSpectData.init_wavenumber = 919.5f; 
267              hasChannelSelect = true;
268              multiSpectData_s.add(multiSpectData);
269           }
270           else if ( name.startsWith("IASI")) {
271              HashMap table = SpectrumAdapter.getEmptyMetadataTable();
272              table.put(SpectrumAdapter.array_name, "observations");
273              table.put(SpectrumAdapter.channelIndex_name, "obsChannelIndex");
274              table.put(SpectrumAdapter.x_dim_name, "obsElement");
275              table.put(SpectrumAdapter.y_dim_name, "obsLine");
276              table.put(SpectrumAdapter.channels_name, "observationChannels");
277              spectrumAdapter = new SpectrumAdapter(reader, table);
278    
279              table = SwathAdapter.getEmptyMetadataTable();
280              table.put("array_name", "observations");
281              table.put("lon_array_name", "obsLongitude");
282              table.put("lat_array_name", "obsLatitude");
283              table.put("XTrack", "obsElement");
284              table.put("Track", "obsLine");
285              table.put("geo_XTrack", "obsElement");
286              table.put("geo_Track", "obsLine");
287              table.put(SpectrumAdapter.channelIndex_name, "obsChannelIndex"); //- think about this?
288              swathAdapter = new SwathAdapter(reader, table);
289              HashMap subset = swathAdapter.getDefaultSubset();
290              subset.put(SpectrumAdapter.channelIndex_name, new double[] {793,793,1});
291              defaultSubset = subset;
292              multiSpectData = new MultiSpectralData(swathAdapter, spectrumAdapter);
293              DataCategory.createCategory("MultiSpectral");
294              categories = DataCategory.parseCategories("MultiSpectral;MultiSpectral;");
295              multiSpectData.init_wavenumber = 919.5f; 
296              multiSpectData_s.add(multiSpectData);
297              hasChannelSelect = true;
298           }
299           else if (name.startsWith("MOD021KM") || name.startsWith("MYD021KM") || 
300                   (name.startsWith("a1") && (name.indexOf("1000m") > 0)) || 
301                   (name.startsWith("t1") && (name.indexOf("1000m") > 0)) ) {
302             HashMap table = SwathAdapter.getEmptyMetadataTable();
303             table.put("array_name", "MODIS_SWATH_Type_L1B/Data_Fields/EV_1KM_Emissive");
304             table.put("lon_array_name", "MODIS_SWATH_Type_L1B/Geolocation_Fields/Longitude");
305             table.put("lat_array_name", "MODIS_SWATH_Type_L1B/Geolocation_Fields/Latitude");
306             //table.put("lon_array_name", "MODIS_Swath_Type_GEO/Geolocation_Fields/Longitude");
307             //table.put("lat_array_name", "MODIS_Swath_Type_GEO/Geolocation_Fields/Latitude");
308             table.put("XTrack", "Max_EV_frames");
309             table.put("Track", "10*nscans");
310             table.put("geo_Track", "2*nscans");
311             table.put("geo_XTrack", "1KM_geo_dim");
312             //table.put("geo_Track", "nscans*10");
313             //table.put("geo_XTrack", "mframes");
314             table.put("scale_name", "radiance_scales");
315             table.put("offset_name", "radiance_offsets");
316             table.put("fill_value_name", "_FillValue");
317             table.put("range_name", "Emissive_Bands");
318             table.put(SpectrumAdapter.channelIndex_name, "Band_1KM_Emissive");
319             table.put(SwathAdapter.geo_track_offset_name, Double.toString(2.0));
320             table.put(SwathAdapter.geo_xtrack_offset_name, Double.toString(2.0));
321             table.put(SwathAdapter.geo_track_skip_name, Double.toString(5.0));
322             table.put(SwathAdapter.geo_xtrack_skip_name, Double.toString(5.0));
323             table.put(SwathAdapter.multiScaleDimensionIndex, Integer.toString(0));
324             
325             // initialize the aggregation reader object
326             logger.debug("Trying to create MODIS 1K GranuleAggregation reader...");
327             LinkedHashSet<String> products = new LinkedHashSet<String>();
328             products.add((String) table.get("array_name"));
329             products.add("MODIS_SWATH_Type_L1B/Data_Fields/EV_1KM_RefSB");
330             products.add("MODIS_SWATH_Type_L1B/Data_Fields/EV_250_Aggr1km_RefSB");
331             products.add("MODIS_SWATH_Type_L1B/Data_Fields/EV_500_Aggr1km_RefSB");
332             products.add("MODIS_SWATH_Type_L1B/Data_Fields/EV_250_Aggr500_RefSB");
333             products.add("MODIS_SWATH_Type_L1B/Data_Fields/EV_250_RefSB");
334             products.add("MODIS_SWATH_Type_L1B/Data_Fields/EV_500_RefSB");
335             products.add((String) table.get("lon_array_name"));
336             products.add((String) table.get("lat_array_name"));
337             if (doAggregation) {
338                     try {
339                             reader = new GranuleAggregation(ncdfal, products, "10*nscans", "2*nscans", "Max_EV_frames");
340                     } catch (Exception e) {
341                             throw new VisADException("Unable to initialize aggregation reader");
342                     }
343             }
344    
345             swathAdapter = new SwathAdapter(reader, table);
346             swathAdapter.setDefaultStride(10);
347             logger.debug("Trying to create MODIS 1K SwathAdapter..."); 
348    
349             HashMap subset = swathAdapter.getDefaultSubset();
350    
351             table = SpectrumAdapter.getEmptyMetadataTable();
352             table.put(SpectrumAdapter.array_name, "MODIS_SWATH_Type_L1B/Data_Fields/EV_1KM_Emissive");
353             table.put(SpectrumAdapter.channelIndex_name, "Band_1KM_Emissive");
354             table.put(SpectrumAdapter.x_dim_name, "Max_EV_frames");
355             table.put(SpectrumAdapter.y_dim_name, "10*nscans");
356             table.put(SpectrumAdapter.channelValues, new float[]
357               {3.799f,3.992f,3.968f,4.070f,4.476f,4.549f,6.784f,7.345f,8.503f,
358                9.700f,11.000f,12.005f,13.351f,13.717f,13.908f,14.205f});
359             table.put(SpectrumAdapter.bandNames, new String[] 
360               {"20","21","22","23","24","25","27","28","29",
361                "30","31","32","33","34","35","36"});
362             table.put(SpectrumAdapter.channelType, "wavelength");
363             SpectrumAdapter spectrumAdapter = new SpectrumAdapter(reader, table);
364    
365             multiSpectData = new MultiSpectralData(swathAdapter, spectrumAdapter, "MODIS", "Aqua");
366             multiSpectData.setInitialWavenumber(11.0f);
367             defaultSubset = multiSpectData.getDefaultSubset();
368    
369             previewImage = multiSpectData.getImage(defaultSubset);
370             multiSpectData_s.add(multiSpectData);
371    
372             //--- aggregate reflective bands
373             table = SwathAdapter.getEmptyMetadataTable();
374    
375             table.put("array_name", "MODIS_SWATH_Type_L1B/Data_Fields/EV_1KM_RefSB");
376             table.put("lon_array_name", "MODIS_SWATH_Type_L1B/Geolocation_Fields/Longitude");
377             table.put("lat_array_name", "MODIS_SWATH_Type_L1B/Geolocation_Fields/Latitude");
378             table.put("XTrack", "Max_EV_frames");
379             table.put("Track", "10*nscans");
380             table.put("geo_Track", "2*nscans");
381             table.put("geo_XTrack", "1KM_geo_dim");
382             table.put("scale_name", "reflectance_scales");
383             table.put("offset_name", "reflectance_offsets");
384             table.put("fill_value_name", "_FillValue");
385             table.put("range_name", "EV_1KM_RefSB");
386             table.put(SpectrumAdapter.channelIndex_name, "Band_1KM_RefSB");
387    
388             table.put(SwathAdapter.geo_track_offset_name, Double.toString(2.0));
389             table.put(SwathAdapter.geo_xtrack_offset_name, Double.toString(2.0));
390             table.put(SwathAdapter.geo_track_skip_name, Double.toString(5.0));
391             table.put(SwathAdapter.geo_xtrack_skip_name, Double.toString(5.0));
392             table.put(SwathAdapter.multiScaleDimensionIndex, Integer.toString(0));
393    
394             SwathAdapter sadapt0 = new SwathAdapter(reader, table);
395             sadapt0.setDefaultStride(10);
396    
397             table = SpectrumAdapter.getEmptyMetadataTable();
398             table.put(SpectrumAdapter.array_name, "MODIS_SWATH_Type_L1B/Data_Fields/EV_1KM_RefSB");
399             table.put(SpectrumAdapter.channelIndex_name, "Band_1KM_RefSB");
400             table.put(SpectrumAdapter.x_dim_name, "Max_EV_frames");
401             table.put(SpectrumAdapter.y_dim_name, "10*nscans");
402             table.put(SpectrumAdapter.channelValues, new float[]
403                {.412f,.450f,.487f,.531f,.551f,.666f,.668f,.677f,.679f,.748f,
404                 .869f,.905f,.936f,.940f,1.375f});
405             table.put(SpectrumAdapter.bandNames, new String[]
406                {"8","9","10","11","12","13lo","13hi","14lo","14hi","15",
407                 "16","17","18","19","26"});
408             table.put(SpectrumAdapter.channelType, "wavelength");
409             SpectrumAdapter specadap0 = new SpectrumAdapter(reader, table);
410             MultiSpectralData multispec0 = new MultiSpectralData(sadapt0, specadap0, "Reflectance", "Reflectance", "MODIS", "Aqua");
411    
412             DataCategory.createCategory("MultiSpectral");
413             categories = DataCategory.parseCategories("MultiSpectral;MultiSpectral;IMAGE");
414             hasImagePreview = true;
415             hasChannelSelect = true;
416    
417             table = SwathAdapter.getEmptyMetadataTable();
418    
419             table.put("array_name", "MODIS_SWATH_Type_L1B/Data_Fields/EV_250_Aggr1km_RefSB");
420             table.put("lon_array_name", "MODIS_SWATH_Type_L1B/Geolocation_Fields/Longitude");
421             table.put("lat_array_name", "MODIS_SWATH_Type_L1B/Geolocation_Fields/Latitude");
422             table.put("XTrack", "Max_EV_frames");
423             table.put("Track", "10*nscans");
424             table.put("geo_Track", "2*nscans");
425             table.put("geo_XTrack", "1KM_geo_dim");
426             table.put("scale_name", "reflectance_scales");
427             table.put("offset_name", "reflectance_offsets");
428             table.put("fill_value_name", "_FillValue");
429             table.put("range_name", "Reflective_Bands");
430             table.put(SpectrumAdapter.channelIndex_name, "Band_250M");
431    
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             table.put(SwathAdapter.multiScaleDimensionIndex, Integer.toString(0));
437    
438             SwathAdapter sadapt1 = new SwathAdapter(reader, table);
439    
440             table = SpectrumAdapter.getEmptyMetadataTable();
441             table.put(SpectrumAdapter.array_name, "MODIS_SWATH_Type_L1B/Data_Fields/EV_250_Aggr1km_RefSB");
442             table.put(SpectrumAdapter.channelIndex_name, "Band_250M");
443             table.put(SpectrumAdapter.x_dim_name, "Max_EV_frames");
444             table.put(SpectrumAdapter.y_dim_name, "10*nscans");
445             table.put(SpectrumAdapter.channelValues, new float[]
446                {.650f,.855f});
447             table.put(SpectrumAdapter.bandNames, new String[]
448                {"1","2"});
449             table.put(SpectrumAdapter.channelType, "wavelength");
450             SpectrumAdapter specadap1 = new SpectrumAdapter(reader, table);
451             MultiSpectralData multispec1 = new MultiSpectralData(sadapt1, specadap1, "Reflectance", "Reflectance", "MODIS", "Aqua");
452    
453             table = SwathAdapter.getEmptyMetadataTable();
454    
455             table.put("array_name", "MODIS_SWATH_Type_L1B/Data_Fields/EV_500_Aggr1km_RefSB");
456             table.put("lon_array_name", "MODIS_SWATH_Type_L1B/Geolocation_Fields/Longitude");
457             table.put("lat_array_name", "MODIS_SWATH_Type_L1B/Geolocation_Fields/Latitude");
458             table.put("XTrack", "Max_EV_frames");
459             table.put("Track", "10*nscans");
460             table.put("geo_Track", "2*nscans");
461             table.put("geo_XTrack", "1KM_geo_dim");
462             table.put("scale_name", "reflectance_scales");
463             table.put("offset_name", "reflectance_offsets");
464             table.put("fill_value_name", "_FillValue");
465             table.put("range_name", "EV_500_Aggr1km_RefSB");
466             table.put(SpectrumAdapter.channelIndex_name, "Band_500M");
467             table.put(SwathAdapter.geo_track_offset_name, Double.toString(2.0));
468             table.put(SwathAdapter.geo_xtrack_offset_name, Double.toString(2.0));
469             table.put(SwathAdapter.geo_track_skip_name, Double.toString(5.0));
470             table.put(SwathAdapter.geo_xtrack_skip_name, Double.toString(5.0));
471             table.put(SwathAdapter.multiScaleDimensionIndex, Integer.toString(0));
472    
473    
474             SwathAdapter sadapt2 = new SwathAdapter(reader, table);
475    
476    
477             table = SpectrumAdapter.getEmptyMetadataTable();
478             table.put(SpectrumAdapter.array_name, "MODIS_SWATH_Type_L1B/Data_Fields/EV_500_Aggr1km_RefSB");
479             table.put(SpectrumAdapter.channelIndex_name, "Band_500M");
480             table.put(SpectrumAdapter.x_dim_name, "Max_EV_frames");
481             table.put(SpectrumAdapter.y_dim_name, "10*nscans");
482             table.put(SpectrumAdapter.channelValues, new float[]
483                {.470f,.555f,1.240f,1.638f,2.130f});
484             table.put(SpectrumAdapter.bandNames, new String[]
485                {"3","4","5","6","7"});
486             table.put(SpectrumAdapter.channelType, "wavelength");
487             SpectrumAdapter specadap2 = new SpectrumAdapter(reader, table);
488             MultiSpectralData multispec2 = new MultiSpectralData(sadapt2, specadap2, "Reflectance", "Reflectance", "MODIS", "Aqua");
489    
490             MultiSpectralAggr aggr = new MultiSpectralAggr(new MultiSpectralData[] {multispec1, multispec2, multispec0});
491             aggr.setInitialWavenumber(0.650f);
492             aggr.setDataRange(new float[] {0f, 0.8f});
493             multiSpectData_s.add(aggr);
494           }
495           else if (name.startsWith("MOD02QKM") || name.startsWith("MYD02QKM") ||
496                   (name.startsWith("a1") && (name.indexOf("250m") > 0)) ||
497                   (name.startsWith("t1") && (name.indexOf("250m") > 0)) ) {
498             HashMap table = SwathAdapter.getEmptyMetadataTable();
499             table.put("array_name", "MODIS_SWATH_Type_L1B/Data_Fields/EV_250_RefSB");
500             table.put("lon_array_name", "MODIS_SWATH_Type_L1B/Geolocation_Fields/Longitude");
501             table.put("lat_array_name", "MODIS_SWATH_Type_L1B/Geolocation_Fields/Latitude");
502             table.put("XTrack", "4*Max_EV_frames");
503             table.put("Track", "40*nscans");
504             table.put("geo_Track", "10*nscans");
505             table.put("geo_XTrack", "Max_EV_frames");
506             table.put("scale_name", "reflectance_scales");
507             table.put("offset_name", "reflectance_offsets");
508             table.put("fill_value_name", "_FillValue");
509             table.put("range_name", "Reflective_Bands");
510             table.put(SpectrumAdapter.channelIndex_name, "Band_250M");
511             table.put(SwathAdapter.geo_track_offset_name, Double.toString(0.0));
512             table.put(SwathAdapter.geo_xtrack_offset_name, Double.toString(0.0));
513             table.put(SwathAdapter.geo_track_skip_name, Double.toString(4.0));
514             table.put(SwathAdapter.geo_xtrack_skip_name, Double.toString(4.0));
515             table.put(SwathAdapter.multiScaleDimensionIndex, Integer.toString(0));
516             // initialize the aggregation reader object
517             logger.debug("Trying to create MODIS 1K GranuleAggregation reader...");
518             LinkedHashSet<String> products = new LinkedHashSet<String>();
519             products.add((String) table.get("array_name"));
520             products.add("MODIS_SWATH_Type_L1B/Data_Fields/EV_250_RefSB");
521             products.add((String) table.get("lon_array_name"));
522             products.add((String) table.get("lat_array_name"));
523             if (doAggregation) {
524                     try {
525                             reader = new GranuleAggregation(ncdfal, products, "40*nscans", "10*nscans", "4*Max_EV_frames");
526                     } catch (Exception e) {
527                             throw new VisADException("Unable to initialize aggregation reader");
528                     }
529             }
530             swathAdapter = new SwathAdapter(reader, table);
531             swathAdapter.setDefaultStride(40);
532    
533             table = SpectrumAdapter.getEmptyMetadataTable();
534             table.put(SpectrumAdapter.array_name, "MODIS_SWATH_Type_L1B/Data_Fields/EV_250_RefSB");
535             table.put(SpectrumAdapter.channelIndex_name, "Band_250M");
536             table.put(SpectrumAdapter.x_dim_name, "4*Max_EV_frames");
537             table.put(SpectrumAdapter.y_dim_name, "40*nscans");
538             table.put(SpectrumAdapter.channelValues, new float[]
539                {.650f,.855f});
540             table.put(SpectrumAdapter.bandNames, new String[]
541                {"1","2"});
542             table.put(SpectrumAdapter.channelType, "wavelength");
543             SpectrumAdapter spectrumAdapter = new SpectrumAdapter(reader, table);
544    
545             multiSpectData = new MultiSpectralData(swathAdapter, spectrumAdapter, "Reflectance", "Reflectance", "MODIS", "Aqua");
546             multiSpectData.setInitialWavenumber(0.650f);
547             multiSpectData.setDataRange(new float[] {0f, 0.8f});
548             defaultSubset = multiSpectData.getDefaultSubset();
549             previewImage = multiSpectData.getImage(defaultSubset);
550             multiSpectData_s.add(multiSpectData);
551    
552             DataCategory.createCategory("MultiSpectral");
553             categories = DataCategory.parseCategories("MultiSpectral;MultiSpectral;IMAGE");
554             hasImagePreview = true;
555             hasChannelSelect = true;
556    
557             multiSpectData_s.add(null);
558           }
559           else if (name.startsWith("MOD02HKM") || name.startsWith("MYD02HKM") ||
560                   (name.startsWith("a1") && (name.indexOf("500m") > 0)) ||
561                   (name.startsWith("t1") && (name.indexOf("500m") > 0)) ) {
562             HashMap table = SwathAdapter.getEmptyMetadataTable();
563             table.put("array_name", "MODIS_SWATH_Type_L1B/Data_Fields/EV_250_Aggr500_RefSB");
564             table.put("lon_array_name", "MODIS_SWATH_Type_L1B/Geolocation_Fields/Longitude");
565             table.put("lat_array_name", "MODIS_SWATH_Type_L1B/Geolocation_Fields/Latitude");
566             table.put("XTrack", "2*Max_EV_frames");
567             table.put("Track", "20*nscans");
568             table.put("geo_Track", "10*nscans");
569             table.put("geo_XTrack", "Max_EV_frames");
570             table.put("scale_name", "reflectance_scales");
571             table.put("offset_name", "reflectance_offsets");
572             table.put("fill_value_name", "_FillValue");
573             table.put("range_name", "Reflective_Bands");
574             table.put(SpectrumAdapter.channelIndex_name, "Band_250M");
575             table.put(SwathAdapter.geo_track_offset_name, Double.toString(0.0));
576             table.put(SwathAdapter.geo_xtrack_offset_name, Double.toString(0.0));
577             table.put(SwathAdapter.geo_track_skip_name, Double.toString(2.0));
578             table.put(SwathAdapter.geo_xtrack_skip_name, Double.toString(2.0));
579             table.put(SwathAdapter.multiScaleDimensionIndex, Integer.toString(0));
580    
581             // initialize the aggregation reader object
582             logger.debug("Trying to create MODIS 1K GranuleAggregation reader...");
583             LinkedHashSet<String> products = new LinkedHashSet<String>();
584             products.add((String) table.get("array_name"));
585             products.add("MODIS_SWATH_Type_L1B/Data_Fields/EV_500_RefSB");
586             products.add("MODIS_SWATH_Type_L1B/Data_Fields/EV_250_Aggr500_RefSB");
587             products.add((String) table.get("lon_array_name"));
588             products.add((String) table.get("lat_array_name"));
589             if (doAggregation) {
590                     try {
591                             reader = new GranuleAggregation(ncdfal, products, "20*nscans", "10*nscans", "2*Max_EV_frames");
592                     } catch (Exception e) {
593                             throw new VisADException("Unable to initialize aggregation reader");
594                     }
595             }
596    
597             SwathAdapter swathAdapter0 = new SwathAdapter(reader, table);
598             swathAdapter0.setDefaultStride(20);
599    
600             table = SpectrumAdapter.getEmptyMetadataTable();
601             table.put(SpectrumAdapter.array_name, "MODIS_SWATH_Type_L1B/Data_Fields/EV_250_Aggr500_RefSB");
602             table.put(SpectrumAdapter.channelIndex_name, "Band_250M");
603             table.put(SpectrumAdapter.x_dim_name, "2*Max_EV_frames");
604             table.put(SpectrumAdapter.y_dim_name, "20*nscans");
605             table.put(SpectrumAdapter.channelValues, new float[]
606                {.650f,.855f});
607             table.put(SpectrumAdapter.bandNames, new String[]
608                {"1","2"});
609             table.put(SpectrumAdapter.channelType, "wavelength");
610             SpectrumAdapter spectrumAdapter0 = new SpectrumAdapter(reader, table);
611    
612             MultiSpectralData multiSpectData0 = new MultiSpectralData(swathAdapter0, spectrumAdapter0, "Reflectance", "Reflectance", "MODIS", "Aqua");
613    
614             table = SwathAdapter.getEmptyMetadataTable();
615             table.put("array_name", "MODIS_SWATH_Type_L1B/Data_Fields/EV_500_RefSB");
616             table.put("lon_array_name", "MODIS_SWATH_Type_L1B/Geolocation_Fields/Longitude");
617             table.put("lat_array_name", "MODIS_SWATH_Type_L1B/Geolocation_Fields/Latitude");
618             table.put("XTrack", "2*Max_EV_frames");
619             table.put("Track", "20*nscans");
620             table.put("geo_Track", "10*nscans");
621             table.put("geo_XTrack", "Max_EV_frames");
622             table.put("scale_name", "reflectance_scales");
623             table.put("offset_name", "reflectance_offsets");
624             table.put("fill_value_name", "_FillValue");
625             table.put("range_name", "Reflective_Bands");
626             table.put(SpectrumAdapter.channelIndex_name, "Band_500M");
627             table.put(SwathAdapter.geo_track_offset_name, Double.toString(0.0));
628             table.put(SwathAdapter.geo_xtrack_offset_name, Double.toString(0.0));
629             table.put(SwathAdapter.geo_track_skip_name, Double.toString(2.0));
630             table.put(SwathAdapter.geo_xtrack_skip_name, Double.toString(2.0));
631             table.put(SwathAdapter.multiScaleDimensionIndex, Integer.toString(0));
632    
633             SwathAdapter swathAdapter1 = new SwathAdapter(reader, table);
634             swathAdapter1.setDefaultStride(20);
635    
636             table = SpectrumAdapter.getEmptyMetadataTable();
637             table.put(SpectrumAdapter.array_name, "MODIS_SWATH_Type_L1B/Data_Fields/EV_500_RefSB");
638             table.put(SpectrumAdapter.channelIndex_name, "Band_500M");
639             table.put(SpectrumAdapter.x_dim_name, "2*Max_EV_frames");
640             table.put(SpectrumAdapter.y_dim_name, "20*nscans");
641             table.put(SpectrumAdapter.channelValues, new float[]
642                {.470f,.555f,1.240f,1.638f,2.130f});
643             table.put(SpectrumAdapter.bandNames, new String[]
644                {"3","4","5","6","7"});
645             table.put(SpectrumAdapter.channelType, "wavelength");
646             SpectrumAdapter spectrumAdapter1 = new SpectrumAdapter(reader, table);
647    
648             MultiSpectralData multiSpectData1 = new MultiSpectralData(swathAdapter1, spectrumAdapter1, "Reflectance", "Reflectance", "MODIS", "Aqua");
649    
650             MultiSpectralAggr aggr = 
651                new MultiSpectralAggr(new MultiSpectralData[] {multiSpectData0, multiSpectData1});
652             aggr.setInitialWavenumber(0.650f);
653             aggr.setDataRange(new float[] {0f, 0.8f});
654             multiSpectData_s.add(aggr);
655             multiSpectData = aggr;
656             defaultSubset = aggr.getDefaultSubset();
657             previewImage = aggr.getImage(defaultSubset);
658    
659             DataCategory.createCategory("MultiSpectral");
660             categories = DataCategory.parseCategories("MultiSpectral;MultiSpectral;IMAGE");
661             hasImagePreview = true;
662             hasChannelSelect = true;
663    
664             multiSpectData_s.add(null);
665           }
666           else if (name.startsWith("NSS.HRPT") && name.endsWith("level2.hdf")) {
667             HashMap swthTable = SwathAdapter.getEmptyMetadataTable();
668             swthTable.put("array_name", "temp_3_75um_nom");
669             swthTable.put("lon_array_name", "longitude");
670             swthTable.put("lat_array_name", "latitude");
671             swthTable.put("XTrack", "pixel_elements_along_scan_direction");
672             swthTable.put("Track", "scan_lines_along_track_direction");
673             swthTable.put("geo_Track", "scan_lines_along_track_direction");
674             swthTable.put("geo_XTrack", "pixel_elements_along_scan_direction");
675             swthTable.put("scale_name", "SCALE_FACTOR");
676             swthTable.put("offset_name", "ADD_OFFSET");
677             swthTable.put("fill_value_name", "_FILLVALUE");
678             swthTable.put("range_name", "Emmissive_Bands");
679             swthTable.put("unpack", "unpack");
680             swthTable.put("geo_scale_name", "SCALE_FACTOR");
681             swthTable.put("geo_offset_name", "ADD_OFFSET");
682             swthTable.put("geo_fillValue_name", "_FILLVALUE");
683    
684    
685             SwathAdapter swathAdapter0 = new SwathAdapter(reader, swthTable);
686             swathAdapter0.setDefaultStride(10);
687             HashMap subset = swathAdapter0.getDefaultSubset();
688             defaultSubset = subset;
689    
690             HashMap specTable = SpectrumAdapter.getEmptyMetadataTable();
691             specTable.put(SpectrumAdapter.array_name, "temp_3_75um_nom");
692             specTable.put(SpectrumAdapter.x_dim_name, "pixel_elements_along_scan_direction");
693             specTable.put(SpectrumAdapter.y_dim_name, "scan_lines_along_track_direction");
694             specTable.put(SpectrumAdapter.channelValues, new float[] {3.740f});
695             specTable.put(SpectrumAdapter.bandNames, new String[] {"ch3b"});
696             specTable.put(SpectrumAdapter.channelType, "wavelength");
697             SpectrumAdapter spectrumAdapter0 = new SpectrumAdapter(reader, specTable);
698    
699             MultiSpectralData multiSpectData0 = new MultiSpectralData(swathAdapter0, spectrumAdapter0, "BrightnessTemp", "BrightnessTemp", null, null);
700    
701             HashMap table = SwathAdapter.getEmptyMetadataTable();
702             table.put("array_name", "temp_11_0um_nom");
703             table.put("lon_array_name", "longitude");
704             table.put("lat_array_name", "latitude");
705             table.put("XTrack", "pixel_elements_along_scan_direction");
706             table.put("Track", "scan_lines_along_track_direction");
707             table.put("geo_Track", "scan_lines_along_track_direction");
708             table.put("geo_XTrack", "pixel_elements_along_scan_direction");
709             table.put("scale_name", "SCALE_FACTOR");
710             table.put("offset_name", "ADD_OFFSET");
711             table.put("fill_value_name", "_FILLVALUE");
712             table.put("range_name", "Emmissive_Bands");
713             table.put("unpack", "unpack");
714             table.put("geo_scale_name", "SCALE_FACTOR");
715             table.put("geo_offset_name", "ADD_OFFSET");
716             table.put("geo_fillValue_name", "_FILLVALUE");
717    
718    
719             SwathAdapter swathAdapter1 = new SwathAdapter(reader, table);
720             swathAdapter1.setDefaultStride(10);
721    
722             table = SpectrumAdapter.getEmptyMetadataTable();
723             table.put(SpectrumAdapter.array_name, "temp_11_0um_nom");
724             table.put(SpectrumAdapter.x_dim_name, "pixel_elements_along_scan_direction");
725             table.put(SpectrumAdapter.y_dim_name, "scan_lines_along_track_direction");
726             table.put(SpectrumAdapter.channelValues, new float[] {10.80f});
727             table.put(SpectrumAdapter.bandNames, new String[] {"ch4"});
728             table.put(SpectrumAdapter.channelType, "wavelength");
729             SpectrumAdapter spectrumAdapter1 = new SpectrumAdapter(reader, table);
730    
731             MultiSpectralData multiSpectData1 = new MultiSpectralData(swathAdapter1, spectrumAdapter1, "BrightnessTemp", "BrightnessTemp", null, null);
732    
733             table = SwathAdapter.getEmptyMetadataTable();
734             table.put("array_name", "temp_12_0um_nom");
735             table.put("lon_array_name", "longitude");
736             table.put("lat_array_name", "latitude");
737             table.put("XTrack", "pixel_elements_along_scan_direction");
738             table.put("Track", "scan_lines_along_track_direction");
739             table.put("geo_Track", "scan_lines_along_track_direction");
740             table.put("geo_XTrack", "pixel_elements_along_scan_direction");
741             table.put("scale_name", "SCALE_FACTOR");
742             table.put("offset_name", "ADD_OFFSET");
743             table.put("fill_value_name", "_FILLVALUE");
744             table.put("range_name", "Emmissive_Bands");
745             table.put("unpack", "unpack");
746             table.put("geo_scale_name", "SCALE_FACTOR");
747             table.put("geo_offset_name", "ADD_OFFSET");
748             table.put("geo_fillValue_name", "_FILLVALUE");
749    
750    
751             SwathAdapter swathAdapter2 = new SwathAdapter(reader, table);
752             swathAdapter2.setDefaultStride(10);
753    
754             table = SpectrumAdapter.getEmptyMetadataTable();
755             table.put(SpectrumAdapter.array_name, "temp_12_0um_nom");
756             table.put(SpectrumAdapter.x_dim_name, "pixel_elements_along_scan_direction");
757             table.put(SpectrumAdapter.y_dim_name, "scan_lines_along_track_direction");
758             table.put(SpectrumAdapter.channelValues, new float[] {12.00f});
759             table.put(SpectrumAdapter.bandNames, new String[] {"ch5"});
760             table.put(SpectrumAdapter.channelType, "wavelength");
761             SpectrumAdapter spectrumAdapter2 = new SpectrumAdapter(reader, table);
762    
763             MultiSpectralData multiSpectData2 = new MultiSpectralData(swathAdapter2, spectrumAdapter2, "BrightnessTemp", "BrightnessTemp", null, null);
764    
765    
766             MultiSpectralAggr aggr = new MultiSpectralAggr(new MultiSpectralData[] {multiSpectData0, multiSpectData1, multiSpectData2});
767             aggr.setInitialWavenumber(3.740f);
768             aggr.setDataRange(new float[] {180f, 340f});
769             multiSpectData = aggr;
770             multiSpectData_s.add(aggr);
771             defaultSubset = aggr.getDefaultSubset();
772             previewImage = aggr.getImage(defaultSubset);
773    
774             //- now do the reflective bands
775             swthTable.put("array_name", "refl_0_65um_nom");
776             swthTable.put("range_name", "Reflective_Bands");
777    
778             swathAdapter0 = new SwathAdapter(reader, swthTable);
779             swathAdapter0.setDefaultStride(10);
780    
781             specTable.put(SpectrumAdapter.array_name, "refl_0_65um_nom");
782             specTable.put(SpectrumAdapter.channelValues, new float[] {0.630f});
783             specTable.put(SpectrumAdapter.bandNames, new String[] {"ch1"});
784             spectrumAdapter0 = new SpectrumAdapter(reader, specTable);
785    
786             multiSpectData0 = new MultiSpectralData(swathAdapter0, spectrumAdapter0, "Reflectance", "Reflectance", null, null);
787    
788             swthTable.put("array_name", "refl_0_86um_nom");
789             swthTable.put("range_name", "Reflective_Bands");
790             
791             swathAdapter1 = new SwathAdapter(reader, swthTable);
792             swathAdapter1.setDefaultStride(10);
793             
794             specTable.put(SpectrumAdapter.array_name, "refl_0_86um_nom");
795             specTable.put(SpectrumAdapter.channelValues, new float[] {0.862f});
796             specTable.put(SpectrumAdapter.bandNames, new String[] {"ch2"});
797             spectrumAdapter1 = new SpectrumAdapter(reader, specTable);
798    
799             multiSpectData1 = new MultiSpectralData(swathAdapter1, spectrumAdapter1, "Reflectance", "Reflectance", null, null);
800    
801             swthTable.put("array_name", "refl_1_60um_nom");
802             swthTable.put("range_name", "Reflective_Bands");
803             
804             swathAdapter2 = new SwathAdapter(reader, swthTable);
805             swathAdapter2.setDefaultStride(10);
806             subset = swathAdapter2.getDefaultSubset();
807             defaultSubset = subset;
808             
809             specTable.put(SpectrumAdapter.array_name, "refl_1_60um_nom");
810             specTable.put(SpectrumAdapter.channelValues, new float[] {1.610f});
811             specTable.put(SpectrumAdapter.bandNames, new String[] {"ch3ab"});
812             spectrumAdapter2 = new SpectrumAdapter(reader, specTable);
813    
814             multiSpectData2 = new MultiSpectralData(swathAdapter2, spectrumAdapter2, "Reflectance", "Reflectance", null, null);
815    
816             aggr = new MultiSpectralAggr(new MultiSpectralData[] {multiSpectData0, multiSpectData1, multiSpectData2});
817             aggr.setInitialWavenumber(0.630f);
818             aggr.setDataRange(new float[] {0f, 100f});
819             multiSpectData_s.add(aggr);
820    
821             categories = DataCategory.parseCategories("MultiSpectral;MultiSpectral;IMAGE");
822    
823             hasImagePreview = true;
824             hasChannelSelect = true;
825           }
826           else {
827              HashMap table = SwathAdapter.getEmptyMetadataTable();
828              table.put("array_name", "MODIS_SWATH_Type_L1B/Data_Fields/EV_1KM_Emissive");
829              table.put("lon_array_name", "pixel_longitude");
830              table.put("lat_array_name", "pixel_latitude");
831              table.put("XTrack", "elements");
832              table.put("Track", "lines");
833              table.put("geo_Track", "lines");
834              table.put("geo_XTrack", "elements");
835              table.put("scale_name", "scale_factor");
836              table.put("offset_name", "add_offset");
837              table.put("fill_value_name", "_FillValue");
838              swathAdapter = new SwathAdapter(reader, table);
839              categories = DataCategory.parseCategories("2D grid;GRID-2D;");
840              defaultSubset = swathAdapter.getDefaultSubset();
841           }
842           setProperties(properties);
843        }
844    
845        public void initAfterUnpersistence() {
846          try {
847            setup();
848          } 
849          catch (Exception e) {
850          }
851        }
852    
853        /**
854         * Make and insert the <code>DataChoice</code>-s for this
855         * <code>DataSource</code>.
856         */
857        public void doMakeDataChoices() {
858            try {
859              for (int k=0; k<multiSpectData_s.size(); k++) {
860                MultiSpectralData adapter = multiSpectData_s.get(k);
861                DataChoice choice = doMakeDataChoice(k, adapter);
862                adapterMap.put(choice.getName(), adapter);
863                addDataChoice(choice);
864              }
865            }
866            catch(Exception e) {
867              e.printStackTrace();
868            }
869        }
870    
871        public void addChoice(String name, Data data) {
872            ComboDataChoice combo = new ComboDataChoice(name + hashCode(), name, new Hashtable(), data);
873            addDataChoice(combo);
874            getDataContext().dataSourceChanged(this);
875        }
876    
877        private DataChoice doMakeDataChoice(int idx, MultiSpectralData adapter) throws Exception {
878            String name = "_    ";
879            DataSelection dataSel = new MultiDimensionSubset();
880            if (adapter != null) {
881              name = adapter.getName();
882              //dataSel = new MultiDimensionSubset(defaultSubset);
883              dataSel = new MultiDimensionSubset(adapter.getDefaultSubset());
884            }
885    
886            Hashtable subset = new Hashtable();
887            subset.put(MultiDimensionSubset.key, dataSel);
888            if (adapter != null) {
889              subset.put(MultiSpectralDataSource.paramKey, adapter.getParameter());
890            }
891    
892            DirectDataChoice ddc = new DirectDataChoice(this, new Integer(idx), name, name, categories, subset);
893            ddc.setProperties(subset);
894            return ddc;
895        }
896    
897        /**
898         * Check to see if this <code>HDFHydraDataSource</code> is equal to the object
899         * in question.
900         * @param o  object in question
901         * @return true if they are the same or equivalent objects
902         */
903        public boolean equals(Object o) {
904            if ( !(o instanceof MultiSpectralDataSource)) {
905                return false;
906            }
907            return (this == (MultiSpectralDataSource) o);
908        }
909    
910        public MultiSpectralData getMultiSpectralData() {
911          return multiSpectData;
912        }
913    
914        public MultiSpectralData getMultiSpectralData(DataChoice choice) {
915          return adapterMap.get(choice.getName());
916        }
917    
918        public MultiSpectralData getMultiSpectralData(String name) {
919          return adapterMap.get(name);
920        }
921    
922        public MultiSpectralData getMultiSpectralData(int idx) {
923          return multiSpectData_s.get(idx);
924        }
925    
926        public String getDatasetName() {
927          return filename;
928        }
929    
930        public void setDatasetName(String name) {
931          filename = name;
932        }
933    
934        public ComboDataChoice getComboDataChoice() {
935          return comboChoice;
936        }
937    
938        /**
939         * Called by the IDV's persistence manager in an effort to collect all of
940         * the files that should be included in a zipped bundle.
941         * 
942         * @return Singleton list containing the file that this data source came from.
943         */
944        @Override public List getDataPaths() {
945            return Collections.singletonList(filename);
946        }
947    
948      /**
949        public HashMap getSubsetFromLonLatRect(MultiDimensionSubset select, GeoSelection geoSelection) {
950          GeoLocationInfo ginfo = geoSelection.getBoundingBox();
951          return adapters[0].getSubsetFromLonLatRect(select.getSubset(), ginfo.getMinLat(), ginfo.getMaxLat(),
952                                            ginfo.getMinLon(), ginfo.getMaxLon());
953        }
954       */
955    
956        public synchronized Data getData(String name, HashMap subset) throws VisADException, RemoteException {
957          MultiSpectralData msd =  getMultiSpectralData(name);
958          Data data = null;
959          try {
960            data = msd.getImage(subset);
961          } catch (Exception e) {
962            e.printStackTrace();
963          }
964          return data;
965        }
966    
967    
968        public synchronized Data getData(DataChoice dataChoice, DataCategory category,
969                                    DataSelection dataSelection, Hashtable requestProperties)
970                                    throws VisADException, RemoteException {
971           return this.getDataInner(dataChoice, category, dataSelection, requestProperties);
972    
973        }
974    
975        protected Data getDataInner(DataChoice dataChoice, DataCategory category,
976                                    DataSelection dataSelection, Hashtable requestProperties)
977                                    throws VisADException, RemoteException {
978    
979            //- this hack keeps the HydraImageProbe from doing a getData()
980            //- TODO: need to use categories?
981            if (requestProperties != null) {
982              if ((requestProperties.toString()).contains("ReadoutProbe")) {
983                return null;
984              }
985            }
986    
987            GeoLocationInfo ginfo = null;
988            GeoSelection geoSelection = null;
989            
990            if ((dataSelection != null) && (dataSelection.getGeoSelection() != null)) {
991              if (dataSelection.getGeoSelection().getBoundingBox() != null) {
992                geoSelection = dataSelection.getGeoSelection();
993              }
994              else if (dataChoice.getDataSelection() != null) {
995                geoSelection = dataChoice.getDataSelection().getGeoSelection();
996              }
997            }
998    
999            if (geoSelection != null) {
1000              ginfo = geoSelection.getBoundingBox();
1001            }
1002    
1003            Data data = null;
1004    
1005            try {
1006                HashMap subset = null;
1007                if (ginfo != null) {
1008                  subset = swathAdapter.getSubsetFromLonLatRect(ginfo.getMinLat(), ginfo.getMaxLat(),
1009                                            ginfo.getMinLon(), ginfo.getMaxLon());
1010                }
1011                else {
1012                  MultiDimensionSubset select = null;
1013                  Hashtable table = dataChoice.getProperties();
1014                  Enumeration keys = table.keys();
1015                  while (keys.hasMoreElements()) {
1016                    Object key = keys.nextElement();
1017                    if (key instanceof MultiDimensionSubset) {
1018                      select = (MultiDimensionSubset) table.get(key);
1019                    }
1020                  }  
1021                  if (select != null) {
1022                    subset = select.getSubset();
1023                  }
1024    
1025                  if (dataSelection != null) {
1026                      Hashtable props = dataSelection.getProperties();
1027                      if (props != null) {
1028                        if (props.containsKey(MultiDimensionSubset.key)) {
1029                          subset = (HashMap)((MultiDimensionSubset)props.get(MultiDimensionSubset.key)).getSubset();
1030                        }
1031                        else {
1032                          subset = defaultSubset;
1033                        }
1034                        if (props.containsKey(SpectrumAdapter.channelIndex_name)) {
1035                          int idx = ((Integer) props.get(SpectrumAdapter.channelIndex_name)).intValue();
1036                          double[] coords = (double[]) subset.get(SpectrumAdapter.channelIndex_name);
1037                          if (coords == null) {
1038                            coords = new double[] {(double)idx, (double)idx, (double)1};
1039                            subset.put(SpectrumAdapter.channelIndex_name, coords);
1040                          }
1041                          else {
1042                            coords[0] = (double)idx;
1043                            coords[1] = (double)idx;
1044                            coords[2] = (double)1;
1045                          }
1046                       }
1047                     }
1048                   }
1049                }
1050    
1051                if (subset != null) {
1052                  MultiSpectralData multiSpectData = getMultiSpectralData(dataChoice);
1053                  if (multiSpectData != null) {
1054                    data = multiSpectData.getImage(subset);
1055                    data = applyProperties(data, requestProperties, subset);
1056                  }
1057                }
1058            } catch (Exception e) {
1059                e.printStackTrace();
1060                System.out.println("getData exception e=" + e);
1061            }
1062            return data;
1063        }
1064    
1065        public MapProjection getDataProjection(HashMap subset) {
1066          MapProjection mp = null;
1067          try {
1068            Rectangle2D rect =  multiSpectData.getLonLatBoundingBox(subset);
1069            mp = new LambertAEA(rect);
1070          }
1071          catch (Exception e) {
1072            logException("MultiSpectralDataSource.getDataProjection", e);
1073          }
1074          return mp;
1075        }
1076    
1077        protected Data applyProperties(Data data, Hashtable requestProperties, HashMap subset) 
1078              throws VisADException, RemoteException {
1079          Data new_data = data;
1080    
1081          if (requestProperties == null) {
1082            new_data = data;
1083            return new_data;
1084          }
1085          return new_data;
1086        }
1087    
1088        protected void initDataSelectionComponents(
1089             List<DataSelectionComponent> components,
1090                 final DataChoice dataChoice) {
1091    
1092          if (System.getProperty("os.name").equals("Mac OS X") && hasImagePreview && hasChannelSelect) {
1093            try {
1094              components.add(new ImageChannelSelection(new PreviewSelection(dataChoice, previewImage, null), new ChannelSelection(dataChoice)));
1095            } catch (Exception e) {
1096              e.printStackTrace();
1097            }
1098          }
1099          else {
1100            if (hasImagePreview) {
1101              try {
1102                previewSelection = new PreviewSelection(dataChoice, previewImage, null);
1103                components.add(previewSelection);
1104              } catch (Exception e) {
1105                System.out.println("Can't make PreviewSelection: "+e);
1106                e.printStackTrace();
1107              }
1108            }
1109            if (hasChannelSelect) {
1110              try {
1111                components.add(new ChannelSelection(dataChoice));
1112              } 
1113              catch (Exception e) {
1114                e.printStackTrace();
1115              }
1116            }
1117          }
1118        }
1119    
1120    
1121      public static MapProjection getDataProjection(FlatField fltField) throws Exception {
1122        Rectangle2D rect = MultiSpectralData.getLonLatBoundingBox(fltField);
1123        MapProjection mp = new LambertAEA(rect, false);
1124        return mp;
1125      }
1126    
1127       public static MapProjection getSwathProjection(FlatField image, float[][] corners) throws VisADException, RemoteException {
1128          MapProjection mp = null;
1129          FunctionType fnc_type = (FunctionType) image.getType();
1130          RealTupleType rtt = fnc_type.getDomain();
1131          CoordinateSystem cs = rtt.getCoordinateSystem();
1132          Gridded2DSet domainSet = (Gridded2DSet) image.getDomainSet();
1133    
1134          if (cs instanceof visad.CachingCoordinateSystem) {
1135             cs = ((visad.CachingCoordinateSystem)cs).getCachedCoordinateSystem();
1136          }
1137    
1138          if (cs instanceof LongitudeLatitudeCoordinateSystem) {
1139             try {
1140               mp = new LambertAEA(corners);
1141             } catch (Exception e) {
1142               System.out.println(" getDataProjection"+e);
1143             }
1144             return mp;
1145          }
1146          else {
1147             return null;
1148          }
1149       }
1150    
1151    
1152      public static Linear2DSet makeGrid(MapProjection mp, double res) throws Exception {
1153        Rectangle2D rect = mp.getDefaultMapArea();
1154    
1155        int xLen = (int) (rect.getWidth()/res);
1156        int yLen = (int) (rect.getHeight()/res);
1157    
1158        RealType xmap = RealType.getRealType("xmap", CommonUnit.meter);
1159        RealType ymap = RealType.getRealType("ymap", CommonUnit.meter);
1160    
1161        RealTupleType rtt = new visad.RealTupleType(xmap, ymap, mp, null);
1162    
1163        Linear2DSet grid = new Linear2DSet(rtt, rect.getX(), (xLen-1)*res, xLen,
1164                                                rect.getY(), (yLen-1)*res, yLen);
1165        return grid;
1166      }
1167    
1168      public static Linear2DSet makeGrid(MapProjection mp, float[][] corners, float res) throws Exception {
1169         float[][] xy = mp.fromReference(corners);
1170    
1171         float min_x = Float.MAX_VALUE;
1172         float min_y = Float.MAX_VALUE;
1173         float max_x = -Float.MAX_VALUE;
1174         float max_y = -Float.MAX_VALUE;
1175    
1176         for (int k=0; k<xy[0].length;k++) {
1177           if (xy[0][k] < min_x) min_x = xy[0][k];
1178           if (xy[1][k] < min_y) min_y = xy[1][k];
1179           if (xy[0][k] > max_x) max_x = xy[0][k];
1180           if (xy[1][k] > max_y) max_y = xy[1][k];
1181         }
1182    
1183         RealType xmap = RealType.getRealType("xmap", CommonUnit.meter);
1184         RealType ymap = RealType.getRealType("ymap", CommonUnit.meter);
1185    
1186         RealTupleType rtt = new visad.RealTupleType(xmap, ymap, mp, null);
1187    
1188         min_x = ((int) (min_x/res)) * res;
1189         max_x = ((int) (max_x/res)) * res;
1190         min_y = ((int) (min_y/res)) * res;
1191         max_y = ((int) (max_y/res)) * res;
1192    
1193         float del_x = max_x - min_x;
1194         float del_y = max_y - min_y;
1195    
1196         int xLen = (int) (del_x/res);
1197         int yLen = (int) (del_y/res);
1198    
1199         Linear2DSet grid = new Linear2DSet(rtt, min_x, min_x + (xLen-1)*res, xLen,
1200                                                 min_y, min_y + (yLen-1)*res, yLen);
1201    
1202         return grid;
1203      }
1204    
1205      public static FlatField swathToGridOld(Linear2DSet grid, FlatField swath) throws Exception {
1206        return swathToGridOld(grid, swath, 0.0);
1207      }
1208    
1209      private static int count = 0;
1210    
1211      public static FlatField swathToGridOld(Linear2DSet grid, FlatField[] swaths, double mode) throws Exception {
1212        FunctionType ftype = (FunctionType) swaths[0].getType();
1213        visad.Set domSet = swaths[0].getDomainSet();
1214    
1215        FlatField swath = new FlatField(new FunctionType(ftype.getDomain(),
1216            new RealTupleType(new RealType[] {RealType.getRealType("redimage_"+count), RealType.getRealType("greenimage_"+count), RealType.getRealType("blueimage_"+count)})), domSet);
1217    
1218        swath.setSamples(new float[][] 
1219            {swaths[0].getFloats(false)[0], swaths[1].getFloats(false)[0], swaths[2].getFloats(false)[0]});
1220    
1221        count++;
1222    
1223        return swathToGridOld(grid, swath, mode);
1224      }
1225    
1226      public static FlatField swathToGrid(Linear2DSet grid, FlatField[] swaths, double mode) throws Exception {
1227        FunctionType ftype = (FunctionType) swaths[0].getType();
1228        visad.Set domSet = swaths[0].getDomainSet();
1229    
1230        FlatField swath = new FlatField(new FunctionType(ftype.getDomain(),
1231            new RealTupleType(new RealType[] {RealType.getRealType("redimage_"+count), RealType.getRealType("greenimage_"+count), RealType.getRealType("blueimage_"+count)})), domSet);
1232    
1233        swath.setSamples(new float[][]
1234            {swaths[0].getFloats(false)[0], swaths[1].getFloats(false)[0], swaths[2].getFloats(false)[0]});
1235    
1236        count++;
1237    
1238        return swathToGrid(grid, swath, mode);
1239      }
1240    
1241    
1242      public static FlatField swathToGridOld(Linear2DSet grid, FlatField swath, double mode) throws Exception {
1243        FunctionType ftype = (FunctionType) swath.getType();
1244        Linear2DSet swathDomain = (Linear2DSet) swath.getDomainSet();
1245        int[] lens = swathDomain.getLengths();
1246        float[][] swathRange = swath.getFloats(false);
1247        int trackLen = lens[1];
1248        int xtrackLen = lens[0];
1249        int gridLen = grid.getLength();
1250        lens = grid.getLengths();
1251        int gridXLen = lens[0];
1252        int gridYLen = lens[1];
1253    
1254        CoordinateSystem swathCoordSys = swathDomain.getCoordinateSystem();
1255        CoordinateSystem gridCoordSys = grid.getCoordinateSystem();
1256    
1257        RealTupleType rtt = ((SetType)grid.getType()).getDomain();
1258        FlatField grdFF = new FlatField(new FunctionType(rtt, ftype.getRange()), grid);
1259        float[][] gridRange = grdFF.getFloats(false);
1260        int rngTupDim = gridRange.length;
1261    
1262        float[][] swathGridCoord = new float[2][gridLen];
1263        java.util.Arrays.fill(swathGridCoord[0], Float.NaN);
1264    
1265        int[] swathIndexAtGrid = null;
1266        if (true) {
1267          swathIndexAtGrid = new int[gridLen];
1268        }
1269    
1270        for (int j=0; j < trackLen; j++) {
1271           for (int i=0; i < xtrackLen; i++) {
1272             int swathIdx = j*xtrackLen + i;
1273             float val = swathRange[0][swathIdx];
1274    
1275             float[][] swathCoord = swathDomain.indexToValue(new int[] {swathIdx});
1276             float[][] swathEarthCoord = swathCoordSys.toReference(swathCoord);
1277    
1278             float[][] gridValue = gridCoordSys.fromReference(swathEarthCoord);
1279             float[][] gridCoord = grid.valueToGrid(gridValue);
1280             float g0 = gridCoord[0][0];
1281             float g1 = gridCoord[1][0];
1282             int grdIdx  = (g0 != g0 || g1 != g1) ? -1 : ((int) (g0 + 0.5)) + gridXLen * ((int) (g1 + 0.5));
1283    
1284    
1285                   int m=0;
1286                   int n=0;
1287                   int k = grdIdx + (m + n*gridXLen);
1288    
1289                   if ( !(Float.isNaN(val)) && ((k >=0) && (k < gridXLen*gridYLen)) ) { // val or val[rngTupDim] ?
1290                     float grdVal = gridRange[0][k];
1291    
1292                     if (Float.isNaN(grdVal)) {
1293                       for (int t=0; t<rngTupDim; t++) {
1294                         gridRange[t][k] = swathRange[t][swathIdx];
1295                       }
1296                       swathGridCoord[0][k] = gridCoord[0][0];
1297                       swathGridCoord[1][k] = gridCoord[1][0];
1298                       swathIndexAtGrid[k] = swathIdx;
1299                     }
1300                     else {
1301                       /**
1302                       // compare current to last distance
1303                       float[][] gridLoc = grid.indexToValue(new int[] {k});
1304                       gridLoc = grid.valueToGrid(gridLoc);
1305                       
1306                       float del_0 = swathGridCoord[0][k] - gridLoc[0][0];
1307                       float del_1 = swathGridCoord[1][k] - gridLoc[1][0];
1308                       float last_dst_sqrd = del_0*del_0 + del_1*del_1;
1309    
1310                       del_0 = gridCoord[0][0] - gridLoc[0][0];
1311                       del_1 = gridCoord[1][0] - gridLoc[1][0];
1312                       float dst_sqrd = del_0*del_0 + del_1*del_1;
1313    
1314                       if (dst_sqrd < last_dst_sqrd) {
1315                         for (int t=0; t<rngTupDim; t++) {
1316                           gridRange[t][k] = val;
1317                         }
1318                         swathGridCoord[0][k] = gridCoord[0][0];
1319                         swathGridCoord[1][k] = gridCoord[1][0];
1320                         swathIndexAtGrid[k] = swathIdx;
1321                       }
1322                       **/
1323                     }
1324    
1325                   }
1326           }
1327        }
1328    
1329    
1330        // 2nd pass weighted average
1331        float[][] gCoord = new float[2][1];
1332        if (mode > 0.0) {
1333        float weight = 1f;
1334        float[] sumValue = new float[rngTupDim];
1335        for (int j=2; j<gridYLen-2; j++) {
1336           for (int i=2; i<gridXLen-2; i++) {
1337             int grdIdx = i + j*gridXLen;
1338         
1339             // dont do weighted average if a nearest neigbhor existed for the grid point
1340             if (mode == 2.0) {
1341               if (!Float.isNaN(gridRange[0][grdIdx])) {
1342                 continue;
1343               }
1344             }
1345    
1346             gCoord[0][0] = swathGridCoord[0][grdIdx];
1347             gCoord[1][0] = swathGridCoord[1][grdIdx];
1348             float del_0 = gCoord[0][0] - (float) i;
1349             float del_1 = gCoord[1][0] - (float) j;
1350             float dst_sqrd = del_0*del_0 + del_1*del_1;
1351             
1352             int num = 0;
1353             float sumWeights = 0f;
1354             for (int t=0; t<rngTupDim; t++) sumValue[t] = 0f;
1355             for (int n = -1; n < 2; n++) {
1356                for (int m = -1; m < 2; m++) {
1357                   int k = grdIdx + (m + n*gridXLen);
1358    
1359                   if ( !Float.isNaN(swathGridCoord[0][k]) ) {
1360    
1361                      gCoord[0][0] = swathGridCoord[0][k];
1362                      gCoord[1][0] = swathGridCoord[1][k];
1363                      del_0 = gCoord[0][0] - (float) i;
1364                      del_1 = gCoord[1][0] - (float) j;
1365                      dst_sqrd = del_0*del_0 + del_1*del_1;
1366                      //weight = (float) (1.0/Math.exp((double)(dst_sqrd)*2.75f));
1367                      weight = (float) (1.08/Math.exp((double)(dst_sqrd)*5.40f));
1368    
1369                      for (int t=0; t<rngTupDim; t++) sumValue[t] += swathRange[t][swathIndexAtGrid[k]]*weight;
1370                      sumWeights += weight;
1371                      num++;
1372                   }
1373                }
1374              }
1375              for (int t=0; t<rngTupDim; t++) {
1376                gridRange[t][grdIdx] = sumValue[t]/sumWeights;
1377              }
1378           }
1379          }
1380        }
1381    
1382       grdFF.setSamples(gridRange);
1383    
1384       return grdFF;
1385     }
1386    
1387      public static FlatField swathToGrid(Linear2DSet grid, FlatField swath, double mode) throws Exception {
1388        FunctionType ftype = (FunctionType) swath.getType();
1389        Linear2DSet swathDomain = (Linear2DSet) swath.getDomainSet();
1390        int[] lens = swathDomain.getLengths();
1391        float[][] swathRange = swath.getFloats(false);
1392        int trackLen = lens[1];
1393        int xtrackLen = lens[0];
1394        int gridLen = grid.getLength();
1395        lens = grid.getLengths();
1396        int gridXLen = lens[0];
1397        int gridYLen = lens[1];
1398    
1399        CoordinateSystem swathCoordSys = swathDomain.getCoordinateSystem();
1400        CoordinateSystem gridCoordSys = grid.getCoordinateSystem();
1401    
1402        RealTupleType rtt = ((SetType)grid.getType()).getDomain();
1403        FlatField grdFF = new FlatField(new FunctionType(rtt, ftype.getRange()), grid);
1404        float[][] gridRange = grdFF.getFloats(false);
1405        int rngTupDim = gridRange.length;
1406    
1407        float[][] swathGridCoord = new float[2][gridLen];
1408        byte[] numSwathPoints = new byte[gridLen];
1409    
1410        int[] swathIndexAtGrid = null;
1411        if (true) {
1412          swathIndexAtGrid = new int[gridLen];
1413        }
1414    
1415        float[][] grdCrd = new float[2][1];
1416        float[][] firstGridRange = new float[rngTupDim][gridLen];
1417        float[] sumRange = new float[rngTupDim];
1418        for (int t=0; t<rngTupDim; t++) {
1419           java.util.Arrays.fill(firstGridRange[t], Float.NaN);
1420           java.util.Arrays.fill(gridRange[t], Float.NaN);
1421        }
1422    
1423        float g0_last = Float.NaN;
1424        float g1_last = Float.NaN;
1425        float xt_dist = Float.NaN;
1426    
1427        for (int j=0; j < trackLen; j++) {
1428           for (int i=0; i < xtrackLen; i++) {
1429             int swathIdx = j*xtrackLen + i;
1430             float val = swathRange[0][swathIdx];
1431    
1432             float[][] swathCoord = swathDomain.indexToValue(new int[] {swathIdx});
1433             float[][] swathEarthCoord = swathCoordSys.toReference(swathCoord);
1434    
1435             float[][] gridValue = gridCoordSys.fromReference(swathEarthCoord);
1436             float[][] gridCoord = grid.valueToGrid(gridValue);
1437             float g0 = gridCoord[0][0];
1438             float g1 = gridCoord[1][0];
1439             int grdIdx  = (g0 != g0 || g1 != g1) ? -1 : ((int) (g0 + 0.5)) + gridXLen * ((int) (g1 + 0.5));
1440    
1441    
1442             // tooclose logic
1443             if (i >= 1) {
1444               float diff_0 = g0 - g0_last;
1445               float diff_1 = g1 - g1_last;
1446               xt_dist = (diff_0*diff_0) + (diff_1*diff_1);
1447             }
1448             g0_last = g0;
1449             g1_last = g1;
1450    
1451             boolean tooclose = false;
1452             float closest = Float.MAX_VALUE;
1453             for (int n = -2; n < 3; n++) {
1454                for (int m = -2; m < 3; m++) {
1455                   int k = grdIdx + (m + n*gridXLen);
1456                   if (k >=0 && k < gridXLen*gridYLen) {
1457                   if ( !Float.isNaN(swathGridCoord[0][k]) ) {
1458                      float del_0 = g0 - swathGridCoord[0][k];
1459                      float del_1 = g1 - swathGridCoord[1][k];
1460                      float dst = del_0*del_0 + del_1*del_1;
1461                      if (dst < closest) closest = dst;
1462                   }
1463                   }
1464                }
1465             }
1466             if (Math.sqrt((double)closest) < 0.86*Math.sqrt((double)xt_dist)) tooclose = true;
1467    
1468    
1469             int m=0;
1470             int n=0;
1471             int k = grdIdx + (m + n*gridXLen);
1472    
1473             if ( !(Float.isNaN(val)) && ((k >=0) && (k < gridXLen*gridYLen)) && !tooclose) { // val or val[rngTupDim] ?
1474                float grdVal = firstGridRange[0][k];
1475    
1476                if (Float.isNaN(grdVal)) {
1477                   for (int t=0; t<rngTupDim; t++) {
1478                      firstGridRange[t][k] = swathRange[t][swathIdx];
1479                   }
1480                   swathGridCoord[0][k] = g0;
1481                   swathGridCoord[1][k] = g1;
1482                   swathIndexAtGrid[k] = swathIdx;
1483                }
1484             }
1485    
1486           }
1487        }
1488    
1489        float[][] gCoord = new float[2][1];
1490        if (mode > 0.0) {  // 2nd pass weighted average
1491        float sigma = 0.6f;
1492        float weight = 1f;
1493        float[] sumValue = new float[rngTupDim];
1494    
1495        float[][] dst_sqrd = new float[5][5];
1496        for (int n=-2; n<3; n++) {
1497          for (int m=-2; m<3; m++) {
1498              float del_0 = m;
1499              float del_1 = n;
1500              dst_sqrd[n+2][m+2] = (float) Math.sqrt((double)(del_0*del_0 + del_1*del_1));
1501          }
1502        }
1503       
1504    
1505        for (int j=2; j<gridYLen-2; j++) {
1506           for (int i=2; i<gridXLen-2; i++) {
1507             int grdIdx = i + j*gridXLen;
1508    
1509             // don't do weighted average if a nearest neigbhor existed for the grid point
1510             if (mode == 2.0) {
1511               if (!Float.isNaN(firstGridRange[0][grdIdx])) {
1512                  for (int t=0; t<rngTupDim; t++) {
1513                     gridRange[t][grdIdx] = firstGridRange[t][grdIdx];
1514                  }
1515                  continue;
1516               }
1517             }
1518    
1519             int num = 0;
1520             float mag = 1f;
1521             float sumWeights = 0f;
1522             float[] dists = new float[25];
1523             float[][] values = new float[rngTupDim][25];
1524             for (int t=0; t<rngTupDim; t++) {
1525                sumValue[t] = 0f;
1526             }
1527    
1528             for (int n = -1; n < 2; n++) {
1529                for (int m = -1; m < 2; m++) {
1530                   int k = grdIdx + (m + n*gridXLen);
1531                   if ( !Float.isNaN(firstGridRange[0][k]) ) {
1532                      dists[num] = dst_sqrd[n+2][m+2];
1533                      for (int t=0; t<rngTupDim; t++) {
1534                        values[t][num] = firstGridRange[t][k];
1535                      }
1536                      num++;
1537                   }
1538                }
1539             }
1540    
1541             if (num < 5) {
1542    
1543             for (int n = -2; n < 3; n++) {
1544                for (int m = -2; m < 3; m++) {
1545                   if ( (n == -2 || n == 2) || ((n <= 1 && n >= -1) && (m==-2 || m==2)) ) { // don't repeat inner box
1546                   int k = grdIdx + (m + n*gridXLen);
1547                   if ( !Float.isNaN(firstGridRange[0][k]) ) {
1548                      dists[num] = dst_sqrd[n+2][m+2];
1549                      for (int t=0; t<rngTupDim; t++) {
1550                        values[t][num] = firstGridRange[t][k];
1551                      }
1552                      num++;
1553                   }
1554                   }
1555                }
1556              }
1557    
1558              if (num > 14 && num <= 21) sigma = 0.46f;
1559              if (num > 10 && num <= 14) sigma = 0.50f;
1560              if (num > 7 && num <= 10) sigma = 0.58f;
1561              if (num > 4 && num <= 7) sigma = 0.72f;
1562              if (num < 4) sigma = 1.44f;
1563              }
1564              else { // inner box only
1565                sigma = 0.40f;
1566              }
1567    
1568              for (int q=0; q<num; q++) {
1569                    float dstsqrd = dists[q];
1570                    weight = (float) (mag/Math.exp((double)(dstsqrd/(sigma))));
1571                    for (int t=0; t<rngTupDim; t++) {
1572                       sumValue[t] += values[t][q]*weight;
1573                    }
1574                    sumWeights += weight;
1575              }
1576    
1577              for (int t=0; t<rngTupDim; t++) {
1578                gridRange[t][grdIdx] = sumValue[t]/sumWeights;
1579              }
1580    
1581            }
1582          }
1583          grdFF.setSamples(gridRange);
1584        }
1585        else { // no averaging
1586          grdFF.setSamples(firstGridRange);
1587        }
1588    
1589       return grdFF;
1590     }
1591    
1592     public static boolean validLonLat(float[][] lonlat) {
1593       float lon = lonlat[0][0];
1594       float lat = lonlat[1][0];
1595       return ((lon >= -180f && lon <= 360f) && (lat >= -90f && lat <= 90f));
1596     }
1597    
1598    }
1599    
1600    
1601    class ChannelSelection extends DataSelectionComponent {
1602    
1603      DataChoice dataChoice;
1604      MultiSpectralDisplay display;
1605    
1606      ChannelSelection(DataChoice dataChoice) throws Exception {
1607         super("Channels");
1608         this.dataChoice = dataChoice;
1609         display = new MultiSpectralDisplay((DirectDataChoice)dataChoice);
1610         display.showChannelSelector();
1611      }
1612    
1613      protected JComponent doMakeContents() {
1614        try {
1615          JPanel panel = new JPanel(new BorderLayout());
1616          panel.add("Center", display.getDisplayComponent());
1617          if (display.getBandSelectComboBox() != null) {
1618            JPanel bandPanel = new JPanel(new FlowLayout());
1619            bandPanel.add(new JLabel("Band: "));
1620            bandPanel.add(display.getBandSelectComboBox());
1621            panel.add("South", bandPanel);
1622          }
1623          return panel;
1624        }
1625        catch (Exception e) {
1626          System.out.println(e);
1627        }
1628        return null;
1629      }
1630    
1631      public void applyToDataSelection(DataSelection dataSelection) {
1632          try {
1633            dataSelection.putProperty(Constants.PROP_CHAN, display.getWaveNumber());
1634            dataSelection.putProperty(SpectrumAdapter.channelIndex_name, display.getChannelIndex());
1635          } catch (Exception e) {
1636            e.printStackTrace();
1637          }
1638      }
1639    }
1640    
1641    class ImageChannelSelection extends DataSelectionComponent {
1642       PreviewSelection previewSelection;
1643       ChannelSelection channelSelection;
1644    
1645       ImageChannelSelection(PreviewSelection previewSelection, ChannelSelection channelSelection) {
1646         super("MultiSpectral");
1647         this.previewSelection = previewSelection;
1648         this.channelSelection = channelSelection;
1649       }
1650    
1651       protected JComponent doMakeContents() {
1652          JSplitPane splitpane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
1653          splitpane.add(previewSelection.doMakeContents());
1654          splitpane.add(channelSelection.doMakeContents());
1655          splitpane.setContinuousLayout(true);
1656          splitpane.setOneTouchExpandable(true);
1657          splitpane.setResizeWeight(1);
1658          splitpane.setDividerSize(12);
1659          return splitpane;
1660       }
1661    
1662       public void applyToDataSelection(DataSelection dataSelection) {
1663         previewSelection.applyToDataSelection(dataSelection);
1664         channelSelection.applyToDataSelection(dataSelection);
1665       }
1666    
1667    
1668    }