OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
Emissive_Cal.c
Go to the documentation of this file.
1 #include "Preprocess.h"
2 #include "Emissive_Cal.h"
3 #include "HDF_Lib.h"
4 #include "PGS_Error_Codes.h"
5 #include "FNames.h"
6 #include <math.h>
7 
8 #define FLOAT_TO_PIXEL(L, L_max, L_min, scale, offset, Scale_Integer) \
9 if ((L) <= (L_min)) Scale_Integer = DN_MIN; \
10 else if ((L) >= (L_max)) Scale_Integer = DN15_SAT; \
11 else Scale_Integer = (uint16)( ( (L)/(scale) + (offset) ) + 0.5 );
12 
13 /*
14  Revision 05/10/06
15  Skip "Bad_L1A_Error_Out" errors rather than exiting.
16  J. Gales
17 */
18 
19 PGSt_SMF_status Emissive_Cal (int16 S,
20  int16 MS,
21  L1B_granule_t *L1B_Gran,
22  L1A_Scan_t *L1A_Scan,
23  L1B_Scan_t *L1B_Scan,
24  Preprocess_Emiss_t *PP_emiss,
25  emiss_tables_t *emiss_tables,
26  QA_tables_t *QA_tables,
27  QA_Data_t *QA,
28  L1B_Scan_Metadata_t *L1B_Scan_Meta)
29 /*
30 !C**********************************************************************
31 !Description:
32  This routine accomplishes the calibration of one scan of EV pixels for
33  Emissive bands. Corrections to the digital numbers are applied for
34  electronic background, for the angular dependence of the response of the
35  scan mirror, for non-linearities in the Analog to Digital Converters.
36  Correction may also be applied for cross-talk for PC bands (the leak from
37  band 31 to band 32, 33, 34, 35, 36) depending on the switch value in the
38  lookup table. The radiance is computed after the corrections. If the
39  radiance can be computed and is in a valid range, it is converted
40  to a scaled integer in the range of [0-32767]. If a valid value cannot be
41  computed, the scaled integer is set to a value in the range of [32768-65535].
42  Specific values in the range of [32768-65535] are used to denote why a valid
43  value could not be obtained (a list of these is in the L1B file
44  specifications). This routine also computes the uncertainty in the
45  radiance product for every pixel, and converts the uncertainty to a
46  4-bit uncertainty index, stored in the 4 least significant bits of an 8-bit
47  unsigned integer.
48 
49 !Input Parameters:
50  int16 S Current scan index
51  int16 MS The corresponding mirror side
52  L1B_granule_t *L1B_Gran contains scale and offset factors
53  L1A_Scan_t *L1A_Scan contains earth view DN values
54  Preprocess_Emiss_t *PP_emiss contains ADC index, calibration coefficients a0,
55  b1, a2 preprocessed data, radiance at scan mirror
56  temperature, NEdL and electronic background DNs
57  emiss_tables_t *emiss_tables contains emissive lookup tables values used in
58  emissive calibration
59  QA_tables_t *QA_tables contains the dead detector look up table value and
60  NEdL look up table value
61  QA_Data_t *QA contains values to determine if the instrument is
62  in a sector rotation and if the moon is in SV KOB.
63 !Output Parameters:
64  L1B_Scan_t *L1B_Scan contains scaled integers and uncertainty indices
65  L1B_Scan_Metadata_t *L1B_Scan_Meta contains the bit QA value for negative radiance
66  beyond noise level.
67 !Revision History:
68  $Log: Emissive_Cal.c,v $
69  Revision 1.13 2011-04-19 12:48:31-04 ltan
70  Typo erro correction
71 
72  Revision 1.12 2011-04-07 14:38:15-04 xgeng
73  TEB uncertainty algorithm update.
74 
75  Revision 1.11 2010-11-15 11:36:45-05 xgeng
76  No calibration is performed for the scan if both sides of PCLW electronics are on at the same time.
77 
78  Revision 1.10 2005/01/18 21:57:33 ltan
79  Added new file attributes prefixed with HDFEOS_FractionalOffset
80 
81 
82  gevision 02.26, March 26, 2003 Razor Issue #191
83  Change hard-coded band (28) whose EV data are saved for SWIR OOB correction to be
84  determined by a LUT instead.
85  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
86 
87  Revision 02.25, April 25, 2002 Razor Issue #180
88  Moved checks on Dead detector, sector rotation, negative SV/BB average, and
89  negative b1 outside of Frame loop.
90  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
91 
92  Revision 02.24, March 25, 2001 Razor Issue #178
93  Removed ADC Correction
94  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
95 
96  Revision 02.23, February 2002 Razor Issue #180
97  Inserted check on B1 to be sure it is not negative
98  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
99 
100  Revision 02.22, November 9, 2001 Razor Issue #168
101  Cleanup of spelling/grammar; changed TOLLERANCE to TOLERANCE
102  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
103 
104  Revision 02.21, January 16, 2001
105  Eliminated the "pow" functions in calculations of uncertainty.
106  Also made other efficiency improvements and made variables a little
107  more like the algorithm document.
108  Changed frame index (F) to frame number in uncertainty calculation
109  (minor bug in previous version)
110  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
111 
112  Revision 02.20 August 26, 1999
113  Added checking if the EV data read from L1A are valid.
114  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
115  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
116 
117  Revision 02.19 August 1999
118  Removed interpolation correction.
119  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
120  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
121 
122  Revision 02.18 August 1999
123  Implemented changes to meet the requirement of new ADC algorithms. See SDF.
124  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
125  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
126 
127  Revision 02.17 Aug 10, 1999
128  Used L_Max and L_Min LUTs
129  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
130 
131  Revision 02.16 May 23, 1999
132  Many changes leading up to the May 30 delivery. See SDF.
133  Jim Rogers (rogers@mcst.gsfc.nasa.gov) and Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
134 
135  Revision 02.15 April 12, 1999
136  Removed cubic term a3
137  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
138 
139  Revision 02.12 Feb 9, 1999
140  Added use of variables ADC_correction_switch, PCX_correction_switch and
141  INT_correction_switch set to macro values to remove compiler warnings.
142  Macros in upper case.
143  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
144 
145  Revision 02.11 July 1998
146  modified EV, SI, UI to match L1B_Scan_t data structure change.
147  Zhenying Gu (zgu@ltpmail.gsfc.nasa.gov)
148 
149  Revision 02.10 Mar. 1998
150  Removed D_inv, which has already been taken care of in L1A
151  Removed all the V vs L algorithm implementation.
152  Added the DN vs. L algorithm implementation
153  Shi-Yue Qiu (syqiu@ltpmail.gsfc.nasa.gov)
154 
155  Revision 02.00 Jan. 1997
156  Plugged in lookup tables and added Preprocess_data_t *PP as an input parameter;
157  eliminated DED as an input parameter;
158  expanded processing scope from one band to one scan.
159  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
160 
161  Revision 01.01 1996/04/05
162  Update to match Version 1 Design Document
163  Joan Baden(baden@highwire.gsfc.nasa.gov)
164  John Hannon(hannon@highwire.gsfc.nasa.gov)
165  Neal Devine(neal.devine@gsfc.nasa.gov) -- debugging 1996/5/9-13
166 
167  Revision 01.00 1993
168  Initial development
169  Geir Kvaran(geir@highwire.gsfc.nasa.gov)
170 
171 !Team-unique Header:
172  This software is developed by the MODIS Characterization Support
173  Team (MCST)for the National Aeronautics and Space Administration,
174  Goddard Space Flight Center, under contract NAS5-32373.
175 
176 !References and Credits:
177  HDF portions developed at the National Center for Supercomputing
178  Applications at the University of Illinois at Urbana-Champaign.
179 
180 !Design Notes:
181 
182 !END********************************************************************
183 */
184 {
185  int16 D = 0; /* detector index within band (0,9) */
186  int16 D_emiss = 0; /* Emiss detector index (0,159) */
187  int16 D_490 = 0; /* modis detector index (0,489) */
188  int16 B = 0; /* band index within L1A resolution (1km_Emiss res only here) */
189  int16 B_emiss = 0; /* Emiss band index (0,15) */
190  int16 B_xt = 0; /* PCX band index (32,36) */
191  int16 B_38 = 0; /* MODIS band index (0,37) */
192  int16 F = 0; /* frame index (0 -> 1353) */
193  int16 flag = 0; /* for L < -NEdL */
194  int16 F_shift = 0; /* frame index in PCX */
195  float32 L_ev = 0; /* EV radiance */
196  int16 DN_ev = 0; /* must use signed integer (since MISSING FLAG is -1)*/
197  float32 dn_ev = 0; /* corrected Earth view DN */
198  float32 dn_ev_31[10][EV_1km_FRAMES]; /* for PCX correction */
199  float32 Fn = 0;
200  float32 dL_ev = 0;
201 
202  /*
203  * obsolete due to TEB UI algorithm update, 3/22/2011, Xu Geng
204  */
205  /*float32 Sigma_TEB_PV_resid_elec_sq; */ /* holds residual electronic crosstalk
206  contribution to sigma^2 */
207  /*float32 Sigma_TEB_ADC_sq; */ /* holds RSB ADC contribution to sigma^2 */
208  /*float32 Calibr_resid; */ /* holds calibration polynomial fit
209  residual */
210  /*float32 *calibr_resid_coeffs; */ /* temporary pointer to table for one
211  detector */
212  /*float32 *si0, *si1; */ /* temporary pointer to Ucoeff tables */
213  /*float32 ri0, ri1; */ /* summation variables for uncert coeff */
214 
215  float32 dn_PCX_corr = 0; /* PC cross talk correction. Must be
216  initialized to 0. */
217  float32 dtemp; /* temporary variable */
218 
219  uint16 bad_SI = 0; /* flag value for SI */
220  boolean bad_value = False;
221 
222  int8 PCX_correction_switch;
223  int16 uncert;
224 
225  int16 SV_frame_no = 0; /* Frame number to use for SV RVS Correction */
226 
227  /*
228  * If the mirror side value is not 0 or 1, it is not a valid value.
229  * It is most likely this scan is a missing scan and the following
230  * calculation should not be proceeded.
231  */
232 
233  if (MS != 0 && MS != 1)
234  SMF_ERROR(MODIS_F_NOK, "Invalid mirror side value in Emissive_Cal()");
235 
236  /*
237  * The Band chosen for the SWIR OOB correction may be any emissive band.
238  * Let "X" denote that band number in the following discussion. The values
239  * of dn for band "X" are saved for use in "SWIR_out_of_band_correction".
240  * It is assumed in that function that a negative value of dn_"X" is not
241  * valid for making the SWIR OOB correction. Thus, initialize the dn_"X"
242  * to a negative value before the loop through individual pixels. dn_"X"
243  * will only be re-assigned if a value of dn is actually calculated.
244  */
245 
246  for (D = 0; D < DETECTORS_PER_1KM_BAND; D++)
247  for (F = 0; F < EV_1km_FRAMES; F++)
248  L1B_Scan->dn_X[D][F] = -1.;
249 
250  /*Initialize extended indices, to be incremented within loops*/
251  /*Note: band_26 is included in L1A_BANDS_AT_RES[INDEX_1000M_EMISS]*/
252  B_38 = NUM_BANDS - NUM_EMISSIVE_BANDS - 1;
253  B_emiss = 0;
254  D_emiss = 0;
255  D_490 = NUM_REFLECTIVE_DETECTORS - 10;
256  SV_frame_no = emiss_tables->RVS_BB_SV_Frame_No[1];
257 
258  PCX_correction_switch = emiss_tables->PCX_correction_switch;
259 
260  for (B = 0; B < L1A_BANDS_AT_RES[INDEX_1000M_EMISS]; B++, B_38++)
261  {
262  /*Skip band_26*/
263  if (B == MODIS_BAND26_INDEX_AT_RES)
264  {
265  D_490 += 10; /* one band contains 10 detectors */
266  continue;
267  }
268  /* Initialize the dn_ev_31 */
269  if ( PCX_correction_switch == ON && B == BAND31)
270  {
271  for (D = 0; D < DETECT_PER_BAND_AT_RES[INDEX_1000M_EMISS]; D++)
272  for (F = 0; F < EV_1km_FRAMES; F++)
273  dn_ev_31[D][F] = 0;
274  }
275  for (D = 0; D < DETECT_PER_BAND_AT_RES[INDEX_1000M_EMISS];
276  D++, D_emiss++, D_490++)
277  {
278  /*
279  * obsolete due to TEB UI algorithm update, 3/22/2011, Xu Geng
280  */
281  /*
282  Sigma_TEB_PV_resid_elec_sq =
283  emiss_tables->Sigma_TEB_PV_resid_elec[D_emiss] *
284  emiss_tables->Sigma_TEB_PV_resid_elec[D_emiss];
285 
286  Sigma_TEB_ADC_sq = emiss_tables->Sigma_TEB_ADC[D_emiss] *
287  emiss_tables->Sigma_TEB_ADC[D_emiss];
288  */
289 
290  /* Initialize the logical "bad value" signal: */
291  bad_value = False;
292 
293  /* Check if the detector is dead */
294 
295  if (QA_tables->common_QA_tables.dead_detector[D_490] == 1)
296  {
297  bad_SI = DEAD_DETECTOR_SI;
298  L1B_Gran->valid_pixels[B_38] -= EV_1km_FRAMES;
299  L1B_Gran->dead_detector_pixels[B_38] += EV_1km_FRAMES;
301  bad_value = True;
302  }
303 
304  /* Check if the instrument is in a sector rotation */
305 
306  else if (QA->QA_common.Sector_Rotation[S] == True)
307  {
308  bad_SI = SECTOR_ROTATION_SI;
309  L1B_Gran->valid_pixels[B_38] -= EV_1km_FRAMES;
310  L1B_Gran->bad_data_flag[B_38] = 1;
312  bad_value = True;
313  }
314 
315  /* Check if the instrument has both sides of PCLW electronics on at the same time */
316 
317  else if (QA->QA_common.Electronic_Anomaly[S] == True)
318  {
319  bad_SI = UNABLE_CALIBRATE_SI;
320  L1B_Gran->valid_pixels[B_38] -= EV_1km_FRAMES;
321  L1B_Gran->bad_data_flag[B_38] = 1;
322  bad_value = True;
323  }
324 
325  /* Check if the zero point DN value is valid */
326 
327  else if ( PP_emiss->DN_sv[D_emiss][S] < 0)
328  {
329  bad_SI = ZERO_POINT_DN_SI;
330  L1B_Gran->valid_pixels[B_38] -= EV_1km_FRAMES;
331  L1B_Gran->bad_data_flag[B_38] = 1;
333  bad_value = True;
334  }
335 
336  /* Check to see that the b1 value is not negative. */
337 
338  else if (PP_emiss->b1[D_emiss][S] < 0)
339  {
340  bad_SI = TEB_B1_NOT_CALCULATED;
341  L1B_Gran->valid_pixels[B_38] -= EV_1km_FRAMES;
342  L1B_Gran->bad_data_flag[B_38] = 1;
344  bad_value = True;
345  }
346 
347  if (bad_value)
348  {
349  for (F = 0; F < EV_1km_FRAMES; F++)
350  {
351  L1B_Scan->SI.EV_1km_Emissive[B_emiss][D][F] = (uint16) bad_SI;
352  L1B_Scan->UI.EV_1km_Emissive_UI[B_emiss][D][F] = BAD_DATA_UI;
353  }
354  continue;
355  }
356 
357  for (F = 0; F < EV_1km_FRAMES; F++)
358  {
359 
360  DN_ev = L1A_Scan->EV_1km_night[D][B][F];
361 
362  if (DN_ev < MISSING_L1A_FLAG || DN_ev > SATURATED_DN) {
363  continue;
364  /*
365  Bad_L1A_Error_Out("EV_1km_night",
366  " out of range in middle L1A file, Emissive_Cal(), Emissive_Cal.c");
367  */
368  }
369 
370  /* Skip missing data */
371 
372  if (DN_ev == MISSING_L1A_FLAG)
373  {
374  L1B_Scan->SI.EV_1km_Emissive[B_emiss][D][F] = L1A_DN_MISSING_SI;
375  L1B_Scan->UI.EV_1km_Emissive_UI[B_emiss][D][F] = BAD_DATA_UI;
376  L1B_Gran->missing_pixels[B_38]++;
377  L1B_Gran->valid_pixels[B_38]--;
378  L1B_Gran->bad_data_flag[B_38] = 1;
380  continue;
381  }
382 
383  /* Check if the EV DN read from L1A file is saturated */
384 
385  if (DN_ev == SATURATED_DN)
386  {
387  L1B_Scan->SI.EV_1km_Emissive[B_emiss][D][F] = SATURATED_DETECTOR_SI;
388  L1B_Scan->UI.EV_1km_Emissive_UI[B_emiss][D][F] = BAD_DATA_UI;
389  L1B_Gran->saturated_pixels[B_38]++;
390  L1B_Gran->valid_pixels[B_38]--;
391  L1B_Gran->bad_data_flag[B_38] = 1;
392  QA->QA_common.num_saturated_EV_data[D_490]++;
393  continue;
394  }
395 
396  dn_ev = DN_ev - PP_emiss->DN_sv[D_emiss][S];
397 
398  /*
399  * Save the value of dn for band X (any TEB band) to use for SWIR OOB
400  * correction
401  */
402 
403  if (B == L1B_Scan->band_X)
404  L1B_Scan->dn_X[D][F] = dn_ev;
405 
406  /* check PCX Switch */
407  if ( PCX_correction_switch == ON )
408  {
409  dn_PCX_corr = 0;
410  if ( B == BAND31 ) dn_ev_31[D][F] = dn_ev;
411  else if( B >= BAND32 && B <= BAND36 )
412  {
413  B_xt = B - BAND32;
414  F_shift = F + emiss_tables->PC_XT[B_xt][D][1];
415  if ( F_shift >= 0 && F_shift < EV_1km_FRAMES &&
416  dn_ev_31[D][F_shift] > 0 )
417  {
418  dn_PCX_corr = -emiss_tables->PC_XT[B_xt][D][0]*0.01
419  *dn_ev_31[D][F_shift]
420  *emiss_tables->PC_XT[B_xt][D][2] +
421  emiss_tables->PC_XT[B_xt][D][3];
422  dn_ev += dn_PCX_corr;
423  }
424  }
425  }
426 
427 
428  /* Compute L_ev */
429  Fn = PP_emiss->a0[D_emiss][S] +
430  PP_emiss->b1[D_emiss][S] * dn_ev +
431  PP_emiss->a2[D_emiss][S] * dn_ev * dn_ev ;
432 
433  L_ev = (Fn -
434  (L1B_Gran->Emiss_Cal_Coeff.RVS_1km_Emiss_SV[D_emiss][MS] -
435  L1B_Gran->Emiss_Cal_Coeff.RVS_1km_Emiss_EV[D_emiss][F][MS])
436  * PP_emiss->Planck_mir[D_emiss][S] ) /
437  L1B_Gran->Emiss_Cal_Coeff.RVS_1km_Emiss_EV[D_emiss][F][MS];
438 
439  /* Check if the calculated radiance L exceeds the LUT L_Max.
440  * If so, then set the unusable data value for SI and UI and
441  * keep track of the number of instances of these pixels.
442  */
443 
444  if (L_ev > emiss_tables->L_Max[B_emiss])
445  {
446  L1B_Scan->SI.EV_1km_Emissive[B_emiss][D][F] = TEB_OR_RSB_GT_MAX_SI;
447  L1B_Scan->UI.EV_1km_Emissive_UI[B_emiss][D][F] = BAD_DATA_UI;
448  L1B_Gran->valid_pixels[B_38]--;
449  L1B_Gran->bad_data_flag[B_38] = 1;
451  continue;
452  }
453 
454  /* determine if the radiance is negative and below noise level */
455  if (L_ev < -QA_tables->emiss_QA_tables.NEdL[D_emiss])
456  {
457  flag = 1;
458  L1B_Gran->negative_value_below_noise_pixels[B_38]++;
459  L1B_Gran->valid_pixels[B_38]--;
460  L1B_Gran->bad_data_flag[B_38] = 1;
461  }
462 
463  /* Convert the product to scaled integer and store in the L1B scan */
464 
465  FLOAT_TO_PIXEL(L_ev,
466  emiss_tables->L_Max[B_emiss],
467  emiss_tables->L_Min[B_emiss],
468  L1B_Gran->SO.rad_scale_Emiss[B_emiss],
469  L1B_Gran->SO.rad_offset_Emiss[B_emiss],
470  L1B_Scan->SI.EV_1km_Emissive[B_emiss][D][F]);
471 
472  /*
473  * Check if NAD door is closed. If it is closed, set the most significant
474  * bit to 1. If SI is larger than the upper limit for the NAD closed SI
475  * value, set it to that value.
476  */
477 
478  if (QA->QA_common.NAD_Door_Open[S] == False)
479  {
480  L1B_Scan->SI.EV_1km_Emissive[B_emiss][D][F] |= 0x8000;
482 
483  if (L1B_Scan->SI.EV_1km_Emissive[B_emiss][D][F] > NAD_CLOSED_UPPER_SI)
484  L1B_Scan->SI.EV_1km_Emissive[B_emiss][D][F] = NAD_CLOSED_UPPER_SI;
485  }
486 
487  /*
488  * Set the uncertainty index.
489  */
490 
491  if (L_ev <= TOLERANCE || QA->QA_common.NAD_Door_Open[S] == False
492  || dn_ev <= TOLERANCE || PP_emiss->dn_bb[D_emiss][S] <= TOLERANCE )
493  {
494  L1B_Scan->UI.EV_1km_Emissive_UI[B_emiss][D][F] = BAD_DATA_UI;
495  }
496  else
497  {
498 
499  /*
500  * Compute uncertainty based on equation (3) in memo:
501  * "PFM TEB Radiometric Uncertainty and LUT Format - Update 2",
502  * Kwo-Fu (Vincent) Chiang, G. Godden and X. (Jack) Xiong,
503  * December 6, 1999.
504  *********************************************************
505  * The above algorithm is obsolete due to the recent update.
506  * Please refer to the new algorithm in memo:
507  * "TEB Radiometric Uncertainty and LUT Format",
508  * by Kwo-Fu (Vincent) Chiang etc., March, 2011
509  *********************************************************
510  */
511 
512  dL_ev = 0.0; /* use this variable to accumulate (dL_ev/L_ev)^2 */
513 
514  /***************************************************************
515  * obsolete due to TEB UI algorithm update, 3/22/2011, Xu Geng
516  */
517 
518  /*
519  * Add in terms from Eq. (4).
520  */
521 
522  /*
523  frame_number = (float32) (F+1);
524  for ( i = 0; i < NUM_UI_PARAMETERS; i++ )
525  {
526  si0 = emiss_tables->Ucoeff[D_emiss][i][0];
527  si1 = emiss_tables->Ucoeff[D_emiss][i][1];
528  EVAL_4TH_ORDER_POLYNOMIAL(ri0, si0, frame_number);
529  EVAL_4TH_ORDER_POLYNOMIAL(ri1, si1, frame_number);
530  dL_i_over_L_ev = (ri0 + ri1 * L_ev) / L_ev;
531  dL_ev += (dL_i_over_L_ev * dL_i_over_L_ev);
532  }
533  */
534 
535  /*
536  * Compute residual uncertainty to calibration fit (Eq. 9) and store
537  * in variable "Calibr_resid".
538  */
539  /*
540  calibr_resid_coeffs = emiss_tables->Ucoeff_Calibr_resid[D_emiss];
541  EVAL_4TH_ORDER_POLYNOMIAL(Calibr_resid, calibr_resid_coeffs, L_ev);
542  Calibr_resid /= L_ev;
543  */
544 
545  /*
546  * Add in remaining terms to (dL_ev/L_ev)^2
547  */
548  /*
549  dtemp = PP_emiss->NEdL[D_emiss][S]/L_ev;
550  dL_ev += (dtemp * dtemp) + Sigma_TEB_PV_resid_elec_sq +
551  (0.25 * dn_PCX_corr * dn_PCX_corr + Sigma_TEB_ADC_sq) /
552  (dn_ev * dn_ev) + Calibr_resid * Calibr_resid;
553  if (B_emiss == BAND21)
554  {
555  dtemp = emiss_tables->Band_21_Uncert_Lsat * L_ev;
556  dL_ev += (dtemp * dtemp);
557  }
558  *******************************************************************/
559 
560  /*
561  * Uncertainty due to a0
562  */
563  dtemp = PP_emiss->sigma_a0[D_emiss][S]*(1. - dn_ev/PP_emiss->dn_bb[D_emiss][S])
564  /(L1B_Gran->Emiss_Cal_Coeff.RVS_1km_Emiss_EV[D_emiss][F][MS]*L_ev);
565  dL_ev += (dtemp * dtemp);
566 
567  /*
568  * Uncertainty due to a2
569  */
570  dtemp = PP_emiss->sigma_a2[D_emiss][S]*(dn_ev-PP_emiss->dn_bb[D_emiss][S])*dn_ev
571  /(L1B_Gran->Emiss_Cal_Coeff.RVS_1km_Emiss_EV[D_emiss][F][MS]*L_ev);
572  dL_ev += (dtemp * dtemp);
573 
574  /*
575  * Uncertainty due to RVS_SV
576  */
577  dtemp = L1B_Gran->Emiss_Cal_Coeff.sigma_RVS_Emiss_EV[D_emiss][SV_frame_no][MS]*
578  (dn_ev/PP_emiss->dn_bb[D_emiss][S]-1.)*PP_emiss->Planck_mir[D_emiss][S]
579  /(L1B_Gran->Emiss_Cal_Coeff.RVS_1km_Emiss_EV[D_emiss][F][MS]*L_ev);
580  dL_ev += (dtemp * dtemp);
581 
582  /*
583  * Uncertainty due to RVS_EV
584  */
585  dtemp = L1B_Gran->Emiss_Cal_Coeff.sigma_RVS_Emiss_EV[D_emiss][F][MS]*
586  (PP_emiss->Planck_mir[D_emiss][S]/L_ev - 1.)
587  /L1B_Gran->Emiss_Cal_Coeff.RVS_1km_Emiss_EV[D_emiss][F][MS];
588  dL_ev += (dtemp * dtemp);
589 
590 
591  /*
592  * Uncertainty due to epsilon_bb
593  */
594  dtemp = emiss_tables->sigma_epsilon_BB[B_emiss]*(PP_emiss->L_bb[D_emiss][S] -
595  emiss_tables->epsilon_cav[D_emiss]*PP_emiss->L_cav[D_emiss][S])*dn_ev
596  /(L1B_Gran->Emiss_Cal_Coeff.RVS_1km_Emiss_EV[D_emiss][F][MS]*L_ev*
597  PP_emiss->dn_bb[D_emiss][S]);
598  dL_ev += (dtemp * dtemp);
599  /*
600  * Uncertainty due to epsilon_cav
601  */
602  dtemp = emiss_tables->sigma_epsilon_CAV[B_emiss]*(1.-emiss_tables->epsilon_bb[D_emiss])
603  *PP_emiss->L_cav[D_emiss][S]*dn_ev
604  /(L1B_Gran->Emiss_Cal_Coeff.RVS_1km_Emiss_EV[D_emiss][F][MS]*L_ev*
605  PP_emiss->dn_bb[D_emiss][S]);
606  dL_ev += (dtemp * dtemp);
607 
608  /*
609  * Uncertainty due to lambda
610  */
611  dtemp = (emiss_tables->sigma_L_lambda[B_emiss][0]+emiss_tables->sigma_L_lambda[B_emiss][1]*L_ev)
612  /(L1B_Gran->Emiss_Cal_Coeff.RVS_1km_Emiss_EV[D_emiss][F][MS]*L_ev);
613  dL_ev += (dtemp * dtemp);
614 
615  /*
616  * Uncertainty due to T_bb
617  */
618  dtemp = emiss_tables->sigma_L_Tbb[B_emiss]*emiss_tables->epsilon_bb[D_emiss]*dn_ev
619  /(L1B_Gran->Emiss_Cal_Coeff.RVS_1km_Emiss_EV[D_emiss][F][MS]*L_ev*
620  PP_emiss->dn_bb[D_emiss][S]);
621  dL_ev += (dtemp * dtemp);
622 
623  /*
624  * Uncertainty due to T_sm
625  */
626  dtemp = emiss_tables->sigma_L_Tsm[B_emiss]*
627  (L1B_Gran->Emiss_Cal_Coeff.RVS_1km_Emiss_EV[D_emiss][F][MS]-
628  L1B_Gran->Emiss_Cal_Coeff.RVS_1km_Emiss_SV[D_emiss][MS]+
629  (L1B_Gran->Emiss_Cal_Coeff.RVS_1km_Emiss_SV[D_emiss][MS] - 1)
630  *dn_ev/PP_emiss->dn_bb[D_emiss][S])
631  /(L1B_Gran->Emiss_Cal_Coeff.RVS_1km_Emiss_EV[D_emiss][F][MS]*L_ev);
632  dL_ev += (dtemp * dtemp);
633 
634  /*
635  * Uncertainty due to T_cav
636  */
637  dtemp = emiss_tables->sigma_L_Tcav[B_emiss]*(1.-emiss_tables->epsilon_bb[D_emiss])
638  *emiss_tables->epsilon_cav[D_emiss]*dn_ev/PP_emiss->dn_bb[D_emiss][S]
639  /(L1B_Gran->Emiss_Cal_Coeff.RVS_1km_Emiss_EV[D_emiss][F][MS]*L_ev);
640  dL_ev += (dtemp * dtemp);
641 
642  /*
643  * Uncertainty due to dn_EV
644  */
645  dtemp = PP_emiss->dn_bb_sdev[D_emiss][S]*(PP_emiss->b1[D_emiss][S]+
646  2.*PP_emiss->a2[D_emiss][S]*dn_ev)
647  /(L1B_Gran->Emiss_Cal_Coeff.RVS_1km_Emiss_EV[D_emiss][F][MS]*L_ev);
648  dL_ev += (dtemp * dtemp);
649 
650  /*
651  * Uncertainty due to band_21_b1
652  */
653  if (B_emiss == BAND21)
654  {
655  dtemp = emiss_tables->sigma_b1_B21[D][MS];
656  dL_ev += (dtemp * dtemp);
657  }
658 
659  /*
660  * Uncertainty due to PC cross talk correction
661  */
662  if ( PCX_correction_switch == ON && B >= BAND32 && B <= BAND36 )
663  {
664  dtemp = emiss_tables->pcx_ui_factor[B_xt]*(dn_PCX_corr / dn_ev);
665  dL_ev += (dtemp * dtemp);
666  }
667 
668  /*
669  * Compute fractional uncertainty (take square root of (dL_ev/L_ev)^2)
670  */
671 
672  dL_ev = sqrt((double) dL_ev);
673 
674  /*
675  * Calculate the uncertainty index using the formula from the
676  * L1B Product User's Guide:
677  *
678  * UI = n * log(percent_uncertainty / m)
679  *
680  * The value of n and m are band dependent and come from lookup tables.
681  * The factor of 100 in the formula below converts the fractional
682  * uncertainty to % uncertainty.
683  */
684 
685  if (dL_ev > 0)
686  uncert = emiss_tables->TEB_UI_scaling_factor[B_emiss] *
687  log((double) (100.0*dL_ev/emiss_tables->TEB_specified_uncertainty[B_emiss]));
688  else
689  uncert = BAD_DATA_UI;
690 
691  /*
692  * Ensure the uncertainty is in the range of 0-15.
693  */
694 
695  if (uncert > BAD_DATA_UI)
696  L1B_Scan->UI.EV_1km_Emissive_UI[B_emiss][D][F] = BAD_DATA_UI;
697  else if(uncert < 0)
698  L1B_Scan->UI.EV_1km_Emissive_UI[B_emiss][D][F] = 0;
699  else
700  L1B_Scan->UI.EV_1km_Emissive_UI[B_emiss][D][F] = (uint8) uncert;
701  }
702 
703  }/*End of loop over frames*/
704 
705  }/*End of loop over detectors within band*/
706 
707  B_emiss++;
708  }/*End of loop over bands*/
709 
710  if (flag == 1)
711  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00000008;
712 
713  return(MODIS_S_OK);
714 }
715 
716 
float32 epsilon_cav[NUM_EMISSIVE_DETECTORS]
Definition: L1B_Tables.h:767
#define MODIS_S_OK
float32 b1[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:141
integer, parameter int16
Definition: cubeio.f90:3
instead the metadata field ProcessingEnvinronment is filled in from the output of a call to the POSIX compliant function uname from within the L1B code A small bug in L1B_Tables an incorrect comparison of RVS coefficients for TEBs to RVS coefficients for RSBs was being made This was replaced with a comparison between TEB coefficients This error never resulted in an incorrect RVS correction but did lead to recalculating the coefficients for each detector in a thermal band even if the coefficients were the same for all detectors To reduce to overall size of the reflective LUT HDF fill values were eliminated from all LUTs previously dimensioned where and where NUM_TIMES is the number of time dependent table pieces In Preprocess a small error where the trailing dropped scan counter was incremented when the leading dropped scan counter should have been was fixed This counter is internal only and is not yet used for any chiefly to casting of were added to make it LINUX compatible Output of code run on LINUX machines displays differences of at most scaled sector incalculable values of the Emissive calibration factor and incalculable values of SV or BB averages was moved outside the loop over frames in Emissive_Cal c since none of these quantities are frame dependent Initialization of b1 and XMS values in Preprocess c routine Process_OBCENG_Emiss was moved inside the detector loops The code was altered so that if up to five scans are dropped between the leading middle or middle trailing the leading or trailing granule will still be used in emissive calibration to form a cross granule average QA bits and are set for a gap between the leading middle and middle trailing granules respectively This may in rare instances lead to a change in emissive calibration coefficients for scans at the beginning or end of a granule A small bug in the Band correction algorithm was corrected an uncertainty value was being checked against an upper bound whereas the proper quantity to be checked was the corresponding which is the product of the Band radiance times the ratio of the Band to Band scaling factors times the LUT correction value for that detector In addition a new LUT which allows for a frame offset with regard to the Band radiance was added A LUT which switches the correction off or on was also added Changes which do not affect scientific output of the the pixel is flagged with the newly created flag TEB_B1_NOT_CALCULATED
Definition: HISTORY.txt:623
QA_Common_t QA_common
Definition: Granule.h:1097
#define SATURATED_DETECTOR_SI
Definition: Granule.h:519
#define BAD_DATA_UI
Definition: Granule.h:533
L1B_ScaleOffset_t SO
Definition: Granule.h:865
uint32 valid_pixels[NUM_BANDS]
Definition: Granule.h:878
@ BAND36
Definition: Granule.h:644
int32 num_sector_rotation_EV_data[NUM_DETECTORS]
Definition: Granule.h:1082
float32 sigma_b1_B21[DETECTORS_PER_1KM_BAND][NUM_MIRROR_SIDES]
Definition: L1B_Tables.h:854
int32 num_nadir_door_closed_EV_data[NUM_DETECTORS]
Definition: Granule.h:1088
int8 PCX_correction_switch
Definition: L1B_Tables.h:805
#define SECTOR_ROTATION_SI
Definition: Granule.h:525
uint16 EV_1km_Emissive[NUM_1000M_EMISS_BANDS][DETECTORS_PER_1KM_BAND][EV_1km_FRAMES]
Definition: Granule.h:905
int32 num_saturated_EV_data[NUM_DETECTORS]
Definition: Granule.h:1083
@ BAND32
Definition: Granule.h:644
#define UNABLE_CALIBRATE_SI
Definition: Granule.h:528
#define L1A_DN_MISSING_SI
Definition: Granule.h:518
Emiss_Cal_Coeff_t Emiss_Cal_Coeff
Definition: Granule.h:864
int32 num_exceed_max_for_scaling[NUM_DETECTORS]
Definition: Granule.h:1087
#define MODIS_BAND26_INDEX_AT_RES
Definition: Granule.h:447
boolean Sector_Rotation[MAX_NUM_SCANS]
Definition: Granule.h:1075
#define MISSING_L1A_FLAG
Definition: Granule.h:515
@ BAND21
Definition: Granule.h:643
#define ON
Definition: l1.h:43
PGSt_SMF_status Emissive_Cal(int16 S, int16 MS, L1B_granule_t *L1B_Gran, L1A_Scan_t *L1A_Scan, L1B_Scan_t *L1B_Scan, Preprocess_Emiss_t *PP_emiss, emiss_tables_t *emiss_tables, QA_tables_t *QA_tables, QA_Data_t *QA, L1B_Scan_Metadata_t *L1B_Scan_Meta)
Definition: Emissive_Cal.c:19
#define DETECTORS_PER_1KM_BAND
Definition: Granule.h:438
float32 RVS_1km_Emiss_SV[NUM_EMISSIVE_DETECTORS][NUM_MIRROR_SIDES]
Definition: Granule.h:848
const double F
float32 sigma_a0[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:140
int32 num_negative_b1[NUM_DETECTORS]
Definition: Granule.h:1089
boolean Electronic_Anomaly[MAX_NUM_SCANS]
Definition: Granule.h:1076
uint32 saturated_pixels[NUM_BANDS]
Definition: Granule.h:879
const int NUM_BANDS
float32 sigma_L_Tcav[NUM_EMISSIVE_BANDS]
Definition: L1B_Tables.h:853
float32 sigma_epsilon_BB[NUM_EMISSIVE_BANDS]
Definition: L1B_Tables.h:847
float32 sigma_a2[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:143
#define SATURATED_DN
Definition: Granule.h:511
L1B_Scan_UI_t UI
Definition: Granule.h:987
float32 dn_bb[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:145
float32 L_Min[NUM_EMISSIVE_BANDS]
Definition: L1B_Tables.h:823
int16 L1A_BANDS_AT_RES[NUM_L1A_RESOLUTIONS]
Definition: Granule.c:63
float32 a2[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:142
#define TEB_OR_RSB_GT_MAX_SI
Definition: Granule.h:523
float32 rad_offset_Emiss[NUM_EMISSIVE_BANDS]
Definition: Granule.h:809
#define FLOAT_TO_PIXEL(L, L_max, L_min, scale, offset, Scale_Integer)
Definition: Emissive_Cal.c:8
#define EV_1km_FRAMES
Definition: Granule.h:469
float32 TEB_specified_uncertainty[NUM_EMISSIVE_BANDS]
Definition: L1B_Tables.h:824
uint32 Bit_QA_Flags[MAX_NUM_SCANS]
Definition: L1B_Setup.h:73
#define DEAD_DETECTOR_SI
Definition: Granule.h:521
#define INDEX_1000M_EMISS
Definition: Granule.h:576
float32 sigma_RVS_Emiss_EV[NUM_EMISSIVE_DETECTORS][EV_1km_FRAMES][NUM_MIRROR_SIDES]
Definition: Granule.h:853
void SMF_ERROR(PGSt_SMF_code code, char *messagestring)
Definition: Granule.c:1345
float32 pcx_ui_factor[NUM_PC_XT_BANDS]
Definition: L1B_Tables.h:855
float32 dn_X[DETECTORS_PER_1KM_BAND][EV_1km_FRAMES]
Definition: Granule.h:1027
int32 num_missing_data_in_scans[NUM_DETECTORS]
Definition: Granule.h:1079
#define ZERO_POINT_DN_SI
Definition: Granule.h:520
float32 DN_sv[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:144
float32 epsilon_bb[NUM_EMISSIVE_DETECTORS]
Definition: L1B_Tables.h:766
#define MODIS_F_NOK
int8 dead_detector[NUM_DETECTORS]
Definition: L1B_Tables.h:889
float32 dn_bb_sdev[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:146
#define True
Definition: Granule.h:537
#define TOLERANCE
Definition: Granule.h:535
float32 L_cav[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:148
int32 num_dead_detector_EV_data[NUM_DETECTORS]
Definition: Granule.h:1080
uint32 missing_pixels[NUM_BANDS]
Definition: Granule.h:880
int16 RVS_BB_SV_Frame_No[2]
Definition: L1B_Tables.h:819
float32 RVS_1km_Emiss_EV[NUM_EMISSIVE_DETECTORS][EV_1km_FRAMES][NUM_MIRROR_SIDES]
Definition: Granule.h:846
uint8 EV_1km_Emissive_UI[NUM_1000M_EMISS_BANDS][DETECTORS_PER_1KM_BAND][EV_1km_FRAMES]
Definition: Granule.h:924
float32 sigma_L_Tsm[NUM_EMISSIVE_BANDS]
Definition: L1B_Tables.h:852
float32 rad_scale_Emiss[NUM_EMISSIVE_BANDS]
Definition: Granule.h:808
int16 bad_data_flag[NUM_BANDS]
Definition: Granule.h:885
int32 num_no_bg_DN_EV_data[NUM_DETECTORS]
Definition: Granule.h:1084
#define NUM_REFLECTIVE_DETECTORS
Definition: Granule.h:427
float32 TEB_UI_scaling_factor[NUM_EMISSIVE_BANDS]
Definition: L1B_Tables.h:825
float32 sigma_L_lambda[NUM_EMISSIVE_BANDS][NUM_1ST_ORDER_COEFFS]
Definition: L1B_Tables.h:850
float32 PC_XT[NUM_PC_XT_BANDS][DETECTORS_PER_1KM_BAND][NUM_PC_XT_PARAMETERS]
Definition: L1B_Tables.h:772
int16 EV_1km_night[DETECTORS_PER_1KM_BAND][NUM_1000M_NIGHT_BANDS][EV_1km_FRAMES]
Definition: Granule.h:791
for(i=0;i< NROOTS;i++) s[i]
Definition: decode_rs.h:85
int16 DETECT_PER_BAND_AT_RES[NUM_L1A_RESOLUTIONS]
Definition: Granule.c:68
#define NAD_CLOSED_UPPER_SI
Definition: Granule.h:531
float32 sigma_L_Tbb[NUM_EMISSIVE_BANDS]
Definition: L1B_Tables.h:851
float32 Planck_mir[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:138
@ BAND31
Definition: Granule.h:644
const int NUM_EMISSIVE_BANDS
uint32 dead_detector_pixels[NUM_BANDS]
Definition: Granule.h:882
float32 L_Max[NUM_EMISSIVE_BANDS]
Definition: L1B_Tables.h:822
int MS[]
Definition: Usds.c:106
L1B_Scan_SI_t SI
Definition: Granule.h:973
float32 L_bb[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:147
int16 band_X
Definition: Granule.h:1026
boolean NAD_Door_Open[MAX_NUM_SCANS]
Definition: Granule.h:1074
common_QA_tables_t common_QA_tables
Definition: L1B_Tables.h:943
float32 sigma_epsilon_CAV[NUM_EMISSIVE_BANDS]
Definition: L1B_Tables.h:848
uint32 negative_value_below_noise_pixels[NUM_BANDS]
Definition: Granule.h:884
#define False
Definition: Granule.h:538
float32 a0[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:139