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 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;
051
052import visad.georef.MapProjection;
053import visad.CachingCoordinateSystem;
054import ucar.visad.ProjectionCoordinateSystem;
055
056public 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}