001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2024 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 https://www.gnu.org/licenses/. 027 */ 028 029package edu.wisc.ssec.mcidasv.data.hydra; 030import visad.Set; 031 032 033public class MODIS_L1B_Utility { 034 /** 035 Emissive bands 036 taken from pfm-in-band-rsr.pdf (Aqua) 037 038 band center width (m*10E6) 039 begin end 040------------------------------------ 041 20 3.799 3.660 3.840 042 21 3.992 3.929 3.989 043 22 3.968 3.929 3.989 044 23 4.070 4.020 4.080 045 24 4.476 4.433 4.498 046 25 4.549 4.482 4.549 047 27 6.784 6.535 6.895 048 28 7.345 7.175 7.475 049 29 8.503 8.400 8.700 050 30 9.700 9.580 9.880 051 31 11.000 10.780 11.280 052 32 12.005 11.770 12.270 053 33 13.351 13.185 13.485 054 34 13.717 13.485 13.785 055 35 13.908 13.785 14.085 056 36 14.205 14.085 14.385 057**/ 058 059 //... Effective central wavelengths (micrometers) 060 static double[] cwl_aqua = { 061 3.799, 3.992, 3.968, 4.070, 4.476, 4.549, 6.784, 062 7.345, 8.503, 9.700, 11.000, 12.005, 13.351, 13.717, 13.908, 14.205}; 063 064 //... Effective central wavenumbers (inverse centimeters) 065 static double[] cwn_terra = { 066 2.641767E+03, 2.505274E+03, 2.518031E+03, 2.465422E+03, 067 2.235812E+03, 2.200345E+03, 1.478026E+03, 1.362741E+03, 068 1.173198E+03, 1.027703E+03, 9.081998E+02, 8.315149E+02, 069 7.483224E+02, 7.309089E+02, 7.188677E+02, 7.045309E+02}; 070 071 //... Temperature correction slopes (no units) 072 static double[] tcs_terra = { 073 9.993487E-01, 9.998699E-01, 9.998604E-01, 9.998701E-01, 074 9.998825E-01, 9.998849E-01, 9.994942E-01, 9.994937E-01, 075 9.995643E-01, 9.997499E-01, 9.995880E-01, 9.997388E-01, 076 9.999192E-01, 9.999171E-01, 9.999174E-01, 9.999264E-01}; 077 078 //... Temperature correction intercepts (Kelvin) 079 static double[] tci_terra = { 080 4.744530E-01, 9.091094E-02, 9.694298E-02, 8.856134E-02, 081 7.287017E-02, 7.037161E-02, 2.177889E-01, 2.037728E-01, 082 1.559624E-01, 7.989879E-02, 1.176660E-01, 6.856633E-02, 083 1.903625E-02, 1.902709E-02, 1.859296E-02, 1.619453E-02}; 084 085 //... Effective central wavenumbers (inverse centimeters) 086 static double[] cwn_aqua = { 087 2.647418E+03, 2.511763E+03, 2.517910E+03, 2.462446E+03, 088 2.248296E+03, 2.209550E+03, 1.474292E+03, 1.361638E+03, 089 1.169637E+03, 1.028715E+03, 9.076808E+02, 8.308397E+02, 090 7.482977E+02, 7.307761E+02, 7.182089E+02, 7.035020E+02}; 091 092 //... Temperature correction slopes (no units) 093 static double[] tcs_aqua = { 094 9.993438E-01, 9.998680E-01, 9.998649E-01, 9.998729E-01, 095 9.998738E-01, 9.998774E-01, 9.995732E-01, 9.994894E-01, 096 9.995439E-01, 9.997496E-01, 9.995483E-01, 9.997404E-01, 097 9.999194E-01, 9.999071E-01, 9.999176E-01, 9.999211E-01}; 098 099 //... Temperature correction intercepts (Kelvin) 100 static double[] tci_aqua = { 101 4.792821E-01, 9.260598E-02, 9.387793E-02, 8.659482E-02, 102 7.854801E-02, 7.521532E-02, 1.833035E-01, 2.053504E-01, 103 1.628724E-01, 8.003410E-02, 1.290129E-01, 6.810679E-02, 104 1.895925E-02, 2.128960E-02, 1.857071E-02, 1.733782E-02}; 105 106// Constants are from "The Fundamental Physical Constants", 107// Cohen, E. R. and B. N. Taylor, Physics Today, August 1993. 108 109// Planck constant (Joule second) 110 static double h = 6.6260755e-34; 111 112// Speed of light in vacuum (meters per second) 113 static double c = 2.9979246e+8; 114 115// Boltzmann constant (Joules per Kelvin) 116 static double k = 1.380658e-23; 117 118// Derived constants 119 static double c1 = 2.0 * h * c * c; 120 static double c2 = (h * c) / k; 121 122 public static float[] modis_radiance_to_brightnessTemp(String platformName, int band_number, float[] values) 123 throws Exception 124 { 125 return (Set.doubleToFloat( 126 new double[][] {modis_radiance_to_brightnessTemp(platformName,band_number,(Set.floatToDouble(new float[][] {values}))[0])}))[0]; 127 } 128 129 public static double[] modis_radiance_to_brightnessTemp(String platformName, int band_number, double[] values) 130 throws Exception 131 { 132 133 if ((band_number < 20) || (band_number > 36) || (band_number == 26)) { 134 throw new Exception("bad band number: "+band_number+" band 20-36 but not 26"); 135 } 136 137 int index; 138 139 if (band_number <= 25) { 140 index = band_number - 19; 141 } 142 else { 143 index = band_number - 20; 144 } 145 index -= 1; 146 147 double cwn; 148 double tcs; 149 double tci; 150 151 if (platformName.equals("Terra")) { 152 cwn = cwn_terra[index]; 153 tcs = tcs_terra[index]; 154 tci = tci_terra[index]; 155 } 156 else if (platformName.equals("Aqua")) { 157 cwn = cwn_aqua[index]; 158 tcs = tcs_aqua[index]; 159 tci = tci_aqua[index]; 160 } 161 else { 162 throw new Exception("platformName must equal: Terra or Aqua"); 163 } 164 165 //... Compute Planck radiance - MODIS units 166 //... Watts per square meter per steradian per micron 167 168 //... Convert wavelength to meters 169 double ws = 1.0E-6 * (1.0E+4 / cwn); 170 171 //... Compute brightness temperature 172 int len = values.length; 173 double[] new_values = new double[len]; 174 for (int kk = 0; kk < len; kk++) { 175 double rad = values[kk]; 176 double BT = ( c2 / (ws * Math.log(c1 /(1.0E+6*rad*(ws*ws*ws*ws*ws)) + 1.0))-tci)/tcs; 177 new_values[kk] = BT; 178 } 179 180 return new_values; 181 } 182 183 public static int emissive_indexToBandNumber(int channelIndex) { 184 int[] bandNumbers = new int[] {20,21,22,23,24,25,27,28,29,30,31,32,33,34,35,36}; 185 return bandNumbers[channelIndex]; 186 } 187 188 public static float[][] brightnessTemp_to_radiance(float[][] values, int band_number) 189 throws Exception { 190 int index = getIndexFromBandNumber(band_number); 191 return new float[][] {brightnessTemp_to_radiance(values[0], (float) cwl_aqua[index])}; 192 } 193 194 public static float[] brightnessTemp_to_radiance(float[] values, float wavelength) { 195 196 // Constants are from "The Fundamental Physical Constants", 197 // Cohen, E. R. and B. N. Taylor, Physics Today, August 1993. 198 199 double w = (double) wavelength; 200 201 // Planck constant (Joule second) 202 double h = 6.6260755e-34; 203 204 // Speed of light in vacuum (meters per second) 205 double c = 2.9979246e8; 206 207 // Boltzmann constant (Joules per Kelvin) 208 double k = 1.380658e-23; 209 210 // Derived constants 211 double c1 = 2.0 * h * c * c; 212 double c2 = (h * c) / k; 213 214 // Convert wavelength to meters 215 double ws = 1.0e-6 * w; 216 217 // Compute brightness temperature 218 float[] new_values = new float[values.length]; 219 for (int i=0; i<values.length; i++) { 220 double t = (double) values[i]; 221 new_values[i] = (float) ((1.0e-6*(c1/(ws*ws*ws*ws*ws)))/(Math.exp(c2/(ws * t)) - 1.0)); 222 } 223 224 return new_values; 225 } 226 227 public static int getIndexFromBandNumber(int band_number) throws Exception { 228 229 if ((band_number < 20) || (band_number > 36) || (band_number == 26)) { 230 throw new Exception("bad band number: "+band_number+" band 20-36 but not 26"); 231 } 232 233 int index; 234 235 if (band_number <= 25) { 236 index = band_number - 19; 237 } 238 else { 239 index = band_number - 20; 240 } 241 index -= 1; 242 243 return index; 244 } 245 246}