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 java.util.ArrayList; 032import java.util.HashMap; 033import java.util.List; 034import java.util.Map; 035 036import visad.FunctionType; 037import visad.Gridded1DSet; 038import visad.QuickSort; 039import visad.RealTupleType; 040import visad.RealType; 041import visad.SampledSet; 042import visad.Set; 043import visad.SingletonSet; 044 045public 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 Map<String, Object> getEmptyMetadataTable() { 064 Map<String, Object> metadata = new HashMap<>(); 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 Map<String, double[]> getEmptySubset() { 088 Map<String, double[]> subset = new HashMap<>(); 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 List<String> bandNameList = new ArrayList<>(); 104 String[] bandNameArray = null; 105 Map<String, Float> bandNameMap = null; 106 boolean hasBandNames = false; 107 108 public SpectrumAdapter(MultiDimensionReader reader, Map<String, Object> 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 List<String> getBandNames() { 151 return bandNameList; 152 } 153 154 public Map<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(Map<String, double[]> 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<>(); 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 public Map<String, double[]> getDefaultSubset() { 238 Map<String, double[]> subset = SpectrumAdapter.getEmptySubset(); 239 240 double[] coords = (double[])subset.get(y_dim_name); 241 coords[0] = 1.0; 242 coords[1] = 1.0; 243 coords[2] = 1.0; 244 subset.put(y_dim_name, coords); 245 246 coords = (double[])subset.get(x_dim_name); 247 coords[0] = 1.0; 248 coords[1] = 1.0; 249 coords[2] = 1.0; 250 subset.put(x_dim_name, coords); 251 252 coords = (double[])subset.get(channelIndex_name); 253 coords[0] = 0.0; 254 coords[1] = (double) (numChannels - 1); 255 coords[2] = 1.0; 256 subset.put(channelIndex_name, coords); 257 258 return subset; 259 } 260 261 public int getChannelIndexFromWavenumber(float wavenumber) throws Exception { 262 int idx = (domainSet.valueToIndex(new float[][] {{wavenumber}}))[0]; 263 return channel_sort[idx]; 264 } 265 266 public float getWavenumberFromChannelIndex(int index) throws Exception { 267 int idx = channel_sort[index]; 268 return (domainSet.indexToValue(new int[] {idx}))[0][0]; 269 } 270 271 public int getNumChannels() { 272 return numChannels; 273 } 274}