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