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