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 }