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 visad.FlatField;
032    import visad.SampledSet;
033    import visad.RealTuple;
034    import visad.SetType;
035    import visad.RealType;
036    import visad.RealTupleType;
037    import visad.VisADException;
038    import visad.CoordinateSystem;
039    import visad.FunctionType;
040    import visad.Real;
041    import visad.Set;
042    import visad.Linear1DSet;
043    import visad.Linear2DSet;
044    import visad.Gridded1DSet;
045    import visad.Gridded2DSet;
046    import visad.QuickSort;
047    import java.rmi.RemoteException;
048    import java.util.HashMap;
049    import java.util.ArrayList;
050    import java.awt.geom.Rectangle2D;
051    
052    import visad.georef.MapProjection;
053    import visad.CachingCoordinateSystem;
054    import ucar.visad.ProjectionCoordinateSystem;
055    
056    public class MultiSpectralAggr extends MultiSpectralData {
057    
058      Gridded1DSet aggrDomain = null;
059    
060      MultiSpectralData[] adapters = null;
061    
062      int[] sort_indexes = null;
063    
064      float[] aggrValues = null;
065    
066      float[] aggrSamples = null;
067    
068      int numAdapters;
069    
070      int numBands;
071    
072      int[] offset;
073    
074      public MultiSpectralAggr(MultiSpectralData[] adapters)
075             throws Exception {
076        super(adapters[0].swathAdapter, null);
077        this.adapters = adapters;
078        paramName = adapters[0].getParameter();
079    
080        numAdapters = adapters.length;
081        int[] numBandsAdapter = new int[numAdapters];
082        offset = new int[numAdapters];
083        SampledSet[] spectrumDomains = new SampledSet[numAdapters];
084    
085        if (adapters[0].spectrumAdapter.hasBandNames()) {
086          hasBandNames = true;
087          bandNameList = new ArrayList<String>();
088          bandNameMap = new HashMap<String, Float>();
089          for (int k=0; k<numAdapters; k++) {
090            bandNameList.addAll(adapters[k].spectrumAdapter.getBandNames());
091            bandNameMap.putAll(adapters[k].spectrumAdapter.getBandNameMap());
092          }
093        }
094    
095        numBands = 0;
096        for (int k=0; k<numAdapters; k++) {
097          SampledSet set = adapters[k].spectrumAdapter.getDomainSet();
098          spectrumDomains[k] = set;
099          numBandsAdapter[k] = set.getLength();
100          offset[k] = numBands;
101          numBands += numBandsAdapter[k];
102        }
103       
104        aggrSamples = new float[numBands];
105        aggrValues  = new float[numBands];
106    
107        for (int k=0; k<numAdapters; k++) {
108          float[][] samples = spectrumDomains[k].getSamples(false);
109          System.arraycopy(samples[0], 0, aggrSamples, offset[k], samples[0].length);
110        }
111    
112        sort_indexes = QuickSort.sort(aggrSamples);
113        SpectrumAdapter specAdapt = adapters[0].spectrumAdapter;
114        aggrDomain = new Gridded1DSet(specAdapt.getDomainSet().getType(), 
115                            new float[][] {aggrSamples}, aggrSamples.length); 
116    
117        init_wavenumber = getWavenumberFromChannelIndex(0);
118      }
119    
120      public FlatField getSpectrum(int[] coords) throws Exception {
121        FlatField spectrum = null;
122        for (int k=0; k<numAdapters; k++) {
123          spectrum = adapters[k].getSpectrum(coords);
124          if (spectrum == null) {
125            return null;
126          }
127          float[][] values = spectrum.getFloats(false);
128          System.arraycopy(values[0], 0, aggrValues, offset[k], values[0].length);
129        }
130    
131        for (int t=0; t<numBands; t++) {
132          aggrValues[t] = aggrValues[sort_indexes[t]];
133        }
134    
135        spectrum = new FlatField((FunctionType)spectrum.getType(), aggrDomain);
136        spectrum.setSamples(new float[][] {aggrValues});
137    
138        return spectrum;
139      }
140    
141      public FlatField getSpectrum(RealTuple location) throws Exception {
142        FlatField spectrum = null;
143        for (int k=0; k<numAdapters; k++) {
144          spectrum = adapters[k].getSpectrum(location);
145          if (spectrum == null) {
146            return null;
147          }
148          float[][] values = spectrum.getFloats(false);
149          System.arraycopy(values[0], 0, aggrValues, offset[k], values[0].length);
150        }
151    
152        for (int t=0; t<numBands; t++) {
153          aggrValues[t] = aggrValues[sort_indexes[t]];
154        }
155    
156        spectrum = new FlatField((FunctionType)spectrum.getType(), aggrDomain);
157        spectrum.setSamples(new float[][] {aggrValues});
158    
159        return spectrum;
160      }
161    
162      public FlatField getImage(HashMap subset) throws Exception {
163        int channelIndex = (int) ((double[])subset.get(SpectrumAdapter.channelIndex_name))[0];
164        
165        int idx = sort_indexes[channelIndex];
166        
167        int swathAdapterIndex = numAdapters-1;
168        for (int k=0; k<numAdapters-1;k++) {
169          if (idx >= offset[k] && idx < offset[k+1]) swathAdapterIndex = k;
170        }
171        float channel = aggrSamples[channelIndex];
172        FlatField image = adapters[swathAdapterIndex].getImage(channel, subset);
173        cs = ((RealTupleType) ((FunctionType)image.getType()).getDomain()).getCoordinateSystem();
174        for (int k=0; k<numAdapters;k++) {
175          if (k != swathAdapterIndex) adapters[k].setCoordinateSystem(cs);
176        }
177        return image;
178      }
179    
180      public FlatField getImage(float channel, HashMap subset) throws Exception {
181        int channelIndex = aggrDomain.valueToIndex(new float[][] {{channel}})[0];
182    
183        int idx = sort_indexes[channelIndex];
184    
185        int swathAdapterIndex = numAdapters-1;
186        for (int k=0; k<numAdapters-1;k++) {
187          if (idx >= offset[k] && idx < offset[k+1]) swathAdapterIndex = k;
188        }
189        channel = aggrSamples[channelIndex];
190        FlatField image = adapters[swathAdapterIndex].getImage(channel, subset);
191        cs = ((RealTupleType) ((FunctionType)image.getType()).getDomain()).getCoordinateSystem();
192        for (int k=0; k<numAdapters;k++) {
193          if (k != swathAdapterIndex) adapters[k].setCoordinateSystem(cs);
194        }
195        return image;
196      }
197    
198      public int getChannelIndexFromWavenumber(float channel) throws VisADException, RemoteException {
199        int idx = (aggrDomain.valueToIndex(new float[][] {{channel}}))[0];
200        return idx;
201      }
202    
203      public float getWavenumberFromChannelIndex(int index) throws Exception {
204        return (aggrDomain.indexToValue(new int[] {index}))[0][0];
205      }
206    
207      public HashMap getDefaultSubset() {
208        HashMap subset = adapters[0].getDefaultSubset();
209        double chanIdx = 0;
210        try {
211          chanIdx = getChannelIndexFromWavenumber(init_wavenumber);
212        }
213        catch (Exception e) {
214          System.out.println("couldn't get chanIdx, using zero");
215        }
216        subset.put(SpectrumAdapter.channelIndex_name, new double[] {chanIdx, chanIdx, 1});
217        return subset;
218      }
219    
220    }