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 java.util.ArrayList;
032 import java.util.HashMap;
033
034 import visad.FunctionType;
035 import visad.Gridded1DSet;
036 import visad.QuickSort;
037 import visad.RealTupleType;
038 import visad.RealType;
039 import visad.SampledSet;
040 import visad.Set;
041 import visad.SingletonSet;
042
043 public class SpectrumAdapter extends MultiDimensionAdapter {
044
045 public static String channels_name = "Channels";
046 public static String channelIndex_name = "channelIndex";
047 public static String FOVindex_name = "FOVindex";
048 public static String channelUnit = "cm";
049 public static String channelType = "wavenumber";
050 public static String array_name = "array_name";
051 public static String array_dimension_names = "array_dimension_names";
052 public static String range_name = "range_name";
053 public static String x_dim_name = "x_dim"; //- 2 spatial dimensions, x fastest varying
054 public static String y_dim_name = "y_dim"; //-----------------------------------------
055 public static String time_dim_name = "time_dim";
056 public static String ancillary_file_name = "ancillary_file";
057 public static String channelValues = "channelValues";
058 public static String bandNames = "bandNames";
059
060
061 public static HashMap getEmptyMetadataTable() {
062 HashMap<String, String> metadata = new HashMap<String, String>();
063 metadata.put(array_name, null);
064 metadata.put(range_name, null);
065 metadata.put(channelIndex_name, null);
066 metadata.put(ancillary_file_name, null);
067 metadata.put(x_dim_name, null);
068 metadata.put(y_dim_name, null);
069 metadata.put(time_dim_name, null);
070 metadata.put(channelUnit, null);
071 metadata.put(channelType, "wavenumber");
072 metadata.put(channelValues, null);
073 metadata.put(bandNames, null);
074
075 /*
076 metadata.put(scale_name, null);
077 metadata.put(offset_name, null);
078 metadata.put(fill_value_name, null);
079 metadata.put(range_unit, null);
080 metadata.put(valid_range, null);
081 */
082 return metadata;
083 }
084
085 public static HashMap<String, double[]> getEmptySubset() {
086 HashMap<String, double[]> subset = new HashMap<String, double[]>();
087 subset.put(x_dim_name, new double[3]);
088 subset.put(y_dim_name, new double[3]);
089 subset.put(channelIndex_name, new double[3]);
090 return subset;
091 }
092
093 int numChannels;
094 int channelIndex = -1;
095 int[] channel_sort;
096 SampledSet domainSet;
097 RealType channelRealType;
098 RealType spectrumRangeType;
099 FunctionType spectrumType;
100
101 ArrayList<String> bandNameList = new ArrayList<String>();
102 String[] bandNameArray = null;
103 HashMap<String, Float> bandNameMap = null;
104 boolean hasBandNames = false;
105
106 public SpectrumAdapter(MultiDimensionReader reader, HashMap metadata) {
107 super(reader, metadata);
108 this.init();
109 }
110
111 private void init() {
112 for (int k=0; k<array_rank;k++) {
113 String name = (String) metadata.get(channelIndex_name);
114 if (name != null) {
115 if ( name.equals(array_dim_names[k]) ) {
116 channelIndex = k;
117 }
118 }
119 }
120
121 numChannels = computeNumChannels();
122
123 String[] names = (String[]) metadata.get(bandNames);
124 if (names != null) {
125 hasBandNames = true;
126 bandNameArray = new String[names.length];
127 for (int k=0; k<names.length;k++) {
128 bandNameList.add(names[k]);
129 bandNameArray[k] = names[k];
130 }
131 }
132
133 try {
134 domainSet = makeDomainSet();
135 rangeType = makeSpectrumRangeType();
136 spectrumType = new FunctionType(channelRealType, spectrumRangeType);
137 } catch (Exception e) {
138 e.printStackTrace();
139 System.out.println("cannot create spectrum domain");
140 }
141
142 }
143
144 public boolean hasBandNames() {
145 return hasBandNames;
146 }
147
148 public ArrayList<String> getBandNames() {
149 return bandNameList;
150 }
151
152 public HashMap<String, Float> getBandNameMap() {
153 return bandNameMap;
154 }
155
156 public int computeNumChannels() {
157 if (channelIndex == -1) {
158 return 1;
159 }
160 else {
161 return array_dim_lengths[channelIndex];
162 }
163 }
164
165 public Set makeDomain(Object subset) throws Exception {
166 return domainSet;
167 }
168
169 public SampledSet getDomainSet() throws Exception {
170 return domainSet;
171 }
172
173 private SampledSet makeDomainSet() throws Exception {
174 RealType domainType = makeSpectrumDomainType();
175 float[] channels = getChannels();
176 channel_sort = QuickSort.sort(channels);
177 if (numChannels == 1) {
178 domainSet = new SingletonSet(new RealTupleType(domainType), new double[] {(double)channels[0]}, null, null, null);
179 }
180 else {
181 domainSet = new Gridded1DSet(domainType, new float[][] {channels}, numChannels);
182 }
183 return domainSet;
184 }
185
186 public float[] getChannels() throws Exception {
187 float[] channels = null;
188 if (metadata.get(channelValues) == null) {
189 channels = reader.getFloatArray((String)metadata.get(channels_name),
190 new int[] {0}, new int[] {numChannels}, new int[] {1});
191 }
192 else {
193 channels = (float[]) metadata.get(channelValues);
194 }
195
196 if (hasBandNames) {
197 bandNameMap = new HashMap<String, Float>();
198 for (int k=0; k<numChannels; k++) {
199 bandNameMap.put(bandNameArray[k], new Float(channels[k]));
200 }
201 }
202 return channels;
203 }
204
205 public RealType makeSpectrumDomainType() throws Exception {
206 /**
207 if ( ((String)metadata.get(channelType)).equals("wavenumber") ) {
208 ScaledUnit centimeter = new ScaledUnit(0.01, CommonUnit.meter, "cm");
209 Unit tmp_unit = centimeter.pow(-1);
210 ScaledUnit inv_centimeter = new ScaledUnit(1.0, tmp_unit, "cm^-1");
211 channelRealType = RealType.getRealType("wavenumber", null);
212 }
213 **/
214 channelRealType = RealType.getRealType((String)metadata.get(channelType), null);
215 return channelRealType;
216 }
217
218 public RealType makeSpectrumRangeType() throws Exception {
219 spectrumRangeType = RealType.getRealType("Radiance");
220 return spectrumRangeType;
221 }
222
223 float[] sortRange(float[] range) {
224 float[] sorted_range = new float[numChannels];
225 for (int k=0; k<numChannels; k++) sorted_range[k] = range[channel_sort[k]];
226 return sorted_range;
227 }
228
229 double[] sortRange(double[] range) {
230 double[] sorted_range = new double[numChannels];
231 for (int k=0; k<numChannels; k++) sorted_range[k] = range[channel_sort[k]];
232 return sorted_range;
233 }
234
235
236 public float[] processRange(float[] range, Object subset) {
237 return range;
238 }
239
240 public double[] processRange(double[] range, Object subset) {
241 return range;
242 }
243
244 public float[] processRange(short[] range, Object subset) {
245 return rangeProcessor.processAlongMultiScaleDim(range);
246 }
247
248 public float[] processRange(byte[] range, Object subset) {
249 return rangeProcessor.processAlongMultiScaleDim(range);
250 }
251
252 public HashMap getDefaultSubset() {
253 HashMap<String, double[]> subset = SpectrumAdapter.getEmptySubset();
254
255 double[] coords = (double[])subset.get(y_dim_name);
256 coords[0] = 1.0;
257 coords[1] = 1.0;
258 coords[2] = 1.0;
259 subset.put(y_dim_name, coords);
260
261 coords = (double[])subset.get(x_dim_name);
262 coords[0] = 1.0;
263 coords[1] = 1.0;
264 coords[2] = 1.0;
265 subset.put(x_dim_name, coords);
266
267 coords = (double[])subset.get(channelIndex_name);
268 coords[0] = 0.0;
269 coords[1] = (double) (numChannels - 1);
270 coords[2] = 1.0;
271 subset.put(channelIndex_name, coords);
272
273 return subset;
274 }
275
276 public int getChannelIndexFromWavenumber(float wavenumber) throws Exception {
277 int idx = (domainSet.valueToIndex(new float[][] {{wavenumber}}))[0];
278 return channel_sort[idx];
279 }
280
281 public float getWavenumberFromChannelIndex(int index) throws Exception {
282 int idx = channel_sort[index];
283 return (domainSet.indexToValue(new int[] {idx}))[0][0];
284 }
285
286 public int getNumChannels() {
287 return numChannels;
288 }
289 }