001 /*
002 * $Id: SpectrumAdapter.java,v 1.20 2012/04/10 15:32:42 rink Exp $
003 *
004 * This file is part of McIDAS-V
005 *
006 * Copyright 2007-2012
007 * Space Science and Engineering Center (SSEC)
008 * University of Wisconsin - Madison
009 * 1225 W. Dayton Street, Madison, WI 53706, USA
010 * https://www.ssec.wisc.edu/mcidas
011 *
012 * All Rights Reserved
013 *
014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
015 * some McIDAS-V source code is based on IDV and VisAD source code.
016 *
017 * McIDAS-V is free software; you can redistribute it and/or modify
018 * it under the terms of the GNU Lesser Public License as published by
019 * the Free Software Foundation; either version 3 of the License, or
020 * (at your option) any later version.
021 *
022 * McIDAS-V is distributed in the hope that it will be useful,
023 * but WITHOUT ANY WARRANTY; without even the implied warranty of
024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
025 * GNU Lesser Public License for more details.
026 *
027 * You should have received a copy of the GNU Lesser Public License
028 * along with this program. If not, see http://www.gnu.org/licenses.
029 */
030
031 package edu.wisc.ssec.mcidasv.data.hydra;
032
033 import java.util.ArrayList;
034 import java.util.HashMap;
035
036 import visad.FunctionType;
037 import visad.Gridded1DSet;
038 import visad.QuickSort;
039 import visad.RealTupleType;
040 import visad.RealType;
041 import visad.SampledSet;
042 import visad.Set;
043 import visad.SingletonSet;
044
045 public class SpectrumAdapter extends MultiDimensionAdapter {
046
047 public static String channels_name = "Channels";
048 public static String channelIndex_name = "channelIndex";
049 public static String FOVindex_name = "FOVindex";
050 public static String channelUnit = "cm";
051 public static String channelType = "wavenumber";
052 public static String array_name = "array_name";
053 public static String array_dimension_names = "array_dimension_names";
054 public static String range_name = "range_name";
055 public static String x_dim_name = "x_dim"; //- 2 spatial dimensions, x fastest varying
056 public static String y_dim_name = "y_dim"; //-----------------------------------------
057 public static String time_dim_name = "time_dim";
058 public static String ancillary_file_name = "ancillary_file";
059 public static String channelValues = "channelValues";
060 public static String bandNames = "bandNames";
061
062
063 public static HashMap getEmptyMetadataTable() {
064 HashMap<String, String> metadata = new HashMap<String, String>();
065 metadata.put(array_name, null);
066 metadata.put(range_name, null);
067 metadata.put(channelIndex_name, null);
068 metadata.put(ancillary_file_name, null);
069 metadata.put(x_dim_name, null);
070 metadata.put(y_dim_name, null);
071 metadata.put(time_dim_name, null);
072 metadata.put(channelUnit, null);
073 metadata.put(channelType, "wavenumber");
074 metadata.put(channelValues, null);
075 metadata.put(bandNames, null);
076
077 /*
078 metadata.put(scale_name, null);
079 metadata.put(offset_name, null);
080 metadata.put(fill_value_name, null);
081 metadata.put(range_unit, null);
082 metadata.put(valid_range, null);
083 */
084 return metadata;
085 }
086
087 public static HashMap<String, double[]> getEmptySubset() {
088 HashMap<String, double[]> subset = new HashMap<String, double[]>();
089 subset.put(x_dim_name, new double[3]);
090 subset.put(y_dim_name, new double[3]);
091 subset.put(channelIndex_name, new double[3]);
092 return subset;
093 }
094
095 int numChannels;
096 int channelIndex = -1;
097 int[] channel_sort;
098 SampledSet domainSet;
099 RealType channelRealType;
100 RealType spectrumRangeType;
101 FunctionType spectrumType;
102
103 ArrayList<String> bandNameList = new ArrayList<String>();
104 String[] bandNameArray = null;
105 HashMap<String, Float> bandNameMap = null;
106 boolean hasBandNames = false;
107
108 public SpectrumAdapter(MultiDimensionReader reader, HashMap metadata) {
109 super(reader, metadata);
110 this.init();
111 }
112
113 private void init() {
114 for (int k=0; k<array_rank;k++) {
115 String name = (String) metadata.get(channelIndex_name);
116 if (name != null) {
117 if ( name.equals(array_dim_names[k]) ) {
118 channelIndex = k;
119 }
120 }
121 }
122
123 numChannels = computeNumChannels();
124
125 String[] names = (String[]) metadata.get(bandNames);
126 if (names != null) {
127 hasBandNames = true;
128 bandNameArray = new String[names.length];
129 for (int k=0; k<names.length;k++) {
130 bandNameList.add(names[k]);
131 bandNameArray[k] = names[k];
132 }
133 }
134
135 try {
136 domainSet = makeDomainSet();
137 rangeType = makeSpectrumRangeType();
138 spectrumType = new FunctionType(channelRealType, spectrumRangeType);
139 } catch (Exception e) {
140 e.printStackTrace();
141 System.out.println("cannot create spectrum domain");
142 }
143
144 }
145
146 public boolean hasBandNames() {
147 return hasBandNames;
148 }
149
150 public ArrayList<String> getBandNames() {
151 return bandNameList;
152 }
153
154 public HashMap<String, Float> getBandNameMap() {
155 return bandNameMap;
156 }
157
158 public int computeNumChannels() {
159 if (channelIndex == -1) {
160 return 1;
161 }
162 else {
163 return array_dim_lengths[channelIndex];
164 }
165 }
166
167 public Set makeDomain(Object subset) throws Exception {
168 return domainSet;
169 }
170
171 public SampledSet getDomainSet() throws Exception {
172 return domainSet;
173 }
174
175 private SampledSet makeDomainSet() throws Exception {
176 RealType domainType = makeSpectrumDomainType();
177 float[] channels = getChannels();
178 channel_sort = QuickSort.sort(channels);
179 if (numChannels == 1) {
180 domainSet = new SingletonSet(new RealTupleType(domainType), new double[] {(double)channels[0]}, null, null, null);
181 }
182 else {
183 domainSet = new Gridded1DSet(domainType, new float[][] {channels}, numChannels);
184 }
185 return domainSet;
186 }
187
188 public float[] getChannels() throws Exception {
189 float[] channels = null;
190 if (metadata.get(channelValues) == null) {
191 channels = reader.getFloatArray((String)metadata.get(channels_name),
192 new int[] {0}, new int[] {numChannels}, new int[] {1});
193 }
194 else {
195 channels = (float[]) metadata.get(channelValues);
196 }
197
198 if (hasBandNames) {
199 bandNameMap = new HashMap<String, Float>();
200 for (int k=0; k<numChannels; k++) {
201 bandNameMap.put(bandNameArray[k], new Float(channels[k]));
202 }
203 }
204 return channels;
205 }
206
207 public RealType makeSpectrumDomainType() throws Exception {
208 /**
209 if ( ((String)metadata.get(channelType)).equals("wavenumber") ) {
210 ScaledUnit centimeter = new ScaledUnit(0.01, CommonUnit.meter, "cm");
211 Unit tmp_unit = centimeter.pow(-1);
212 ScaledUnit inv_centimeter = new ScaledUnit(1.0, tmp_unit, "cm^-1");
213 channelRealType = RealType.getRealType("wavenumber", null);
214 }
215 **/
216 channelRealType = RealType.getRealType((String)metadata.get(channelType), null);
217 return channelRealType;
218 }
219
220 public RealType makeSpectrumRangeType() throws Exception {
221 spectrumRangeType = RealType.getRealType("Radiance");
222 return spectrumRangeType;
223 }
224
225 float[] sortRange(float[] range) {
226 float[] sorted_range = new float[numChannels];
227 for (int k=0; k<numChannels; k++) sorted_range[k] = range[channel_sort[k]];
228 return sorted_range;
229 }
230
231 double[] sortRange(double[] range) {
232 double[] sorted_range = new double[numChannels];
233 for (int k=0; k<numChannels; k++) sorted_range[k] = range[channel_sort[k]];
234 return sorted_range;
235 }
236
237
238 public float[] processRange(float[] range, Object subset) {
239 return range;
240 }
241
242 public double[] processRange(double[] range, Object subset) {
243 return range;
244 }
245
246 public float[] processRange(short[] range, Object subset) {
247 return rangeProcessor.processAlongMultiScaleDim(range);
248 }
249
250 public float[] processRange(byte[] range, Object subset) {
251 return rangeProcessor.processAlongMultiScaleDim(range);
252 }
253
254 public HashMap getDefaultSubset() {
255 HashMap<String, double[]> subset = SpectrumAdapter.getEmptySubset();
256
257 double[] coords = (double[])subset.get(y_dim_name);
258 coords[0] = 1.0;
259 coords[1] = 1.0;
260 coords[2] = 1.0;
261 subset.put(y_dim_name, coords);
262
263 coords = (double[])subset.get(x_dim_name);
264 coords[0] = 1.0;
265 coords[1] = 1.0;
266 coords[2] = 1.0;
267 subset.put(x_dim_name, coords);
268
269 coords = (double[])subset.get(channelIndex_name);
270 coords[0] = 0.0;
271 coords[1] = (double) (numChannels - 1);
272 coords[2] = 1.0;
273 subset.put(channelIndex_name, coords);
274
275 return subset;
276 }
277
278 public int getChannelIndexFromWavenumber(float wavenumber) throws Exception {
279 int idx = (domainSet.valueToIndex(new float[][] {{wavenumber}}))[0];
280 return channel_sort[idx];
281 }
282
283 public float getWavenumberFromChannelIndex(int index) throws Exception {
284 int idx = channel_sort[index];
285 return (domainSet.indexToValue(new int[] {idx}))[0][0];
286 }
287
288 public int getNumChannels() {
289 return numChannels;
290 }
291 }