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