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.awt.geom.Rectangle2D;
032    import java.rmi.RemoteException;
033    import java.util.ArrayList;
034    import java.util.HashMap;
035    import java.util.Iterator;
036    
037    import visad.CoordinateSystem;
038    import visad.FlatField;
039    import visad.FunctionType;
040    import visad.Gridded2DSet;
041    import visad.Linear1DSet;
042    import visad.Linear2DSet;
043    import visad.Real;
044    import visad.RealTuple;
045    import visad.RealTupleType;
046    import visad.RealType;
047    import visad.SampledSet;
048    import visad.Set;
049    import visad.SetType;
050    import visad.VisADException;
051    
052    public class MultiSpectralData extends MultiDimensionAdapter {
053    
054      SwathAdapter swathAdapter = null;
055      SpectrumAdapter spectrumAdapter = null;
056      CoordinateSystem cs = null;
057    
058      HashMap spectrumSelect = null;
059      HashMap swathSelect = null;
060    
061      String sensorName = null;
062      String platformName = null;
063      String paramName = null;
064      String inputParamName = null;
065      String name = null;
066    
067      public float init_wavenumber = 919.50f;
068      public String init_bandName = null;
069    
070      float[] dataRange = new float[] {180f, 320f};
071    
072      boolean hasBandNames = false;
073      ArrayList<String> bandNameList = null;
074      HashMap<String, Float> bandNameMap = null;
075    
076      
077      public MultiSpectralData(SwathAdapter swathAdapter, SpectrumAdapter spectrumAdapter,
078                               String inputParamName, String paramName, String sensorName, String platformName) {
079        this.swathAdapter = swathAdapter;
080        this.spectrumAdapter = spectrumAdapter;
081        this.paramName = paramName;
082        this.inputParamName = inputParamName;
083        this.name = swathAdapter.getArrayName();
084    
085        if (spectrumAdapter != null) {
086          this.spectrumSelect = spectrumAdapter.getDefaultSubset();
087          if (spectrumAdapter.hasBandNames()) {
088            hasBandNames = true;
089            bandNameList = spectrumAdapter.getBandNames();
090            bandNameMap = spectrumAdapter.getBandNameMap();
091          }
092          try {
093            setInitialWavenumber(getWavenumberFromChannelIndex(0));
094          } 
095          catch (Exception e) {
096            e.printStackTrace();
097            System.out.println("could not initialize initial wavenumber");
098          }
099        }
100    
101        if (swathAdapter != null) {
102          this.swathSelect = swathAdapter.getDefaultSubset();
103          if (spectrumAdapter != null) {
104            spectrumAdapter.setRangeProcessor(swathAdapter.getRangeProcessor());
105          }
106        }
107    
108        this.sensorName = sensorName;
109        this.platformName = platformName;
110      }
111    
112      public MultiSpectralData(SwathAdapter swathAdapter, SpectrumAdapter spectrumAdapter,
113                               String sensorName, String platformName) {
114        this(swathAdapter, spectrumAdapter, "Radiance", "BrightnessTemp", sensorName, platformName);
115      }
116    
117      public MultiSpectralData(SwathAdapter swathAdapter, SpectrumAdapter spectrumAdapter) {
118        this(swathAdapter, spectrumAdapter, null, null);
119      }
120    
121      public MultiSpectralData() {
122        this(null, null, null, null);
123      }
124    
125      public FlatField getSpectrum(int[] coords) 
126          throws Exception, VisADException, RemoteException {
127        if (coords == null) return null;
128        if (spectrumAdapter == null) return null;
129        spectrumSelect.put(SpectrumAdapter.x_dim_name, new double[] {(double)coords[0], (double)coords[0], 1.0});
130        spectrumSelect.put(SpectrumAdapter.y_dim_name, new double[] {(double)coords[1], (double)coords[1], 1.0});
131    
132        FlatField spectrum = spectrumAdapter.getData(spectrumSelect);
133        return convertSpectrum(spectrum, paramName);
134      }
135    
136      public FlatField getSpectrum(RealTuple location) 
137          throws Exception, VisADException, RemoteException {
138        if (spectrumAdapter == null) return null;
139        int[] coords = getSwathCoordinates(location, cs);
140        if (coords == null) return null;
141        spectrumSelect.put(SpectrumAdapter.x_dim_name, new double[] {(double)coords[0], (double)coords[0], 1.0});
142        spectrumSelect.put(SpectrumAdapter.y_dim_name, new double[] {(double)coords[1], (double)coords[1], 1.0});
143    
144        FlatField spectrum = spectrumAdapter.getData(spectrumSelect);
145        return convertSpectrum(spectrum, paramName);
146      }
147    
148      public FlatField getImage(HashMap subset) 
149        throws Exception, VisADException, RemoteException {
150        FlatField image = swathAdapter.getData(subset);
151        cs = ((RealTupleType) ((FunctionType)image.getType()).getDomain()).getCoordinateSystem();
152    
153        int channelIndex = (int) ((double[])subset.get(SpectrumAdapter.channelIndex_name))[0];
154        float channel = spectrumAdapter.getWavenumberFromChannelIndex(channelIndex);
155    
156        return convertImage(image, channel, paramName);
157      }
158    
159      public FlatField getImage(float channel, HashMap subset) 
160          throws Exception, VisADException, RemoteException {
161        if (spectrumAdapter == null) return getImage(subset);
162        int channelIndex = spectrumAdapter.getChannelIndexFromWavenumber(channel);
163        subset.put(SpectrumAdapter.channelIndex_name, new double[] {(double)channelIndex, (double)channelIndex, 1.0});
164        FlatField image = swathAdapter.getData(subset);
165        cs = ((RealTupleType) ((FunctionType)image.getType()).getDomain()).getCoordinateSystem();
166    
167        return convertImage(image, channel, paramName);
168      }
169    
170      public FlatField getData(Object subset) throws Exception {
171        return getImage((HashMap)subset);
172      }
173    
174      public Set makeDomain(Object subset) throws Exception {
175        throw new Exception("makeDomain unimplented");
176      } 
177    
178    
179      FlatField convertImage(FlatField image, float channel, String param) 
180                throws Exception {
181        FlatField new_image = null;
182        FunctionType f_type = (FunctionType)image.getType();
183        if (param.equals("BrightnessTemp")) { //- convert radiance to BrightnessTemp
184          FunctionType new_type = new FunctionType(f_type.getDomain(), RealType.getRealType("BrightnessTemp"));
185          new_image = new FlatField(new_type, image.getDomainSet());
186          float[][] values = image.getFloats(false);
187          float[] bt_values = values[0];
188          if (inputParamName == "Radiance") {
189            bt_values = radianceToBrightnessTemp(values[0], channel, platformName, sensorName);
190          }
191          new_image.setSamples(new float[][] {bt_values}, false);
192        }
193        else if (param.equals("Reflectance")) {
194          FunctionType new_type = new FunctionType(f_type.getDomain(), RealType.getRealType("Reflectance"));
195          new_image = new FlatField(new_type, image.getDomainSet());
196          new_image.setSamples(image.getFloats(false), false);
197        }
198        else {
199          new_image = image;
200        }
201        return new_image;
202      }
203    
204    
205      FlatField convertSpectrum(FlatField spectrum, String param) throws Exception {
206        FlatField new_spectrum = null;
207        FunctionType f_type = (FunctionType) spectrum.getType();
208    
209        if (param.equals("BrightnessTemp")) {
210          FunctionType new_type = new FunctionType(f_type.getDomain(), RealType.getRealType("BrightnessTemp"));
211          float[][] channels = ((SampledSet)spectrum.getDomainSet()).getSamples(false);
212          float[][] values = spectrum.getFloats(false);
213          float[] bt_values = values[0];
214          if (inputParamName == "Radiance") {
215            bt_values = radianceToBrightnessTempSpectrum(values[0], channels[0], platformName, sensorName);
216          }
217          new_spectrum = new FlatField(new_type, spectrum.getDomainSet());
218          new_spectrum.setSamples(new float[][] {bt_values}, true);
219        }
220        else if (param.equals("Reflectance")) {
221          FunctionType new_type = new FunctionType(f_type.getDomain(), RealType.getRealType("Reflectance"));
222          new_spectrum = new FlatField(new_type, spectrum.getDomainSet());
223          new_spectrum.setSamples(spectrum.getFloats(false), false);
224        }
225        else {
226          new_spectrum = spectrum;
227        }
228        return new_spectrum;
229      }
230    
231      protected void setDataRange(float[] range) {
232        dataRange = range;
233      }
234    
235      public float[] getDataRange() {
236        return dataRange;
237      }
238    
239      public String getParameter() {
240        return paramName;
241      }
242    
243      public String getName() {
244        return name;
245      }
246    
247      public CoordinateSystem getCoordinateSystem() {
248        return cs;
249      }
250    
251      public void setCoordinateSystem(CoordinateSystem cs) {
252        this.cs = cs;
253      }
254    
255      public boolean hasBandNames() {
256        return hasBandNames;
257      }
258    
259      public ArrayList<String> getBandNames() {
260        return bandNameList;
261      }
262    
263      public HashMap<String, Float> getBandNameMap() {
264        return bandNameMap;
265      }
266    
267      public String getBandNameFromWaveNumber(float channel) {
268        String bandName = null;
269        Iterator iter = bandNameMap.keySet().iterator();
270        while (iter.hasNext()) {
271           String key = (String) iter.next();
272           float mapVal = ((Float)bandNameMap.get(key)).floatValue();
273           if (channel == mapVal) {
274             bandName = key;
275             break;
276           }
277        }
278        return bandName;
279      }
280    
281      public void setInitialWavenumber(float val) {
282        init_wavenumber = val;
283        if (hasBandNames) {
284          init_bandName = getBandNameFromWaveNumber(init_wavenumber);
285        }
286      }
287    
288      public int[] getSwathCoordinates(RealTuple location, CoordinateSystem cs) 
289          throws VisADException, RemoteException {
290        if (location == null) return null;
291        if (cs == null) return null;
292        Real[] comps = location.getRealComponents();
293        //- trusted: latitude:0, longitude:1
294        float lon = (float) comps[1].getValue();
295        float lat = (float) comps[0].getValue();
296        if (lon < -180) lon += 360f;
297        if (lon > 180) lon -= 360f;
298        float[][] xy = cs.fromReference(new float[][] {{lon}, {lat}});
299        if ((Float.isNaN(xy[0][0])) || Float.isNaN(xy[1][0])) return null;
300        Set domain = swathAdapter.getSwathDomain();
301        int[] idx = domain.valueToIndex(xy);
302        xy = domain.indexToValue(idx);
303        int[] coords = new int[2];
304        coords[0] = (int) xy[0][0];
305        coords[1] = (int) xy[1][0];
306        if ((coords[0] < 0)||(coords[1] < 0)) return null;
307        return coords;
308      }
309    
310      public RealTuple getEarthCoordinates(float[] xy)
311          throws VisADException, RemoteException {
312        float[][] tup = cs.toReference(new float[][] {{xy[0]}, {xy[1]}});
313        return new RealTuple(RealTupleType.SpatialEarth2DTuple, new double[] {(double)tup[0][0], (double)tup[1][0]});
314      }
315    
316      public int getChannelIndexFromWavenumber(float channel) throws Exception {
317        return spectrumAdapter.getChannelIndexFromWavenumber(channel);
318      }
319    
320      public float getWavenumberFromChannelIndex(int index) throws Exception {
321        return spectrumAdapter.getWavenumberFromChannelIndex(index);
322      }
323    
324      public Rectangle2D getLonLatBoundingBox(CoordinateSystem cs) {
325        return null;
326      }
327    
328      public Rectangle2D getLonLatBoundingBox(HashMap subset) 
329          throws Exception {
330        Set domainSet = swathAdapter.makeDomain(subset);
331        return getLonLatBoundingBox(domainSet);
332      }
333    
334      public static Rectangle2D getLonLatBoundingBox(FlatField field) {
335        Set domainSet = field.getDomainSet();
336        return getLonLatBoundingBox(domainSet);
337      }
338    
339      public static float[][] getLonLatBoundingCorners(Set domainSet) {
340        CoordinateSystem cs =
341          ((SetType)domainSet.getType()).getDomain().getCoordinateSystem();
342    
343        float start0, stop0, start1, stop1;
344        int len0, len1;
345        float minLon = Float.MAX_VALUE;
346        float minLat = Float.MAX_VALUE;
347        float maxLon = -Float.MAX_VALUE;
348        float maxLat = -Float.MAX_VALUE;
349    
350        float[][] corners = null;
351    
352        if (domainSet instanceof Linear2DSet) {
353          Linear1DSet lset = ((Linear2DSet)domainSet).getLinear1DComponent(0);
354          start0 = (float) lset.getFirst();
355          stop0 = (float) lset.getLast();
356          len0 = lset.getLengthX();
357          lset = ((Linear2DSet)domainSet).getLinear1DComponent(1);
358          start1 = (float) lset.getFirst();
359          stop1 = (float) lset.getLast();
360          len1 = lset.getLengthX();
361    
362          float x, y, del_x, del_y;
363          float lonA = Float.NaN;
364          float lonB = Float.NaN;
365          float lonC = Float.NaN;
366          float lonD = Float.NaN;
367          float latA = Float.NaN;
368          float latB = Float.NaN;
369          float latC = Float.NaN;
370          float latD = Float.NaN;
371    
372          int nXpts = len0/1;
373          int nYpts = len1/1;
374    
375          del_x = (stop0 - start0)/nXpts;
376          del_y = (stop1 - start1)/nYpts;
377          x = start0;
378          y = start1;
379          try {
380            for (int j=0; j<nYpts; j++) {
381              y = start1+j*del_y;
382              for (int i=0; i<nXpts; i++) {
383                x = start0 + i*del_x;
384                float[][] lonlat = cs.toReference(new float[][] {{x}, {y}});
385                float lon = lonlat[0][0];
386                float lat = lonlat[1][0];
387                if (!Float.isNaN(lon) && !Float.isNaN(lat)) {
388                  lonA = lon;
389                  latA = lat;
390                  break;
391                }
392              }
393              for (int i=0; i<nXpts; i++) {
394                x = stop0 - i*del_x;
395                float[][] lonlat = cs.toReference(new float[][] {{x}, {y}});
396                float lon = lonlat[0][0];
397                float lat = lonlat[1][0];
398                if (!Float.isNaN(lon) && !Float.isNaN(lat)) {
399                  lonB = lon;
400                  latB = lat;
401                  break;
402                }
403              }
404              if (!Float.isNaN(lonA) && !Float.isNaN(lonB)) {
405                break;
406              }
407            }
408    
409            for (int j=0; j<nYpts; j++) {
410              y = stop1-j*del_y;
411              for (int i=0; i<nXpts; i++) {
412                x = start0 + i*del_x;
413                float[][] lonlat = cs.toReference(new float[][] {{x}, {y}});
414                float lon = lonlat[0][0];
415                float lat = lonlat[1][0];
416                if (!Float.isNaN(lon) && !Float.isNaN(lat)) {
417                  lonC = lon;
418                  latC = lat;
419                  break;
420                }
421              }
422              for (int i=0; i<nXpts; i++) {
423                x = stop0 - i*del_x;
424                float[][] lonlat = cs.toReference(new float[][] {{x}, {y}});
425                float lon = lonlat[0][0];
426                float lat = lonlat[1][0];
427                if (!Float.isNaN(lon) && !Float.isNaN(lat)) {
428                  lonD = lon;
429                  latD = lat;
430                  break;
431                }
432              }
433              if (!Float.isNaN(lonC) && !Float.isNaN(lonD)) {
434                break;
435              }
436             }
437             corners = new float[][] {{lonA,lonB,lonC,lonD},{latA,latB,latC,latD}};
438             for (int k=0; k<corners[0].length; k++) {
439                float lon = corners[0][k];
440                float lat = corners[1][k];
441                /**
442                if (lon < minLon) minLon = lon;
443                if (lat < minLat) minLat = lat;
444                if (lon > maxLon) maxLon = lon;
445                if (lat > maxLat) maxLat = lat;
446                */
447             }
448           } catch (Exception e) {
449           }
450        }
451        else if (domainSet instanceof Gridded2DSet) {
452          int[] lens = ((Gridded2DSet)domainSet).getLengths();
453          start0 = 0f;
454          start1 = 0f;
455          stop0 = (float) lens[0];
456          stop1 = (float) lens[1];
457    
458          float x, y, del_x, del_y;
459          del_x = (stop0 - start0)/10;
460          del_y = (stop1 - start1)/10;
461          x = start0;
462          y = start1;
463          try {
464            for (int j=0; j<11; j++) {
465              y = start1+j*del_y;
466              for (int i=0; i<11; i++) {
467                x = start0+i*del_x;
468                float[][] lonlat = ((Gridded2DSet)domainSet).gridToValue(new float[][] {{x}, {y}});
469                float lon = lonlat[0][0];
470                float lat = lonlat[1][0];
471                if ((lon > 180 || lon < -180) || (lat > 90 || lat < -90)) continue;
472                if (lon < minLon) minLon = lon;
473                if (lat < minLat) minLat = lat;
474                if (lon > maxLon) maxLon = lon;
475                if (lat > maxLat) maxLat = lat;
476              }
477            }
478          } catch (Exception e) {
479          }
480        }
481    
482    
483        float del_lon = maxLon - minLon;
484        float del_lat = maxLat - minLat;
485    
486        return corners;
487      }
488    
489      public static Rectangle2D getLonLatBoundingBox(Set domainSet) {
490        CoordinateSystem cs = 
491          ((SetType)domainSet.getType()).getDomain().getCoordinateSystem();
492    
493        float start0, stop0, start1, stop1;
494        int len0, len1;
495        float minLon = Float.MAX_VALUE;
496        float minLat = Float.MAX_VALUE;
497        float maxLon = -Float.MAX_VALUE;
498        float maxLat = -Float.MAX_VALUE;
499    
500    
501        if (domainSet instanceof Linear2DSet) {
502          Linear1DSet lset = ((Linear2DSet)domainSet).getLinear1DComponent(0);
503          start0 = (float) lset.getFirst();
504          stop0 = (float) lset.getLast();
505          len0 = lset.getLengthX();
506          lset = ((Linear2DSet)domainSet).getLinear1DComponent(1);
507          start1 = (float) lset.getFirst();
508          stop1 = (float) lset.getLast();
509          len1 = lset.getLengthX();
510    
511          float x, y, del_x, del_y;
512          float lonA = Float.NaN;
513          float lonB = Float.NaN;
514          float lonC = Float.NaN;
515          float lonD = Float.NaN;
516          float latA = Float.NaN;
517          float latB = Float.NaN;
518          float latC = Float.NaN;
519          float latD = Float.NaN;
520    
521          int nXpts = len0/8;
522          int nYpts = len1/8;
523    
524          del_x = (stop0 - start0)/nXpts;
525          del_y = (stop1 - start1)/nYpts;
526    
527          x = start0;
528          y = start1;
529          try {
530            for (int j=0; j<nYpts; j++) {
531              y = start1+j*del_y;
532              for (int i=0; i<nXpts; i++) {
533                x = start0 + i*del_x;
534                float[][] lonlat = cs.toReference(new float[][] {{x}, {y}});
535                float lon = lonlat[0][0];
536                float lat = lonlat[1][0];
537                if (!Float.isNaN(lon) && !Float.isNaN(lat)) {
538                  lonA = lon;
539                  latA = lat;
540                  break;
541                }
542              }
543              for (int i=0; i<nXpts; i++) {
544                x = stop0 - i*del_x;
545                float[][] lonlat = cs.toReference(new float[][] {{x}, {y}});
546                float lon = lonlat[0][0];
547                float lat = lonlat[1][0];
548                if (!Float.isNaN(lon) && !Float.isNaN(lat)) {
549                  lonB = lon;
550                  latB = lat;
551                  break;
552                }
553              }
554              if (!Float.isNaN(lonA) && !Float.isNaN(lonB)) {
555                break;
556              }
557            }
558    
559            for (int j=0; j<nYpts; j++) {
560              y = stop1-j*del_y;
561              for (int i=0; i<nXpts; i++) {
562                x = start0 + i*del_x;
563                float[][] lonlat = cs.toReference(new float[][] {{x}, {y}});
564                float lon = lonlat[0][0];
565                float lat = lonlat[1][0];
566                if (!Float.isNaN(lon) && !Float.isNaN(lat)) {
567                  lonC = lon;
568                  latC = lat;
569                  break;
570                }
571              }
572              for (int i=0; i<nXpts; i++) {
573                x = stop0 - i*del_x;
574                float[][] lonlat = cs.toReference(new float[][] {{x}, {y}});
575                float lon = lonlat[0][0];
576                float lat = lonlat[1][0];
577                if (!Float.isNaN(lon) && !Float.isNaN(lat)) {
578                  lonD = lon;
579                  latD = lat;
580                  break;
581                }
582              }
583              if (!Float.isNaN(lonC) && !Float.isNaN(lonD)) {
584                break;
585              }
586             }
587             float[][] corners = {{lonA,lonB,lonC,lonD},{latA,latB,latC,latD}};
588             for (int k=0; k<corners[0].length; k++) {
589                float lon = corners[0][k];
590                float lat = corners[1][k];
591                if (lon < minLon) minLon = lon;
592                if (lat < minLat) minLat = lat;
593                if (lon > maxLon) maxLon = lon;
594                if (lat > maxLat) maxLat = lat;
595             }
596           } catch (Exception e) {
597           }
598        }
599        else if (domainSet instanceof Gridded2DSet) {
600          int[] lens = ((Gridded2DSet)domainSet).getLengths();
601          start0 = 0f;
602          start1 = 0f;
603          stop0 = (float) lens[0];
604          stop1 = (float) lens[1];
605    
606          float x, y, del_x, del_y;
607          del_x = (stop0 - start0)/10;
608          del_y = (stop1 - start1)/10;
609          x = start0;
610          y = start1;
611          try {
612            for (int j=0; j<11; j++) {
613              y = start1+j*del_y;
614              for (int i=0; i<11; i++) {
615                x = start0+i*del_x;
616                float[][] lonlat = ((Gridded2DSet)domainSet).gridToValue(new float[][] {{x}, {y}});
617                float lon = lonlat[0][0];
618                float lat = lonlat[1][0];
619                if ((lon > 180 || lon < -180) || (lat > 90 || lat < -90)) continue;
620                if (lon < minLon) minLon = lon;
621                if (lat < minLat) minLat = lat;
622                if (lon > maxLon) maxLon = lon;
623                if (lat > maxLat) maxLat = lat;
624              }
625            }
626          } catch (Exception e) {
627          }
628        }
629        
630    
631        float del_lon = maxLon - minLon;
632        float del_lat = maxLat - minLat;
633    
634        return new Rectangle2D.Float(minLon, minLat, del_lon, del_lat);
635      }
636    
637      public float[] radianceToBrightnessTemp(float[] values, float channelValue) {
638        float c1=1.191066E-5f;           //- mW/m2/ster/cm^-4
639        float c2=1.438833f;              //- K*cm
640        float nu = channelValue;         //- nu: wavenumber
641        float B, K, BT;
642    
643        int n_values = values.length;
644        float[] new_values = new float[n_values];
645        for (int i=0; i<n_values;i++) {
646          B = values[i];
647          K = (c1*nu*nu*nu)/B;
648          if (K == 0.0) {
649            BT = B;
650          } 
651          else {
652            BT = c2*nu/((float) (Math.log((double)((c1*nu*nu*nu)/B)+1.0f)) );
653          }
654          if (BT < 0.01) BT = Float.NaN;
655          new_values[i] = BT;
656        }
657        return new_values;
658      }
659    
660      public float[] radianceToBrightnessTemp(float[] values, float channelValue, String platformName, String sensorName) 
661         throws Exception {
662        float[] new_values = null;
663    
664        if (sensorName == null) {
665          new_values = radianceToBrightnessTemp(values, channelValue);
666        }
667        else if (sensorName == "MODIS") {
668          int channelIndex = spectrumAdapter.getChannelIndexFromWavenumber(channelValue);
669          int band_number = MODIS_L1B_Utility.emissive_indexToBandNumber(channelIndex);
670          new_values = MODIS_L1B_Utility.modis_radiance_to_brightnessTemp(platformName, band_number, values);
671        }
672        return new_values;
673      }
674    
675      public float[] radianceToBrightnessTempSpectrum(float[] values, float[] channelValues) {
676        //- Converts radiances [mW/ster/m2/cm^-1] to BT [K]
677        //-  Input: nu  array of wavenmbers [cm^-1]
678        //-          B   radiances [mW/ster/m2/cm^-1]
679        //-  Output: bt brightness temperature in [K]
680        //-   Paolo Antonelli
681        //-   Wed Feb 25 16:43:05 CST 1998
682    
683        float c1=1.191066E-5f;           //- mW/m2/ster/cm^-4
684        float c2=1.438833f;              //- K*cm
685    
686        float nu;                        //- wavenumber
687        float B, BT;
688    
689        int n_values = values.length;
690        float[] new_values = new float[n_values];
691        for (int i=0; i<n_values; i++) {
692          nu = channelValues[i];
693          B = values[i];
694          BT = c2*nu/((float) (Math.log(((c1*nu*nu*nu)/B)+1.0f)) );
695          new_values[i] = BT;
696        }
697        return new_values;
698      }
699    
700    
701      public float[] radianceToBrightnessTempSpectrum(float[] values, float[] channelValues,
702                                     String platformName, String sensorName) 
703         throws Exception
704      {
705        float[] new_values = null;
706    
707        if (sensorName == null) {
708          new_values =  radianceToBrightnessTempSpectrum(values, channelValues);
709        }
710        else if (sensorName == "MODIS") {
711          new_values = new float[values.length];
712          for (int k=0; k<new_values.length; k++) {
713            int channelIndex = spectrumAdapter.getChannelIndexFromWavenumber(channelValues[k]);
714            int band_number = MODIS_L1B_Utility.emissive_indexToBandNumber(channelIndex);
715            float[] tmp = new float[1];
716            tmp[0] = values[k];
717            new_values[k] = (MODIS_L1B_Utility.modis_radiance_to_brightnessTemp(platformName, band_number, tmp))[0];
718          }
719        }
720    
721        return new_values;
722      }
723    
724      public HashMap getDefaultSubset() {
725        HashMap subset = swathAdapter.getDefaultSubset();
726        double chanIdx=0;
727    
728        try {
729           chanIdx = spectrumAdapter.getChannelIndexFromWavenumber(init_wavenumber);
730        }
731        catch (Exception e) {
732          System.out.println("couldn't get chanIdx, using zero");
733        }
734          
735        subset.put(SpectrumAdapter.channelIndex_name, new double[] {chanIdx, chanIdx, 1});
736        return subset;
737      }
738     
739    
740      public SpectrumAdapter getSpectrumAdapter() {
741        return spectrumAdapter;
742      }
743    }