OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
Preprocess.c
Go to the documentation of this file.
1 #include "Preprocess.h" /* contains externals, includes L1B_Tables.h */
2 #include "PreprocessP.h" /* contains local definitions and prototypes */
3 #include "HDF_Lib.h"
4 #include "PGS_PC.h"
5 #include "PGS_MET.h"
6 #include "PGS_Error_Codes.h"
7 #include "FNames.h"
8 #include <math.h>
10 
11 /***************************************************************************
12 Developer's note: (Jim Rogers)
13 
14 In the the various functions, there is a return statement after each
15 L1BErrorMsg function call. These are actually not necessary if the last
16 argument to L1BErrorMsg is "True". These returns make it easier to test
17 error out conditions (with SMF_ERROR used in UNIT_TEST_MODE_ONLY -- it does
18 not actually exit).
19 ****************************************************************************/
20 
21 int32 SUBSAMPLES_AT_RES[NUM_L1A_RESOLUTIONS] = {4, 2, 1, 1};
22 
23 int16 TARGET_1km_FRAMES[NUM_TARGETS] = { 50, 10, 50, 50, 1354 };
24 
25 /* Enclosed the rows in the initializer of the 2-D array with braces for
26  ANSI-C compliance (Razor Issue 173). */
28  {"SD_250m", "SD_500m", "SD_1km_day", "SD_1km_night"},
29  {"SRCA_250m", "SRCA_500m", "SRCA_1km_day", "SRCA_1km_night"},
30  {"BB_250m", "BB_500m", "BB_1km_day", "BB_1km_night"},
31  {"SV_250m", "SV_500m", "SV_1km_day", "SV_1km_night"},
32  {"EV_250m", "EV_500m", "EV_1km_day", "EV_1km_night"}
33 };
34 
35 /*--------------------------------------------------------------
36 The following
37 L1A_BAND_DIM_NAME, L1A_TRACK_DIM_NAME, & L1A_FRAME_DIM_NAME
38 are used only in Preprocess.c to write OBC SDS's, and
39 may not be the same as in L1A input file. --zh
40 --------------------------------------------------------------*/
42  "Band_250m", "Band_500m", "Band_1km_day", "Band_1km_night"
43 };
44 
46  "40*nscans", "20*nscans", "10*nscans", "10*nscans"
47 };
48 
50  {"4*SD_frames", "2*SD_frames", "SD_frames", "SD_frames"},
51  {"4*SRCA_frames", "2*SRCA_frames", "SRCA_frames", "SRCA_frames"},
52  {"4*BB_frames", "2*BB_frames", "BB_frames", "BB_frames"},
53  {"4*SV_frames", "2*SV_frames", "SV_frames", "SV_frames"}
54 };
55 
56  /* January 4, 2002 (Razor Issue #154)
57  * Terra- and Aqua- specific temperature coefficients have been moved
58  * to PreprocessP.h.
59  * Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
60  */
61 
62 extern int16 RFLAG;
67 
68 PGSt_SMF_status Calculate_Temp_QA(int32 num_scans,
69  Temperatures_t *temps,
71  QA_Data_t *QA)
72 /*
73 !C**************************************************************************
74 !Description: Calculate the ratio of temperature variation to the value
75  stored in look up table. The temperatures being calculated
76  are BB thermistor temperatures, averaged BB thermistor
77  temperature, lwir, mwir, nir, vis focal plane temperatures,
78  mirror side 1 temperature, mirror side 2 temperature, averaged
79  mirror side temperature, lwir adc temperature, mwir adc
80  temperature, instrument temperature, cavity temperature.
81 
82 !Input Parameters:
83  int32 num_scans number of data for each kind of
84  temperature values
85  Temperatures_t *temps temperature values
86  QA_tables_t *tables, contains the predetermined variation
87  of temperatures
88 
89 !Output Parameters:
90  QA_Data_t *QA contains the scaled integer, which is
91  ratio being mapped to 0 - 255.
92 
93 !Revision History:
94  $Log: Preprocess.c,v $
95  Revision 1.35 2015-03-17 10:48:12-04 xgeng
96  Fix the anomaly before and after the sector rotation due to the timing mismatch between the command performed and the status updated.
97 
98  Revision 1.34 2011-07-28 15:44:33-04 xgeng
99  Default b1 is derived using real-time LWIR FPA temperature.
100 
101  Revision 1.32 2011-04-07 14:39:08-04 xgeng
102  1. RSB &TEB uncertainty algorithm update; 2. The quadratic RSB RVS changed to 4th order.
103 
104  Revision 1.31 2010-11-15 11:40:04-05 xgeng
105  Added a new function called Get_Electronics_index_special() for PCLW check; and no calibration is performed if both sides of PCLW electronics are on.
106 
107  Revision 1.30 2009/11/27 19:18:15 xgeng
108  Fixed a bug in Revision 1.29
109 
110  Revision 1.29 2009/07/24 19:54:29 xgeng
111  fixed the sector rotation abnormal
112 
113  Revision 1.27 2008/01/24 15:50:36 ltan
114  Changed to relax the RVS correction limit range from [0.8, 1.2] to [0.4, 2.4].
115 
116  Revision 1.24 2005/01/18 21:57:39 ltan
117  Added new file attributes prefixed with HDFEOS_FractionalOffset
118 
119 
120  Revision 02.12, September 30, 1999
121  Added assignment of num_thermistor_outliers.
122  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
123 
124  Revision 02.11 May 12, 1999
125  Eliminated duplication of code by adding function. Function also checks
126  for a bad value of temperature (<= 0 is bad).
127  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
128 
129  Revision 02.10 Mar. 1998
130  Initial development
131  Shi-Yue Qiu (syqiu@ltpmail.gsfc.nasa.gov)
132 
133 !Team-unique Header:
134  This software is developed by the MODIS Science Data Support
135  Team for the National Aeronautics and Space Administration,
136  Goddard Space Flight Center, under contract NAS5-32373.
137 
138 !References and Credits:
139  HDF portions developed at the National Center for Supercomputing
140  Applications at the University of Illinois at Urbana-Champaign.
141 
142 !Design Notes:
143 
144 !END********************************************************************
145 */
146 {
147  PGSt_SMF_status returnStatus = MODIS_S_OK;
148  int32 i = 0;
149  int32 S = 0;
150  int32 n = 0;
151  float32 avg = 0;
152  float32 var = 0;
153  float32 ratio = 0;
154  float32 tbbavg[MAX_NUM_SCANS];
155 
156 #define CALC_ONE_TEMP_QA(t,tablevar,output) \
157  returnStatus = Get_Temp_Avg_And_Variance(num_scans, t, &avg, &var); \
158  if (returnStatus != MODIS_S_OK) \
159  SMF_ERROR(MODIS_F_NOK, \
160  "Get_Temp_Avg_And_Variance failed, Calculate_Temp_QA, Preprocess.c"); \
161  ratio = var / tablevar; \
162  CONVERT_TO_UINT8(ratio, output);
163 
164  /* Initialize the array holding the granule averages */
165 
166  for (i = 0; i < MAX_NUM_GRAN_AVERAGES; i++)
167  QA->QA_common.granule_averages[i] = 0;
168 
169  /* First compute average BB temperature on each scan with
170  * bad value rejection but not outlier rejection (the value in
171  * temps->bb_avg has outlier rejection applied).
172  * Also, assign number of outliers on each scan to QA_emiss.
173  */
174 
175  for (S = 0; S < num_scans; S++)
176  {
177  avg = 0;
178  n = 0;
179  for (i = 0; i < NUM_BB_THERMISTORS; i++)
180  {
181  if (temps->bb[i][S] > 0)
182  {
183  avg += temps->bb[i][S];
184  n++;
185  }
186  }
187  if (n > 0)
188  tbbavg[S] = avg / n;
189  else
190  tbbavg[S] = -1;
192  temps->num_thermistor_outliers[S];
193  }
194 
195  /* Now calculate noise, for all */
196 
197  for (i = 0; i < NUM_BB_THERMISTORS; i++)
198  {
199  CALC_ONE_TEMP_QA(temps->bb[i],
200  tables->emiss_QA_tables.var_T_bb[i],
201  QA->QA_emiss.noise_T_bb[i]);
202  QA->QA_common.granule_averages[i] = avg;
203  }
204 
205  CALC_ONE_TEMP_QA(tbbavg,
206  tables->emiss_QA_tables.var_T_bb_avg,
208 
209  CALC_ONE_TEMP_QA(temps->fp[3],
210  tables->emiss_QA_tables.var_T_lwir,
211  QA->QA_emiss.noise_T_lwir);
213 
214  CALC_ONE_TEMP_QA(temps->fp[2],
215  tables->emiss_QA_tables.var_T_mwir,
216  QA->QA_emiss.noise_T_mwir);
218 
219  CALC_ONE_TEMP_QA(temps->fp[1],
220  tables->refl_QA_tables.var_NIR_FPA,
221  QA->QA_refl.noise_T_nir);
223 
224  CALC_ONE_TEMP_QA(temps->fp[0],
225  tables->refl_QA_tables.var_visual_FPA,
226  QA->QA_refl.noise_T_vis);
228 
229  CALC_ONE_TEMP_QA(temps->mir1,
230  tables->emiss_QA_tables.var_T_mir1,
231  QA->QA_emiss.noise_T_mir1);
233 
234  CALC_ONE_TEMP_QA(temps->mir2,
235  tables->emiss_QA_tables.var_T_mir2,
236  QA->QA_emiss.noise_T_mir2);
238 
239  CALC_ONE_TEMP_QA(temps->mir_avg,
240  tables->emiss_QA_tables.var_T_mir_avg,
242 
243  CALC_ONE_TEMP_QA(temps->ins,
244  tables->emiss_QA_tables.var_T_ins,
245  QA->QA_emiss.noise_T_ins);
246 
247  CALC_ONE_TEMP_QA(temps->cav,
248  tables->emiss_QA_tables.var_T_cav,
249  QA->QA_emiss.noise_T_cav);
250 
251  if (Granule_Average_Temperature(num_scans, temps->scn_mtr,
253  {
255  "avg cavity temperature failed in Calculate_Temp_QA");
256  }
257 
259  && i <= GRAN_AVG_TP_MF_CVR_OP_SR; n++, i++)
260  {
261  if (Granule_Average_Temperature(num_scans, temps->cav_temp[n],
263  {
265  "avg cavity temperature failed in Calculate_Temp_QA");
266  }
267  }
269  && i <= GRAN_AVG_TP_AO_LWIR_LENS; n++, i++)
270  {
271  if (Granule_Average_Temperature(num_scans, temps->ins_temp[n],
273  {
275  "avg inst. temperature failed in Calculate_Temp_QA");
276  }
277  }
278  for (n = 0, i = GRAN_AVG_TA_RC_CS; n < NUM_T_RC_VALUES
279  && i <= GRAN_AVG_TA_RC_OS_OG; n++, i++)
280  {
281  if (Granule_Average_Temperature(num_scans, temps->rc_temp[n],
283  {
285  "avg RC temperature failed in Calculate_Temp_QA");
286  }
287  }
288  avg = 0;
289  n = 0;
290  for (S = 0; S < num_scans; S++) {
291  if (temps->vr_lwir[S] != VOLTAGE_BAD_VALUE) {
292  n++;
293  avg += temps->vr_lwir[S];
294  }
295  }
296  if (n > 0)
298  else
301 
302  return returnStatus;
303 }
304 
305 PGSt_SMF_status Calculate_Planck (float32 *RSR,
306  float32 *wl,
307  int16 size,
308  float32 T,
309  float32 *planck)
310 /*
311 !C************************************************************************
312 !Description: Calculate Planck function integration over RSR
313 
314 !Input Parameters:
315  float32 *RSR * RSR values for a particular channel *
316  int16 size * number of valid points for that RSR *
317  float32 T * temperature *
318  float32 *wl * wavelength with same array size*
319 
320 !Output Parameters:
321  float32 planck * the planck function integration *
322 
323 !Revision History:
324  Revision 02.20 March 25, 2002 Razor Issue #178
325  Strip out ADC Correction
326  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
327 
328  Revision 02.10 Mar. 1998
329  Initial development
330  Shi-Yue Qiu (syqiu@ltpmail.gsfc.nasa.gov)
331 
332 !Team-unique Header:
333  This software is developed by the MODIS Characterization Support
334  Team (MCST)for the National Aeronautics and Space Administration,
335  Goddard Space Flight Center, under contract NAS5-32373.
336 
337 !References and Credits:
338  HDF portions developed at the National Center for Supercomputing
339  Applications at the University of Illinois at Urbana-Champaign.
340 
341 !Design Notes:
342 
343 !END********************************************************************
344 */
345 {
346  PGSt_SMF_status returnStatus = MODIS_S_OK;
347  int16 i = 0;
348  float32 sum = 0;
349  float32 xL = 0;
350  float32 lambda = 0;
351  float32 dw = 0;
352 
353  *planck = 0; /* initialize for error state on return */
354 
355  if (size <= 0 || T < TOLERANCE) /* check for bad values */
356  return (returnStatus);
357 
358  if (size == 1) /* check for single value */
359  {
360  *planck = L(wl[0], T);
361  return (returnStatus);
362  }
363 
364  lambda = wl[0];
365  dw = 0.5 * ( wl[1] - wl[0] );
366  xL = RSR[0] * L(lambda, T) * dw;
367  sum = RSR[0] * dw;
368 
369  for (i = 1; i< size - 1; i++)
370  {
371  lambda = wl[i];
372  dw = 0.5 * ( wl[i+1] - wl[i-1] );
373  xL += RSR[i] * L(lambda, T) * dw;
374  sum += RSR[i] * dw;
375  }
376 
377  lambda = wl[size-1];
378  dw = 0.5 * ( wl[size-1] - wl[size-2] );
379  xL += RSR[size-1] * L(lambda, T) * dw;
380  sum += RSR[size-1] * dw;
381 
382  if (sum > 0)
383  *planck = xL / sum;
384 
385  return (returnStatus);
386 }
387 
388 PGSt_SMF_status Get_Emiss_Coeff_Per_Scan
389  (int8 moon_in_SV_KOB,
390  int16 *BB,
391  int16 *SV,
392  int16 B,
393  int16 D,
394  int16 D_emiss,
395  int16 MS,
396  Emiss_Cal_Coeff_t *RVS_Coeff,
398  float32 T_bb,
399  float32 T_mir,
400  float32 T_cav,
401  float32 T_ins,
402  float32 T_fp_lwir,
403  float32 *Xdn_bb_31,
404  float32 *Xb1,
405  float32 *xdLbb,
406  float32 *xdnbb,
407  float32 *xLbb,
408  float32 *xLcav,
409  float32 *xdnsv,
410  float32 *xdnsv_var,
411  uint32 *sv_omask,
412  float32 *SNR,
413  int32 satellite_ID)
414 /*
415 !C****************************************************************************
416 !Description:
417  For a given emissive band and detector in the band, this function computes
418  Emissive Calibration Coefficients for one scan. The quantities calculated
419  include an averaged space-view (SV) digital number (DN_sv), the band-averaged
420  radiance difference between the black-body and the space view (dL_bb),
421  the linear response coefficient (b1), and the signal to noise ratio (SNR).
422 
423 !Input Parameters:
424 
425  int8 moon_in_SV_KOB Flag denoting if the moon is inside
426  the SV KOB
427  int16 * BB Black-body DNs (one set of frames)
428  int16 * SV Space-view DNs (one set of frames)
429  int16 B Band index within the resolution.
430  int16 D Detector index within one emissive band.
431  int16 D_emiss Detector index within the set of emissive
432  detectors.
433  int16 MS Mirror side index
434  Emiss_Cal_Coeff_t *RVS_Coeff Emissive RVS Correction terms
435  emiss_tables_t * tables emissive lookup tables, contains ADC
436  coefficients and the number frames for the BB
437  and SV averages, and the ADC and PCX correction
438  switches
439  float32 T_bb black body average temperature.
440  float32 T_mir average mirror temperature
441  float32 T_cav average cavity temperature.
442  float32 T_ins instrument temperature.
443  float32 *Xdn_bb_31 the address of the blackbody dn value for the
444  detector D in band 31 and for current scan. It
445  is an input for bands 32-36 and an output for
446  band 31.
447 
448  float32 * SNR Address of the SNR. If entry value is > 0,
449  then calculate SNR. Otherwise, do not calculate.
450 
451  int32 satellite_ID 0 = TERRA, 1 = AQUA, -1 = INVALID_SATELLITE_ID
452 
453 
454 !Output Parameters:
455 
456  float32 * Xb1 Address of one element of b1 of the middle
457  granule.
458  float32 * xdLbb Address of one element of delta radiance of
459  black body for middle granule.
460  float32 * xdnbb Address of one element of average blackbody
461  dn for middle granule.
462  float32 * xLbb Address of one element of radiance of black
463  body for middle granule.
464  float32 * xLcav Address of one element of radiance of cavity
465  for middle granule.
466  float32 * xdnsv Address of one element of average space-view
467  DN for middle granule.
468  float32 * xdnsv_var Address of one element of average space-view
469  variance for middle granule.
470  uint32 * sv_omask array of two elements to return outlier mask.
471  float32 * SNR Address of the SNR. may or may not be calculated
472  depending on input value.
473 
474 !Revision History:
475  Revision 02.31 March 25, 2002 Razor Issue #178
476  Strip out ADC Correction
477  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
478 
479  Revision 02.30, January 29, 2002 Razor Issue #175
480  Added satellite_ID to inputs. Added a check on average BB temperature for Aqua
481  bands (currently 33, 35, and 36): If average BB temperature is above a
482  band-specific cutoff value, use a value of b1 specified in the
483  BB_T_sat_default_b1_aqua LUT if the BB_T_sat_switch_aqua switch is on.
484  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
485 
486 
487  Revision 02.21 March 10, 2002 Razor Issue #174
488  Added passed parameter Emiss_Cal_Coeff_t
489  and changed use of emissive lookup tables to these arrays for
490  RVS correction
491  Alice Isaacman SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
492 
493  Revision 02.20, Jan 29, 2001
494  Improved efficiency of calculation of a0 and a2.
495  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
496 
497  Revision 02.19 Sep 11, 2000
498  Made changes for Razor issue 133 (TEB algorithm for calculating <DN-SV> when
499  moon is in the SVP). Added input argument "moon_in_SV_KOB". Added logic
500  for calculating <DN-SV> if the moon is inside the SV KOB.
501  Corrected bug in calculating SNR.
502  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
503 
504  Revision 02.18 August 1999
505  Removed xdnbb, one element of average black body DN for middle granule, from
506  argument list.
507  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
508 
509  Revision 02.17 August 1999
510  See SDF, "L1B Code Change to meet ADC correction algorithm change"
511  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
512 
513  Revision 02.16 May, 1999
514  See SDF, "Stage 3: Changes to Emissive Algorithm and Code" notes.
515  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
516 
517  Revision 02.15 April 12, 1999
518  Removed cubic term a3
519  Steven Gu(zgu@mcst.gsfc.nasa.gov)
520 
521  Revision 02.11 Feb 9, 1999
522  Added use of variables ADC_correction_switch and PCX_correction_switch
523  set to macro values to remove compiler warnings. Macros in upper case.
524  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
525 
526  Revision 02.10 Mar. 1998
527  Shi-Yue Qiu (syqiu@ltpmail.gsfc.nasa.gov)
528 
529  Revision 01.00 Feb. 1997
530  Initial development
531  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
532 
533 !Team-unique Header:
534  This software is developed by the MODIS Characterization Support
535  Team (MCST)for the National Aeronautics and Space Administration,
536  Goddard Space Flight Center, under contract NAS5-32373.
537 
538 !References and Credits:
539  HDF portions developed at the National Center for Supercomputing
540  Applications at the University of Illinois at Urbana-Champaign.
541 
542 !Design Notes:
543 
544  WARNING: SNR is used as both an input and an output. As an input, it is a
545  flag to determine whether or not to calculate the SNR. As an output,
546  it holds the value of the SNR, if calculated, or -1 if not.
547  The only purpose of having the flag is to save a little CPU time when
548  processing scans from the leading and trailing granules.
549 
550 !END**************************************************************************
551 */
552 
553 {
554  PGSt_SMF_status returnStatus = MODIS_S_OK;
555  int16 F = 0;
556  int16 B_xt = 0;
557  int16 B_emiss = 0;
558  float32 DN_bb = 0;
559  float32 DN_sv = 0;
560  float32 dL_bb = 0;
561  float32 dn_bb = 0;
562  float32 dn_bb_31;
563  float32 bb_corr = 0;
564  float32 sv_corr = 0;
565  float32 a0 = 0;
566  float32 a2 = 0;
567  float32 L_sm = 0;
568  float32 L_bb = 0;
569  float32 L_cav = 0;
570  float32 sdev = 0;
571  int8 PCX_correction_switch;
572  int8 BB_T_sat_switch_aqua;
573  int16 rejects[MAX_1KM_OBC_FRAME_DIM];
574  float32 delta_T_bb;
575  int16 i;
576  float32 BB_temp_threshold = 1000.0;
577  boolean calculate_SNR;
578 
579  /* Determine the emissive band index. */
580  if (B <= BAND26)
581  B_emiss = B;
582  else
583  B_emiss = B - 1;
584 
585  /*
586  * Determine if we will calculate SNR later in this function
587  * (do this here so that we can initialize SNR with a return value)
588  */
589 
590  if (*SNR > 0)
591  calculate_SNR = True;
592  else
593  calculate_SNR = False;
594 
595  /*
596  * Initialize return values in case of error exits
597  * (Xb1 is already initialized)
598  */
599 
600  *xdLbb = -1;
601  *xdnbb = -1;
602  *xLbb = -1;
603  *xLcav = -1;
604  *xdnsv = -1;
605  *xdnsv_var = -1;
606  *SNR = -1;
607 
608  PCX_correction_switch = tables->PCX_correction_switch;
609  BB_T_sat_switch_aqua = tables->BB_T_sat_switch_aqua;
610 
611  /*
612  * initialize "rejects" array to zero for all elements.
613  */
614 
615  for (F = 0; F < MAX_1KM_OBC_FRAME_DIM; F++)
616  rejects[F] = 0;
617 
618  /*
619  * Compute space-view (SV) average DN, standard deviation and rejects.
620  * If the moon is in the SV port, use the "lowest N" algorithm, with all
621  * 50 SV frames. If the moon is not in the SV KOB, use the normal
622  * algorithm.
623  */
624 
625  if (moon_in_SV_KOB == MOON_INSIDE_SV_KOB)
626  {
627  returnStatus =
629  tables->SV_DN_moon_include_frames,
630  0,
632  1,
633  SV,
634  SATURATED_DN - 1,
635  0,
636  &DN_sv,
637  &sdev,
638  &rejects[0]);
639 
640  if (returnStatus != MODIS_S_OK)
641  SMF_ERROR(returnStatus,
642  "Get_DN_Avg_SDev_Rejects_LowN() in "
643  "Get_Emiss_Coeff_Per_Scan(), Preprocess.c");
644 
645  }
646  else
647  {
648  returnStatus =
649  Get_DN_Avg_SDev_Rejects(tables->SV_DN_first_frame_to_use,
650  tables->SV_DN_number_of_frames_to_use,
651  1,
652  SV,
653  SATURATED_DN - 1,
654  0,
655  &DN_sv,
656  &sdev,
657  &rejects[tables->SV_DN_first_frame_to_use]);
658 
659  if (returnStatus != MODIS_S_OK)
660  SMF_ERROR(returnStatus,
661  "Get_DN_Avg_SDev_Rejects() in "
662  "Get_Emiss_Coeff_Per_Scan(), Preprocess.c");
663  }
664 
666  rejects,
667  sv_omask);
668  if (returnStatus != MODIS_S_OK)
669  SMF_ERROR(returnStatus,
670  "Pack_Rejects_In_Outlier_Mask() in "
671  "Get_Emiss_Coeff_Per_Scan(), Preprocess.c");
672 
673  /*
674  * Check for a failure to calculate average SV DN. A failure is not
675  * fatal. It just means that "b1" for this scan will not be calculated.
676  * Return the value of MODIS_S_OK to allow the code to keep going.
677  */
678 
679  if (DN_sv < 0)
680  return (MODIS_S_OK);
681 
682  *xdnsv = DN_sv;
683  *xdnsv_var = sdev * sdev;
684 
685  /*
686  * Compute black-body (BB) average DN.
687  */
688 
689  returnStatus =
690  Get_DN_Avg_SDev_Rejects(tables->BB_DN_first_frame_to_use,
691  tables->BB_DN_number_of_frames_to_use,
692  1,
693  BB,
694  SATURATED_DN - 1,
695  0,
696  &DN_bb,
697  &sdev,
698  &rejects[tables->BB_DN_first_frame_to_use]);
699 
700  if (returnStatus != MODIS_S_OK)
701  SMF_ERROR(returnStatus,
702  "Get_DN_Avg_SDev_Rejects() in "
703  "Get_Emiss_Coeff_Per_Scan(), Preprocess.c");
704 
705 
706  /*
707  * BB WARMUP SATURATION FIX FOR FM1 (MODIS/AQUA)
708  *
709  * On FM1, the BB dns saturate prematurely on BB warmup and consequently
710  * values of b1 cannot be calculated. This problem currently (1/30/2002)
711  * affects FM1 bands 33, 35, and 36. The fix is to check the BB temperature
712  * for these bands, and if it is above a band-specific threshold, use
713  * a LUT value of b1 rather than attempt to calculate b1.
714  */
715 
716  /*
717  * Check to see if satellite is Aqua and the BB_T_sat_switch_aqua
718  * correction switch is on.
719  */
720 
721  if (BB_T_sat_switch_aqua == ON && satellite_ID == AQUA)
722  {
723  /* See if this is one of the bands which needs attention. */
724  for (i = 0; i < NUM_AQUA_BB_SAT_BANDS; i++)
725  {
726  if (B_emiss == bb_sat_bands_indices_aqua[i])
727  {
728  /* The Blackbody temperature threshold: */
729 
730  BB_temp_threshold = tables->BB_T_sat_aqua[i];
731 
732  /* Is the average blackbody temperature over the threshold? */
733 
734  if (T_bb > BB_temp_threshold)
735  {
736  /* If so, use the LUT value of b1 and return. */
737  /* 07/21/2011 apply temperature correction to the default b1. by X. Geng */
738 
739  *Xb1 = tables->BB_T_sat_default_b1_baseline_aqua[i][D][MS]*
740  (1. + tables->BB_T_sat_default_b1_c1_aqua[i][D][MS]*
741  (T_fp_lwir - tables->BB_T_sat_default_b1_Tlwir_baseline_aqua));
742 
743  return (MODIS_S_OK);
744 
745  } /* END if (T_bb >> BB_temp_threshold) */
746 
747  } /* END if (B_emiss == bb_sat_bands_indices_aqua[i]) */
748 
749  } /* END for (i = 0; i < NUM_AQUA_BB_SAT_BANDS; i++) */
750 
751  } /* END if (BB_T_sat_switch_aqua == ON && satellite_ID == AQUA */
752 
753  /*
754  * END BB WARMUP SATURATION FIX FOR FM1 (MODIS/AQUA)
755  */
756 
757  /*
758  * Check for a failure to calculate average BB DN. A failure is not
759  * fatal. It just means that "b1" for this scan will not be calculated.
760  * The value of MODIS_S_OK is returned to allow the code to keep going.
761  * NOTE: if DN_sv is OK but DN_bb is not (all were missing), this will
762  * show up in the product as the "Could not compute zero point DN"
763  * unusable value.
764  */
765 
766  if (DN_bb < 0)
767  return (MODIS_S_OK);
768 
769  /*
770  * Compute dn_bb
771  */
772 
773  dn_bb = DN_bb - DN_sv;
774 
775  /*
776  * PCX correction
777  */
778 
779  if ( PCX_correction_switch == ON && B >= BAND31)
780  {
781 
782  /* For band 31, Xdn_bb_31 is an output. So store dn bb in this address.
783  * For bands 32-36, Xdn_bb_31 is an input and the value stored
784  * in this address is used for PC cross-talk correction.
785  */
786 
787  if ( B == BAND31 ) *Xdn_bb_31 = dn_bb;
788  else if( B >= BAND32 && B <= BAND36 )
789  {
790  dn_bb_31 = *Xdn_bb_31;
791  B_xt = B - BAND32;
792  dn_bb += (tables->PC_XT[B_xt][D][3] -
793  tables->PC_XT[B_xt][D][0]*0.01*
794  dn_bb_31*tables->PC_XT[B_xt][D][2]);
795  }
796  }
797 
798  if (dn_bb < TOLERANCE) /* We cannot calibrate this scan */
799  return returnStatus;
800 
801  if (MS == -1)
802  return returnStatus;
803 
804  *xdnbb = dn_bb;
805 
806  /*
807  * Calculate a0, a2
808  * These are quadratics in instrument temperature (T_ins).
809  */
810 
811  a0 = tables->A0[0][MS][D_emiss] + T_ins * (tables->A0[1][MS][D_emiss]
812  + T_ins * tables->A0[2][MS][D_emiss]);
813 
814  a2 = tables->A2[0][MS][D_emiss] + T_ins * (tables->A2[1][MS][D_emiss]
815  + T_ins * tables->A2[2][MS][D_emiss]);
816 
817  /*
818  * Calculate dL_bb
819  */
820 
821  delta_T_bb = tables->delta_T_bb_beta[D_emiss] * (T_cav - T_bb)
822  + tables->delta_T_bb_delta[D_emiss];
823 
824  returnStatus = Calculate_Planck(tables->RSR[D_emiss],
825  tables->wavelength[D_emiss],
826  tables->NUM_RSR_vs_Lambda[D_emiss],
827  T_mir, &L_sm);
828  if (returnStatus != MODIS_S_OK)
829  SMF_ERROR(returnStatus,
830  "Calculate_Planck() in "
831  "Get_Emiss_Coeff_Per_Scan()");
832 
833  returnStatus = Calculate_Planck(tables->RSR[D_emiss],
834  tables->wavelength[D_emiss],
835  tables->NUM_RSR_vs_Lambda[D_emiss],
836  T_bb+delta_T_bb, &L_bb);
837  if (returnStatus != MODIS_S_OK)
838  SMF_ERROR(returnStatus,
839  "Calculate_Planck() in "
840  "Get_Emiss_Coeff_Per_SCan()");
841 
842  *xLbb = L_bb;
843 
844  returnStatus = Calculate_Planck(tables->RSR[D_emiss],
845  tables->wavelength[D_emiss],
846  tables->NUM_RSR_vs_Lambda[D_emiss],
847  T_cav,
848  &L_cav);
849  if (returnStatus != MODIS_S_OK)
850  SMF_ERROR(returnStatus,
851  "Calculate_Planck() in "
852  "Get_Emiss_Coeff_Per_SCan()");
853 
854  *xLcav = L_cav;
855 
856  bb_corr = RVS_Coeff->RVS_1km_Emiss_BB[D_emiss][MS];
857  sv_corr = RVS_Coeff->RVS_1km_Emiss_SV[D_emiss][MS];
858 
859  dL_bb = bb_corr * tables->epsilon_bb[D_emiss] * L_bb +
860  (sv_corr - bb_corr) * L_sm +
861  (1.0 - tables->epsilon_bb[D_emiss]) *
862  tables->epsilon_cav[D_emiss] *
863  bb_corr * L_cav ;
864 
865  *Xb1 = (dL_bb - a0 - a2 * dn_bb * dn_bb) / dn_bb;
866  *xdLbb = dL_bb;
867 
868  if (calculate_SNR == True)
869  {
870  /*
871  * The anomaly data should be removed in SNR calculation, 3/24/2011, xgeng
872  */
873  /*
874  for ( x = 0; x < BB_1km_FRAMES; x++ )
875  {
876  sum1 += (double) (BB[x] - DN_sv);
877  sum2 += (double) (BB[x] - DN_sv) * (double) (BB[x] - DN_sv);
878  }
879  mean = (float32) (sum1 / (double) x);
880  sdev = (float32) sqrt(fabs((double) (sum2 - sum1*sum1/(double)x)) /
881  (double)(x - 1));
882  if ( sdev < 1.0E-19 )
883  *SNR = -1.0;
884  else
885  *SNR = mean / sdev;
886  */
887  if ( sdev < 1.0E-19 )
888  *SNR = -1.0;
889  else
890  *SNR = dn_bb / sdev;
891 
892  }
893 
894  return returnStatus;
895 }
896 
897 
898 
900  L1A_granule_t *L1A_Gran,
901  L1B_granule_t *L1B_Gran,
902  QA_Data_t *QA,
903  Preprocess_Data_t *PP)
904 /*
905 !C****************************************************************************
906 !Description:
907  Read OBC/Eng data from L1A files and calculate a0, averaged b1, a2,
908  delta_bb, SV counts, dnbb( BB counts subtract SV counts) for every scan in
909  the current granule for emissive bands. Calculate frame-averaged SV
910  counts and standard deviation with outlier rejection for reflective
911  bands. Write OBC target SDSs and preprocessed SDSs, and copy
912  scan_level_metadata sdss, pixel_quality sdss, engineering_memory sdss,
913  and engineering vdata from the middle L1A granule into the L1B_OBC file.
914 
915 !Input Parameters:
916  lookup_tables_t *tables Look-up table inputs.
917  L1A_granule_t *L1A_Gran All data for the middle granule should
918  be filled and file accesses (sd_id, v_id)
919  should be open.
920  L1B_granule_t *L1B_Gran Contains space for RVS correction terms
921  which will be filled
922 !Output Parameters:
923  QA_Data_t *QA All QAs
924  Preprocess_Data_t *PP OBC/Eng averages/statistics
925 
926  Output file: L1B OBC/Eng file.
927 
928 !Revision History:
929 
930  Revision 02.2 March 11, 2002 Razor Issue #174
931  Passed L1B_Gran to Preprocess.c, calculating RVS correction terms before
932  passing them to Emissive coefficient procedures.
933  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
934 
935  Revision 02.12, Jan 26, 2001, Razor issue 152
936  Moved Read Overlap lines inside function Process_OBCEng_Emiss.
937  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
938 
939  Revision 02.11 Sep 5, 2000
940  Made several changes for Razor issue 130 (errors computing "b1" when
941  near a sector rotation or if Ecal ends in the last 40 scans of the
942  leading granule or starts in the 1st 40 scans of the trailing granule).
943  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
944 
945  ... (many revisions not logged) ...
946 
947  Revision 02.10 Mar. 1998
948  Added the QA_Data_t in the interface
949  updated with the new Preprocess_Data_t
950  Shi-Yue Qiu (syqiu@ltpmail.gsfc.nasa.gov)
951 
952  Revision 01.00 Jan. 1997
953  Initial development
954  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
955 
956 !Team-unique Header:
957  This software is developed by the MODIS Characterization Support
958  Team (MCST)for the National Aeronautics and Space Administration,
959  Goddard Space Flight Center, under contract NAS5-32373.
960 
961 !References and Credits:
962  HDF portions developed at the National Center for Supercomputing
963  Applications at the University of Illinois at Urbana-Champaign.
964 
965 !Design Notes:
966 
967 !END**************************************************************************
968 */
969 {
970  PGSt_SMF_status returnStatus = MODIS_S_OK;
971  L1A_granule_OBCEng_t *L1A_OBCEng;
972  L1A_OBCEng = (L1A_granule_OBCEng_t*) malloc(sizeof(L1A_granule_OBCEng_t));
973  Moon_arrays_t *moon_arrays;
974  moon_arrays = (Moon_arrays_t*) malloc(sizeof(Moon_arrays_t));
975 
976  /* Read Extract Metadata */
977  read_extract_metadata(L1A_Gran->sd_id,
982 
983  /*
984  * Calculate the RVS Correction terms for use by Emissive
985  * Coefficient routines and later in L1B.
986  */
987  returnStatus = Calculate_RVS_Correction (tables, L1B_Gran);
988  if (returnStatus != MODIS_S_OK)
989  SMF_ERROR (returnStatus,
990  "Calculate_RVS_Correction() in Preprocess_L1A_Data()");
991 
992 
993  /*
994  * Read OBC & Engineering data from the middle granule.
995  * These are data needed only within the Preprocess module.
996  */
997 
998  returnStatus = Read_L1A_OBCEng (&tables->emiss, L1A_Gran, L1A_OBCEng);
999  if (returnStatus != MODIS_S_OK)
1000  SMF_ERROR (returnStatus,
1001  "Read_L1A_OBCEng() in Preprocess_L1A_Data()");
1002 
1003  /*
1004  * If the NAD is closed, the DN values will be small and the dn_stars
1005  * could be small negative values due to noise. So, set the minimum
1006  * dn_star values to be -40 for all reflective bands if NAD is closed
1007  * for any scan within the granule.
1008  */
1009 
1010  returnStatus = Adjust_dn_star_Min(tables->refl.dn_star_Min,
1011  L1A_Gran->v_id,
1012  L1A_OBCEng->num_scans);
1013  if (returnStatus != MODIS_S_OK)
1014  SMF_ERROR (returnStatus,
1015  "Adjust_dn_star_Min() in Preprocess_L1A_Data()");
1016 
1017  /*
1018  * Check if moon is in SV KOB. This reads data from geolocation file.
1019  */
1020 
1021  returnStatus = Check_For_Moon_in_SV_KOB(L1A_Gran->num_scans,
1022  &tables->QA.common_QA_tables,
1023  QA, moon_arrays);
1024  if (returnStatus != MODIS_S_OK)
1025  SMF_ERROR (returnStatus,
1026  "Check_For_Moon_in_SV_KOB() in Preprocess_L1A_Data()");
1027 
1028  /*
1029  * Process OBCEng data for Reflective_Cal.
1030  */
1031 
1032  returnStatus = Process_OBCEng_Refl (L1A_Gran->sd_id,
1033  L1A_Gran->num_scans,
1034  L1A_OBCEng->temps.ins,
1035  L1A_OBCEng->MirrorSide,
1036  &tables->refl,
1037  moon_arrays,
1038  L1A_OBCEng,
1039  &PP->DN_OBC_Avg,
1040  &QA->QA_refl,
1041  &PP->PP_Refl);
1042 
1043  if (returnStatus != MODIS_S_OK)
1044  SMF_ERROR (returnStatus,
1045  "Process_OBCEng_Refl() in "
1046  "Preprocess_L1A_Data(), Preprocess.c");
1047 
1048  /*
1049  * Process OBCEng data for Emissive_Cal.
1050  */
1051 
1052 
1053  returnStatus = Process_OBCEng_Emiss
1054  (L1A_Gran,
1055  L1A_OBCEng,
1056  &L1B_Gran->Emiss_Cal_Coeff,
1057  &tables->emiss,
1058  &tables->QA,
1059  moon_arrays,
1060  QA,
1061  &PP->PP_Emiss,
1062  &PP->DN_OBC_Avg);
1063 
1064  if (returnStatus != MODIS_S_OK)
1065  SMF_ERROR (returnStatus,
1066  "Process_OBCEng_Emiss"
1067  "Preprocess_L1A_Data(), Preprocess.c");
1068 
1069  /*
1070  * Write most of the OBC file here. Some metadata are added later in other
1071  * parts of the L1B code.
1072  */
1073 
1074  returnStatus = Write_L1B_OBCEng (L1A_Gran, tables,
1075  moon_arrays,
1076  &PP->DN_OBC_Avg);
1077  if (returnStatus != MODIS_S_OK)
1078  SMF_ERROR (returnStatus,
1079  "Write_L1B_OBCEng"
1080  "Preprocess_L1A_Data(), Preprocess.c");
1081 
1082  /*
1083  * Done with the Preprocessor.
1084  */
1085 
1086  free(L1A_OBCEng);
1087  free(moon_arrays);
1088 
1089  return returnStatus;
1090 }
1091 
1092 
1093 PGSt_SMF_status Process_OBCEng_Emiss
1094  (L1A_granule_t *L1A_Gran,
1095  L1A_granule_OBCEng_t *L1A_OBCEng,
1096  Emiss_Cal_Coeff_t *RVS_Coeff,
1098  QA_tables_t *QA_tables,
1099  Moon_arrays_t *moon_arrays,
1100  QA_Data_t *QA,
1101  Preprocess_Emiss_t *PP,
1102  DN_OBC_Avg_t *DN_OBC_Avg)
1103 /*
1104 !C****************************************************************************
1105 !Description:
1106  Preprocess OBC and engineering data for Emissive Calibration. Read
1107  temperature data field, calculated temperatures averaged over a certain
1108  amount of scans, and the ratio of the averaged temperature variance to
1109  prelaunch values (Temperature QA), and the emissive calibration coefficients
1110  (a0, b1, a2, SV dn).
1111 
1112 !Input Parameters:
1113  Overlap_OBCEng_t * Leading_OBCEng Contains number of scans, mirror side,
1114  BB and SV DNs and engineering data for
1115  the leading L1A granule.
1116  Overlap_OBCEng_t * Trailing_OBCEng Contains number of scans, mirror side,
1117  BB and SV DNs and engineering data for
1118  the trailing L1A granule.
1119  L1A_granule_OBCEng_t * L1A_OBCEng Contains number of scans, mirror side,
1120  BB and SV DNs and engineering data for
1121  the middle L1A granule.
1122  Emiss_Cal_Coeff_t *RVS_Coeff Emissive RVS Correction terms
1123  Array of RVS Correction terms for SV
1124  emiss_tables_t * tables Contains all the emissive calibration
1125  LUTs.
1126  QA_tables_t * QA_tables Contains all the emissive quality
1127  assurance LUTs.
1128  Moon_arrays_t * moon_arrays Contains the array of flags for the
1129  moon being in the SV keep-out box (KOB).
1130 
1131 !Output Parameters:
1132  QA_Emiss_t * QA Structure containing quality assurance
1133  data to be written to the L1B products.
1134  Preprocess_Emiss_t * PP Structure containing emissive
1135  calibration coefficients and running
1136  averages of temperatures.
1137  DN_OBC_Avg_t * DN_OBC_Avg Structure containing data to fill in
1138  this routine. The "1km_night" members
1139  are filled (except for band 26, which
1140  was filled in Process_OBCEng_Refl).
1141 
1142 !Revision History:
1143  Revision 02.22, April 29, 2002 Razor Issue #180
1144  Moved initialization of Xb1 and XMS to inside detector loop.
1145  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
1146 
1147  Revision 02.21, March 20, 2002 Razor Issue #178
1148  Removed ADC Correction
1149  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
1150 
1151  Revision 02.20, March 10, 2002 Razor Issue #174
1152  Added passed parameter Emiss_Cal_Coeff_t
1153  in Get_Emiss_Coeff_Per_Scan
1154  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
1155 
1156  Revision 02.19, February 7, 2002 Razor Issue #180
1157  Moved initialization of Xb1 and XMS to inside band loop.
1158  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
1159 
1160  Revision 02.18, January 29, 2002 Razor Issue 175
1161  Create satellite ID and pass to
1162  Get_{Leading,Middle,Trailing}_Gran_Emiss_Coeff
1163  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
1164 
1165  Revision 02.17, Jan 26, 2001, Razor issue 152
1166  Moved Read Overlap lines inside here from parent function.
1167  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1168 
1169  Revision 02.16 Sep 5, 2000
1170  Made changes for Razor issue 130. Removed Ecal_On from argument list
1171  and from calling argument lists of subordinate functions.
1172  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1173 
1174  ... (many revisions not logged) ...
1175 
1176  Revision 02.15 Oct. 22 1999
1177  Added checking for Ecal on
1178  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
1179  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1180 
1181  Revision 02.14 August 1999
1182  Removed variables and calculations for interpolation correction.
1183  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
1184  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1185 
1186  Revision 02.13 August 1999
1187  See SDF, "L1B Code Change to meet ADC correction algorithm change"
1188  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1189 
1190  Revision 02.12 May, 1999
1191  See SDF, "Stage 3: Changes to Emissive Algorithm and Code" notes.
1192  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1193 
1194  Revision 02.11 Feb 9, 1999
1195  Added use of variable ADC_correction_switch set to macro values to
1196  remove compiler warnings. Macros in upper case.
1197  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1198 
1199  Revision 02.10 Apr. 1998
1200  Changed the dynamic to static allocation for the XGranule arrays
1201  Shi-Yue Qiu (syqiu@ltpmail.gsfc.nasa.gov)
1202 
1203  Revision 02.10 Mar. 1998
1204  Remove the D_inv, because it has already been taken care of in L1A
1205  Implemented V2.1 DN vs. L algorithm data preprocessing. Implemented the
1206  different number of scans XGranule averaging for DN and Temperatures
1207  Shi-Yue Qiu (syqiu@ltpmail.gsfc.nasa.gov)
1208 
1209  Revision 01.00 Feb. 1997
1210  Initial development
1211  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
1212 
1213 !Team-unique Header:
1214  This software is developed by the MODIS Characterization Support
1215  Team (MCST)for the National Aeronautics and Space Administration,
1216  Goddard Space Flight Center, under contract NAS5-32373.
1217 
1218 !References and Credits:
1219  HDF portions developed at the National Center for Supercomputing
1220  Applications at the University of Illinois at Urbana-Champaign.
1221 
1222 !Design Notes:
1223  For all cross-granule arrays, a value of -1 is assigned initially as a
1224  value that represents a missing or invalid value. There are two ways that
1225  elements may remain at this invalid value: (1) if the leading or trailing
1226  granule is missing, or (2) if scans are missing from the data.
1227  Additionally, a value of -1 is assigned to the mirror side arrays, also to
1228  denote missing data.
1229 
1230  Variables with "X" at the beginning of the name span the overlap regions of
1231  the leading and trailing granules as well as the middle granule.
1232 
1233 !END**************************************************************************
1234 */
1235 {
1236  PGSt_SMF_status returnStatus = MODIS_S_OK;
1238  int16 B_emiss = 0;
1239  int16 D_emiss = 0;
1240  int16 B = 0;
1241  int16 D = 0;
1242  int16 *XMS;
1243  XMS = (int16*)malloc(MAX_TOTAL_XGRAN_SCANS * sizeof(int16));
1244  float32 *Xb1;
1245  Xb1 = (float32*)malloc(MAX_TOTAL_XGRAN_SCANS * sizeof(float32));
1246  typedef float32 Xdn_bb_31_t[DETECTORS_PER_1KM_BAND];
1247  Xdn_bb_31_t *Xdn_bb_31;
1248  Xdn_bb_31 = (Xdn_bb_31_t*) malloc(MAX_TOTAL_XGRAN_SCANS*sizeof(Xdn_bb_31_t));
1249  int32 s, fp, n;
1250  int32 satellite_ID = INVALID_SATELLITE_ID;
1251  /* 0 = TERRA (PFM); 1 = AQUA (FM1) */
1252 
1253  boolean dropped_scans = False;
1254 
1255  Overlap_OBCEng_t *Leading_OBCEng;
1256  Leading_OBCEng = (Overlap_OBCEng_t*) malloc(sizeof(Overlap_OBCEng_t));
1257  Overlap_OBCEng_t *Trailing_OBCEng;
1258  Trailing_OBCEng = (Overlap_OBCEng_t*) malloc(sizeof(Overlap_OBCEng_t));
1259 
1260  /* Determine the satellite platform. */
1261  satellite_ID = L1A_Gran->satellite_id;
1262 
1263  /*
1264  * Check the macro MAX_TOTAL_XGRAN_SCANS
1265  */
1266 
1267  n = L1A_OBCEng->num_scans + 2 * tables->num_overlap_scans_b1;
1268  if (n > MAX_TOTAL_XGRAN_SCANS)
1270  "MAX_TOTAL_XGRAN_SCANS is too small in "
1271  "Process_OBCEng_Emiss(), Preprocess.c");
1272 
1273  /*
1274  * Read from overlapping granules SV & BB(Emissive only), etc.
1275  */
1276 
1277  dropped_scans = False; /* Initialize for extra insurance */
1278 
1279  returnStatus = Read_Overlap_OBCEng (L1A_Gran,
1280  tables,
1282  Leading_OBCEng,
1283  &dropped_scans);
1284 
1285  if (returnStatus != MODIS_S_OK)
1286  SMF_ERROR (returnStatus,
1287  "Read_Overlap_OBCEng() (Leading granule) in "
1288  "Process_OBCEng_Emiss(), Preprocess.c");
1289 
1290  /*
1291  * If any scans were dropped between the leading and middle granule, set
1292  * a QA flag:
1293  */
1294 
1295  QA->QA_common.leading_granule_scan_gap = dropped_scans;
1296 
1297 
1298  dropped_scans = False; /* Initialize for extra insurance */
1299 
1300 
1301  returnStatus = Read_Overlap_OBCEng (L1A_Gran,
1302  tables,
1304  Trailing_OBCEng,
1305  &dropped_scans);
1306 
1307  if (returnStatus != MODIS_S_OK)
1308  SMF_ERROR (returnStatus,
1309  "Read_Overlap_OBCEng() (Trailing granule) in "
1310  "Process_OBCEng_Emiss(), Preprocess.c");
1311 
1312  /*
1313  * If any scans were dropped between the leading and middle granule, set
1314  * a QA flag:
1315  */
1316 
1317  QA->QA_common.trailing_granule_scan_gap = dropped_scans;
1318 
1319  /*
1320  * Set the QA flags for missing leading and trailing granules.
1321  */
1322 
1323  if (Leading_OBCEng->num_scans == 0)
1325  else
1327  if (Trailing_OBCEng->num_scans == 0)
1329  else
1331 
1332  /*
1333  * Assign quantities to the Preprocess_Emiss_t structure from the per-scan
1334  * values in the middle granule. Also, calculate the granule average
1335  * temperatures which are written to ECS core metadata (in Metadata.c).
1336  */
1337 
1338 
1339  for (s = 0; s < L1A_OBCEng->num_scans; s++) {
1340  PP->fp_set_point_state[s] = L1A_OBCEng->temps.fp_set_point_state[s];
1341  PP->T_bb[s] = L1A_OBCEng->temps.bb_avg[s];
1342  PP->T_mir[s] = L1A_OBCEng->temps.mir_avg[s];
1343  PP->T_ins[s] = L1A_OBCEng->temps.ins[s];
1344  for (fp = 0; fp < NUM_FOCAL_PLANES; fp++)
1345  PP->T_fp[fp][s] = L1A_OBCEng->temps.fp[fp][s];
1346  }
1347  returnStatus = Granule_Average_Temperature(L1A_OBCEng->num_scans,
1348  L1A_OBCEng->temps.mir_avg,
1349  &PP->T_mir_gran);
1350  if (returnStatus != MODIS_S_OK)
1351  SMF_ERROR(returnStatus,
1352  "Granule_Average_Temperature() in "
1353  "Get_Middle_Gran_Temperatures()");
1354 
1355  returnStatus = Granule_Average_Temperature(L1A_OBCEng->num_scans,
1356  L1A_OBCEng->temps.bb_avg,
1357  &PP->T_bb_gran);
1358  if (returnStatus != MODIS_S_OK)
1359  SMF_ERROR(returnStatus,
1360  "Granule_Average_Temperature() in "
1361  "Get_Middle_Gran_Temperatures()");
1362 
1363  returnStatus = Granule_Average_Temperature(L1A_OBCEng->num_scans,
1364  L1A_OBCEng->temps.fp[0],
1365  &PP->T_fp1);
1366  if (returnStatus != MODIS_S_OK)
1367  SMF_ERROR(returnStatus,
1368  "Granule_Average_Temperature() in "
1369  "Get_Middle_Gran_Temperatures()");
1370 
1371  returnStatus = Granule_Average_Temperature(L1A_OBCEng->num_scans,
1372  L1A_OBCEng->temps.fp[1],
1373  &PP->T_fp2);
1374  if (returnStatus != MODIS_S_OK)
1375  SMF_ERROR(returnStatus,
1376  "Granule_Average_Temperature() in "
1377  "Get_Middle_Gran_Temperatures()");
1378 
1379  returnStatus = Granule_Average_Temperature(L1A_OBCEng->num_scans,
1380  L1A_OBCEng->temps.fp[2],
1381  &PP->T_fp3);
1382  if (returnStatus != MODIS_S_OK)
1383  SMF_ERROR(returnStatus,
1384  "Granule_Average_Temperature() in "
1385  "Get_Middle_Gran_Temperatures()");
1386 
1387  returnStatus = Granule_Average_Temperature(L1A_OBCEng->num_scans,
1388  L1A_OBCEng->temps.fp[3],
1389  &PP->T_fp4);
1390  if (returnStatus != MODIS_S_OK)
1391  SMF_ERROR(returnStatus,
1392  "Granule_Average_Temperature() in "
1393  "Get_Middle_Gran_Temperatures()");
1394 
1395 /*-----------------------------------------
1396  Compute temperature QA over a Granule
1397  -----------------------------------------*/
1398  returnStatus = Calculate_Temp_QA(L1A_OBCEng->num_scans,
1399  &L1A_OBCEng->temps, QA_tables, QA);
1400  if (returnStatus != MODIS_S_OK)
1401  SMF_ERROR(returnStatus,
1402  "Calculate_Temp_QA() in Process_OBCEng_Emiss()");
1403 
1404 /*-------------------------------
1405  Calculate PP->Planck_mir
1406  -------------------------------*/
1407 
1408  returnStatus = Calculate_PP_Planck_Mir(L1A_OBCEng->num_scans, tables, PP);
1409  if (returnStatus != MODIS_S_OK)
1410  SMF_ERROR(returnStatus,
1411  "Calculate_PP_Planck_Mir() in Process_OBCEng_Emiss()");
1412 
1413 
1414 /*------------------------------------------------
1415  Compute PP->b1 through XGranule running average
1416  PP->a0
1417  PP->a2
1418  PP->DELTAbb
1419  PP->dbb
1420  ------------------------------------------------*/
1421 
1422  B_emiss = 0;
1423  D_emiss = 0;
1424  for (B = 0; B < L1A_BANDS_AT_RES[R]; B++)
1425  {
1426  if (B == BAND26) continue; /*skip band_26 */
1427 
1428  for (D = 0; D < DETECTORS_PER_1KM_BAND; D++)
1429  {
1430 
1431  /*
1432  * Initialize the X arrays to the invalid value (used as a flag to
1433  * avoid averaging data from scans that are missing or otherwise could
1434  * not calculate b1).
1435  * XMS = Mirror side flags across three granules
1436  * Xb1 = b1 values across three granules (before averaging)
1437  */
1438 
1439  for (s = 0; s < MAX_TOTAL_XGRAN_SCANS; s++)
1440  {
1441  Xb1[s] = -1;
1442  XMS[s] = -1;
1443  }
1444 
1445  /* LeadingOverlap */
1446  returnStatus = Get_Leading_Gran_Emiss_Coeff
1447  (Leading_OBCEng,
1448  B,
1449  D,
1450  D_emiss,
1451  RVS_Coeff,
1452  tables,
1453  moon_arrays,
1454  Xdn_bb_31,
1455  Xb1,
1456  XMS,
1457  satellite_ID);
1458 
1459  if (returnStatus != MODIS_S_OK)
1460  SMF_ERROR(returnStatus,
1461  "Get_Leading_Gran_Emiss_Coeff() in "
1462  "Process_OBCEng_Emiss(), Preprocess.c");
1463 
1464  /* Middle granule
1465  */
1466 
1467  returnStatus = Get_Middle_Gran_Emiss_Coeff
1468  (L1A_OBCEng,
1469  B,
1470  D,
1471  D_emiss,
1472  RVS_Coeff,
1473  tables,
1474  &QA_tables->emiss_QA_tables,
1475  moon_arrays,
1476  Xdn_bb_31,
1477  Xb1,
1478  XMS,
1479  &QA->QA_emiss,
1480  PP,
1481  DN_OBC_Avg,
1482  satellite_ID);
1483  if (returnStatus != MODIS_S_OK)
1484  SMF_ERROR(returnStatus,
1485  "Get_Middle_Gran_Emiss_Coeff() in "
1486  "Process_OBCEng_Emiss(), Preprocess.c");
1487 
1488  /* TrailingOverlap */
1489 
1490  returnStatus = Get_Trailing_Gran_Emiss_Coeff
1491  (L1A_OBCEng->num_scans,
1492  Trailing_OBCEng,
1493  B,
1494  D,
1495  D_emiss,
1496  RVS_Coeff,
1497  tables,
1498  moon_arrays,
1499  Xdn_bb_31,
1500  Xb1,
1501  XMS,
1502  satellite_ID);
1503 
1504  if (returnStatus != MODIS_S_OK)
1505  SMF_ERROR(returnStatus,
1506  "Get_Trailing_Gran_Emiss_Coeff() in "
1507  "Process_OBCEng_Emiss(), Preprocess.c");
1508 
1509  /* Calculate Xgranule running average of b1: PP->b1
1510  */
1511  returnStatus = Get_All_Emiss_Coeff(L1A_OBCEng,
1512  B,
1513  D_emiss,
1514  Xb1,
1515  XMS,
1516  tables,
1517  &QA_tables->emiss_QA_tables,
1518  &QA->QA_emiss,
1519  PP);
1520  if (returnStatus != MODIS_S_OK)
1521  SMF_ERROR(returnStatus,
1522  "Get_All_Emiss_Coeff() in "
1523  "Process_OBCEng_Emiss(), Preprocess.c");
1524  D_emiss++;
1525  }/*End of loop over Detectors per band*/
1526 
1527  B_emiss++;
1528  }/*End of loop over bands*/
1529 
1530  free(XMS);
1531  free(Xb1);
1532  free(Xdn_bb_31);
1533  free(Leading_OBCEng);
1534  free(Trailing_OBCEng);
1535 
1536  return returnStatus;
1537 }
1538 
1539 PGSt_SMF_status Calculate_PP_Planck_Mir(int32 num_scans,
1541  Preprocess_Emiss_t *PP)
1542 
1543 /*
1544 !C************************************************************************
1545 !Description: Calculate radiance of mirror averaged over wavelengths. The
1546  value will be used in Emissive_Cal().
1547 
1548 !Input Parameters:
1549  int32 num_scans
1550  emiss_tables_t * tables
1551 !Output Parameters:
1552  Preprocess_Emiss_t * PP
1553 
1554 !Revision History:
1555  Revision 01.00 Oct. 1998
1556  Initial development
1557  (This code is part of the original function Process_OBCEng_Emiss written
1558  by Zhidong Hao and modified by Shi-Yue Qiu)
1559  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
1560 
1561 !Team-unique Header:
1562  This software is developed by the MODIS Characterization Support
1563  Team (MCST)for the National Aeronautics and Space Administration,
1564  Goddard Space Flight Center, under contract NAS5-32373.
1565 
1566 !References and Credits:
1567  This function is part of the original function Process_OBCEng_Emiss
1568  written by: Zhidong Hao and modified by Shi-Yue Qiu
1569 
1570  HDF portions developed at the National Center for Supercomputing
1571  Applications at the University of Illinois at Urbana-Champaign.
1572 
1573 !Design Notes:
1574 
1575 !END********************************************************************
1576 */
1577 {
1578  PGSt_SMF_status returnStatus = MODIS_S_OK;
1579  int16 B = 0;
1580  int16 D = 0;
1581  int16 S = 0;
1582  int16 D_emiss = 0;
1583 
1584  for (B = 0; B < NUM_EMISSIVE_BANDS; B++)
1585  {
1586  for (D = 0; D < DETECTORS_PER_1KM_BAND; D++)
1587  {
1588  for (S = 0; S < num_scans; S++)
1589  {
1590 
1591  returnStatus = Calculate_Planck(tables->RSR[D_emiss],
1592  tables->wavelength[D_emiss],
1593  tables->NUM_RSR_vs_Lambda[D_emiss],
1594  PP->T_mir[S],
1595  &PP->Planck_mir[D_emiss][S]);
1596  if (returnStatus != MODIS_S_OK)
1597  SMF_ERROR(returnStatus,
1598  "Calculate_Planck() in Process_OBCEng_Emiss()");
1599  }
1600  D_emiss++;
1601  }
1602  }
1603  return (returnStatus);
1604 }
1605 
1606 PGSt_SMF_status Get_Leading_Gran_Emiss_Coeff
1607  (Overlap_OBCEng_t *Leading_OBCEng,
1608  int16 B,
1609  int16 D,
1610  int16 D_emiss,
1611  Emiss_Cal_Coeff_t *RVS_Coeff,
1613  Moon_arrays_t *moon_arrays,
1614  float32 Xdn_bb_31[][DETECTORS_PER_1KM_BAND],
1615  float32 *Xb1,
1616  int16 *XMS,
1617  int32 satellite_ID)
1618 
1619 /*
1620 !C****************************************************************************
1621 !Description:
1622  This function calculates the linear calibration coefficient, b1, for the last
1623  number of overlap scans of the leading L1A granule. The values are placed in
1624  the first set of overlap scans of the return array Xb1. The remaining scan
1625  elements of Xb1 are filled within other functions. The mirror side flags for
1626  the scans of Xb1 are also saved and returned in XMS. If this is band 31, then
1627  BB dn values are saved in Xdn_bb_31. Otherwise, those values are input for
1628  bands 32-36. If this is band 33, 35, or 36, the BB temperature is checked
1629  against a threshold value for the band; if the temperature is over the
1630  threshold, a default b1 value is used for the b1 value.
1631 
1632 !Input Parameters: (Prefix "X" indicates extension cross 3 granules)
1633  Overlap_OBCEng_t * Leading_OBCEng Contains number of scans in leading granule,
1634  SV and BB DNs, mirror side and engineering
1635  temperatures.
1636  int16 B Band index within the resolution.
1637  int16 D Detector index within one emissive band.
1638  int16 B_emiss Band index within the set of emissive bands.
1639  int16 D_emiss Detector index within the set of emissive
1640  detectors.
1641  Emiss_Cal_Coeff_t *RVS_Coeff Emissive RVS Correction terms
1642  emiss_tables_t * tables emissive lookup tables, contains ADC
1643  coefficients and the number of overlap scans
1644  for b1.
1645  Moon_arrays_t * moon_arrays Contains the array of flags for the moon
1646  being in the SV keep-out box (KOB) for the middle
1647  granule.
1648  float32 * Xdn_bb_31[][] Array of blackbody dn for each detector in
1649  band 31 and for each scan. It is an input for
1650  bands 32-36 and an output for band 31.
1651 
1652 !Output Parameters: (Prefix "X" indicates extension across 3 granules)
1653  float32 * Xdn_bb_31[][] (see above)
1654  float32 * Xb1 Per-scan values of b1 in the first number
1655  of overlap scans elements of extended array.
1656  int16 * XMS Mirror side flags across granule, matching the
1657  scans in Xb1.
1658  int32 satellite_ID 0 = TERRA, 1 = AQUA, -1 = INVALID_SATELLITE_ID
1659 
1660 !Revision History:
1661  Revision 02.20 March 25, 2002 Razor Issue #178
1662  Strip out ADC Correction
1663  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
1664 
1665  Revision 02.03 March 10, 2002 Razor Issue #174
1666  Added passed parameter Emiss_Cal_Coeff_t
1667  in Get_Emiss_Coeff_Per_Scan
1668  Alice Isaacman SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
1669 
1670  Revision 02.10, January 29, 2002, Razor Issue 175
1671  Input satellite_ID and passed to Get_Emiss_Coeff_Per_Scan.
1672  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
1673 
1674  Revision 02.02, Dec 19, 2000, Razor issue 148
1675  Delete XT arrays, use values in temps structure (per-scan values)
1676  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1677 
1678  Revision 02.01 Sep 11, 2000
1679  Made changes for Razor issue 133 (TEB algorithm for calculating <DN-SV> when
1680  moon is in the SVP). Now, pass flag denoting if moon is in the SV KOB into
1681  Get_Emiss_Coeff_Per_Scan.
1682  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1683 
1684  Revision 02.00 Sep 5, 2000
1685  Made several changes for Razor issue 130. Removed Ecal_On from argument
1686  list. Added check for Ecal_On and Sector_Rotated for the correct scan prior
1687  to calling Get_Emiss_Coeff_Per_Scan.
1688  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1689 
1690  ... (many revisions not logged) ...
1691 
1692  Revision 01.04 Oct. 22, 1999
1693  Added checking for Ecal on
1694  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
1695  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1696 
1697  Revision 01.03 August 1999
1698  Made corresponding change due to the remove of xdnbb in
1699  Get_Emiss_Coeff_Per_Scan()
1700  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
1701  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1702 
1703  Revision 01.02 August 1999
1704  See SDF, "L1B Code Change to meet ADC correction algorithm change"
1705  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1706 
1707  Revision 01.01 May, 1999Revision 01.02 August 1999
1708  See SDF, "L1B Code Change to meet ADC correction algorithm change"
1709  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1710  See SDF, "Stage 3: Changes to Emissive Algorithm and Code" notes.
1711  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1712 
1713  Revision 01.00 Oct. 1998
1714  Initial development
1715  (This code is part of the original function Process_OBCEng_Emiss written
1716  by Zhidong Hao and modified by Shi-Yue Qiu)
1717  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
1718 
1719 !Team-unique Header:
1720  This software is developed by the MODIS Characterization Support
1721  Team (MCST)for the National Aeronautics and Space Administration,
1722  Goddard Space Flight Center, under contract NAS5-32373.
1723 
1724 !References and Credits:
1725  HDF portions developed at the National Center for Supercomputing
1726  Applications at the University of Illinois at Urbana-Champaign.
1727 
1728 !Design Notes:
1729  If the number of scans in the leading granule is set to zero, then it is
1730  assumed that the leading granule is undefined or missing. This function
1731  simply returns normally to allowed continued processing.
1732 
1733  On a scan-by-scan basis, we do not compute emissive coefficients if:
1734  (1) Ecal is on, (2) there is a sector
1735  rotation on this scan or (3) the mirror side flag is -1 (which usually
1736  means that all data are missing for the scan).
1737 
1738  We determine if the moon is in the SV KOB and pass a flag into
1739  Get_Emiss_Coeff_Per_Scan. For determining if the moon is in the SVP, we use
1740  the 1st scan of the middle granule for all scans of the leading granule.
1741 
1742 !END**************************************************************************
1743 */
1744 {
1745  PGSt_SMF_status returnStatus = MODIS_S_OK;
1746  int16 S = 0;
1747  int16 start_scan = 0;
1748  int16 MS = 0;
1749  int16 XS = 0;
1750  int16 track_index = 0;
1751  float32 SNR = 0;
1752  float32 xdLbb = 0;
1753  float32 xdnbb = 0;
1754  float32 xLbb = 0;
1755  float32 xLcav = 0;
1756  float32 xdnsv = 0;
1757  float32 xdnsv_var;
1758  uint32 sv_omask[2];
1759  int16 B_38;
1760 
1761 
1762  /*
1763  * If the number of scans in the leading granule is zero, then treat
1764  * the leading granule as missing. Simply return and continue
1765  * processing normally.
1766  */
1767 
1768 
1769  if (Leading_OBCEng->num_scans == 0)
1770  return returnStatus;
1771 
1772  /*
1773  * start_scan = absolute scan index in the leading granule for the
1774  * 1st overlap scan.
1775  * XS = index in the set of overlap scans, starting at 0
1776  * for the leading granule.
1777  * S = absolute scan index in the leading granule that
1778  * corresponds to XS
1779  * B_38 = index of this band in the set of 38 MODIS bands.
1780  * track_index = index in the BB and SV arrays that corresponds to
1781  * XS and S (the first track index in those arrays
1782  * corresponds to the start_scan index)
1783  */
1784 
1785  start_scan = Leading_OBCEng->num_scans - tables->num_overlap_scans_b1;
1786  B_38 = MODIS_BAND20_INDEX + B;
1787 
1788  for (XS = 0; XS < tables->num_overlap_scans_b1; XS++)
1789  {
1790  S = start_scan + XS;
1791  MS = Leading_OBCEng->MirrorSide[S];
1792  XMS[XS] = MS;
1793  track_index = XS * DETECTORS_PER_1KM_BAND + D;
1794 
1795  SNR = 0.0;
1796  if ((MS == 0 || MS == 1)
1797  && Leading_OBCEng->Ecal_On[S][B_38] == False
1798  && Leading_OBCEng->Sector_Rotated[S] == False
1799  && Leading_OBCEng->temps.pclw_adc_index[S] != ELECTRONICS_BOTH)
1800  {
1801  returnStatus =
1803  (moon_arrays->moon_in_SV_KOB[0][B_38],
1804  Leading_OBCEng->BB_1km_night[track_index][B],
1805  Leading_OBCEng->SV_1km_night[track_index][B],
1806  B,
1807  D,
1808  D_emiss,
1809  MS,
1810  RVS_Coeff,
1811  tables,
1812  Leading_OBCEng->temps.bb_avg[S],
1813  Leading_OBCEng->temps.mir_avg[S],
1814  Leading_OBCEng->temps.cav[S],
1815  Leading_OBCEng->temps.ins[S],
1816  Leading_OBCEng->temps.fp[FP_LWIR][S],
1817  &Xdn_bb_31 [XS][D],
1818  &Xb1 [XS],
1819  &xdLbb,
1820  &xdnbb,
1821  &xLbb,
1822  &xLcav,
1823  &xdnsv,
1824  &xdnsv_var,
1825  sv_omask,
1826  &SNR,
1827  satellite_ID);
1828 
1829  if (returnStatus != MODIS_S_OK)
1830  SMF_ERROR(returnStatus, "Get_Emiss_Coeff_Per_Scan() in "
1831  "Get_Leading_Gran_Emiss_Coeff()");
1832  }
1833  }
1834 
1835  return (returnStatus);
1836 }
1837 
1838 PGSt_SMF_status Get_Middle_Gran_Emiss_Coeff
1839  (L1A_granule_OBCEng_t *L1A_OBCEng,
1840  int16 B,
1841  int16 D,
1842  int16 D_emiss,
1843  Emiss_Cal_Coeff_t *RVS_Coeff,
1845  emiss_QA_tables_t *QA_tables,
1846  Moon_arrays_t *moon_arrays,
1847  float32 Xdn_bb_31[][DETECTORS_PER_1KM_BAND],
1848  float32 *Xb1,
1849  int16 *XMS,
1850  QA_Emiss_t *QA,
1851  Preprocess_Emiss_t *PP,
1852  DN_OBC_Avg_t *DN_OBC_Avg,
1853  int32 satellite_ID)
1854 
1855 /*
1856 !C****************************************************************************
1857 !Description:
1858  This function calculates the linear calibration coefficient, b1, for the
1859  middle L1A granule. The values are placed in the in Xb1 following the
1860  overlap scans values filled by Get_Leading_Gran_Emiss_Coeff. This function
1861  also calculates averaged SV DN for emissive processing. The mirror side flags for
1862  the scans of Xb1 are also saved and returned in XMS. If this is band 31, then
1863  BB dn values are saved in Xdn_bb_31. Otherwise, those values are input for
1864  bands 32-36.
1865 
1866 
1867 !Input Parameters:
1868  L1A_granule_OBCEng_t *L1A_OBCEng Contains number of scans in middle
1869  granule, SV and BB DNs, mirror side and
1870  engineering temperatures.
1871  int16 B Band index within the resolution.
1872  int16 D Detector index within one emissive band.
1873  int16 B_emiss Band index within the set of emissive bands.
1874  int16 D_emiss Detector index within the set of
1875  emissive detectors.
1876  Emiss_Cal_Coeff_t *RVS_Coeff Emissive RVS Correction terms
1877  emiss_tables_t *tables emissive lookup tables, contains ADC
1878  coefficients and the number of overlap
1879  scans for b1.
1880  emiss_QA_tables *QA_tables Contains prelaunch NEdL.
1881  Moon_arrays_t *moon_arrays Contains the array of flags for the moon
1882  being in the SV keep-out box (KOB) for the
1883  middle granule.
1884  float32 * Xdn_bb_31[][] Array of blackbody dn for each detector in
1885  band 31 and for each scan. It is an input
1886  for bands 32-36 and an output for band31.
1887  int32 satellite_ID 0 = TERRA, 1 = AQUA, -1 = INVALID_SATELLITE_ID
1888 
1889 !Output Parameters:
1890  float32 * Xdn_bb_31[][] (see above)
1891  float32 * Xb1 Per-scans values of b1 in the first
1892  number of overlap scans elements of
1893  extended array.
1894  int16 * XMS Mirror side flags across granule
1895  matching the scans in Xb1.
1896  QA_Emiss_t * QA Hold the NEdL calculated here.
1897  Preprocess_Emiss_t * PP members filled include DN_sv.
1898  DN_OBC_Avg_t * DN_OBC_Avg Members filled include the 1km_night
1899  arrays.
1900 
1901 !Revision History:
1902  Revision 02.10 March 25, 2002 Razor Issue #178
1903  Strip out ADC Correction
1904  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
1905 
1906  Revision 02.03 March 11, 2002 Razor Issue #174
1907  Added passed parameter Emiss_Cal_Coeff_t
1908  and added to call to Get_Emiss_Coeffs_Per_Scan
1909  Alice Isaacman SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
1910 
1911  Revision 02.02, January 29, 2002 Razor Issue #175
1912  Added satellite_ID as input and passed to Get_Emiss_Coeffs_Per_Scan
1913  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
1914 
1915  Revision 02.01 Sep 11, 2000
1916  Made changes for Razor issue 133 (TEB algorithm for calculating <DN-SV> when
1917  moon is in the SVP). Now, pass flag denoting if moon is in the SV KOB into
1918  Get_Emiss_Coeff_Per_Scan.
1919  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1920 
1921  Revision 02.00 Sep 5, 2000
1922  Made several changes for Razor issue 130. Removed Ecal_On from argument
1923  list. Added check for Ecal_On and Sector_Rotated for the correct scan prior
1924  to calling Get_Emiss_Coeff_Per_Scan.
1925  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1926 
1927  ... (many revisions not logged) ...
1928 
1929  Revision 01.04 Oct. 22, 1999
1930  Added checking for Ecal on
1931  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1932 
1933  Revision 01.03 August 1999
1934  Removed calculation of delta radiance and DN for the black body.
1935  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1936 
1937  Revision 01.02 August 1999
1938  See SDF, "L1B Code Change to meet ADC correction algorithm change"
1939  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1940 
1941  Revision 01.01 May, 1999
1942  See SDF, "Stage 3: Changes to Emissive Algorithm and Code" notes.
1943  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1944 
1945  Revision 01.00 Oct. 1998
1946  Initial development
1947  (This code is part of the original function Process_OBCEng_Emiss written
1948  by Zhidong Hao and modified by Shi-Yue Qiu)
1949  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
1950 
1951 !Team-unique Header:
1952  This software is developed by the MODIS Characterization Support
1953  Team (MCST)for the National Aeronautics and Space Administration,
1954  Goddard Space Flight Center, under contract NAS5-32373.
1955 
1956 !References and Credits:
1957  HDF portions developed at the National Center for Supercomputing
1958  Applications at the University of Illinois at Urbana-Champaign.
1959 
1960 !Design Notes:
1961  Prefix "X" indicates extension cross 3 granules.
1962  On a scan-by-scan basis, we do not compute emissive coefficients if:
1963  (1) Ecal is on, (2) there is a sector
1964  rotation on this scan or (3) the mirror side flag is -1 (which usually
1965  means that all data are missing for the scan).
1966 
1967  We determine if the moon is in the SV KOB and pass a flag into
1968  Get_Emiss_Coeff_Per_Scan.
1969 
1970 !END**************************************************************************
1971 */
1972 {
1973  PGSt_SMF_status returnStatus = MODIS_S_OK;
1974  int16 rejects[MAX_1KM_OBC_FRAME_DIM];
1975  int16 S = 0;
1976  int16 MS = 0;
1977  int16 XS = 0;
1978  int16 track_index = 0;
1979  float32 SNR = 0;
1980  float32 sum_NEdL = 0;
1981  float32 xdLbb = 0;
1982  float32 xdnbb = 0;
1983  float32 xLbb = 0;
1984  float32 xLcav = 0;
1985  float32 xdnsv = 0;
1986  float32 xdnsv_var = 0;
1987  float32 ratio = 0;
1988  int32 n;
1989  int16 B_38;
1990  int16 F;
1991 
1992  n = 0;
1993  B_38 = MODIS_BAND20_INDEX + B;
1994  for (S = 0; S < L1A_OBCEng->num_scans; S++)
1995  {
1996  MS = L1A_OBCEng->MirrorSide[S];
1997  XS = tables->num_overlap_scans_b1 + S;
1998  XMS[XS] = MS;
1999  track_index = S * DETECTORS_PER_1KM_BAND + D;
2000  SNR = 1.0;
2001  if (L1A_OBCEng->Ecal_On[S][B_38] == False
2002  && L1A_OBCEng->Sector_Rotated[S] == False
2003  && L1A_OBCEng->temps.pclw_adc_index[S] != ELECTRONICS_BOTH
2004  && (MS == 0 || MS == 1))
2005  {
2006  returnStatus =
2008  (moon_arrays->moon_in_SV_KOB[S][B_38],
2009  L1A_OBCEng->BB_1km_night[track_index][B],
2010  L1A_OBCEng->SV_1km_night[track_index][B],
2011  B,
2012  D,
2013  D_emiss,
2014  MS,
2015  RVS_Coeff,
2016  tables,
2017  L1A_OBCEng->temps.bb_avg[S],
2018  L1A_OBCEng->temps.mir_avg[S],
2019  L1A_OBCEng->temps.cav[S],
2020  L1A_OBCEng->temps.ins[S],
2021  L1A_OBCEng->temps.fp[FP_LWIR][S],
2022  &Xdn_bb_31 [XS][D],
2023  &Xb1 [XS],
2024  &xdLbb,
2025  &xdnbb,
2026  &xLbb,
2027  &xLcav,
2028  &xdnsv,
2029  &xdnsv_var,
2030  DN_OBC_Avg->DN_obc_1km_night_outlier_mask
2031  [track_index][B][0],
2032  &SNR,
2033  satellite_ID);
2034 
2035  if (returnStatus != MODIS_S_OK)
2036  SMF_ERROR(returnStatus,
2037  "Get_Emiss_Coeff_Per_Scan() in "
2038  "Get_Middle_Gran_Emiss_Coeff()");
2039  }
2040  else
2041  {
2042  for (F = 0; F < MAX_1KM_OBC_FRAME_DIM; F++)
2043  rejects[F] = 1;
2044  returnStatus = Pack_Rejects_In_Outlier_Mask
2045  (SV_1km_FRAMES,
2046  rejects,
2047  DN_OBC_Avg->DN_obc_1km_night_outlier_mask
2048  [track_index][B][0]);
2049 
2050  if (returnStatus != MODIS_S_OK)
2051  SMF_ERROR(returnStatus,
2052  "Pack_Rejects_In_Outlier_Mask() in "
2053  "Get_Middle_Gran_Emiss_Coeff()");
2054 
2055  xdLbb = -1;
2056  xdnbb = -1;
2057  xLbb = -1;
2058  xLcav = -1;
2059  xdnsv = -1;
2060  xdnsv_var = -1;
2061  SNR = -1;
2062  }
2063 
2064  PP->dn_bb[D_emiss][S] = xdnbb;
2065  PP->L_bb[D_emiss][S] = xLbb;
2066  PP->L_cav[D_emiss][S] = xLcav;
2067  PP->DN_sv[D_emiss][S] = xdnsv;
2068  DN_OBC_Avg->DN_obc_1km_night_avg[track_index][B][0] = xdnsv;
2069  DN_OBC_Avg->DN_obc_1km_night_var[track_index][B][0] = xdnsv_var;
2070  if ( SNR > 0 )
2071  {
2072  PP->dn_bb_sdev[D_emiss][S] = PP->dn_bb[D_emiss][S]/SNR;
2073  PP->NEdL[D_emiss][S] = xdLbb/SNR;
2074  sum_NEdL += xdLbb/SNR;
2075  n++;
2076  }
2077  else
2078  {
2079  PP->dn_bb_sdev[D_emiss][S] = 0.;
2080  PP->NEdL[D_emiss][S] = 0;
2081  }
2082  }/*End of loop over middle scans*/
2083 
2084  if (n == 0)
2085  ratio = 0.0;
2086  else
2087  {
2088  sum_NEdL /= (float32)n;
2089  ratio = sum_NEdL / QA_tables->NEdL[D_emiss];
2090  }
2091  CONVERT_TO_UINT8(ratio, QA->NEdL[D_emiss]);
2092 
2093  return (returnStatus);
2094 }
2095 
2096 
2097 PGSt_SMF_status Get_Trailing_Gran_Emiss_Coeff
2098  (int32 num_scans_middle,
2099  Overlap_OBCEng_t *Trailing_OBCEng,
2100  int16 B,
2101  int16 D,
2102  int16 D_emiss,
2103  Emiss_Cal_Coeff_t *RVS_Coeff,
2105  Moon_arrays_t *moon_arrays,
2106  float32 Xdn_bb_31[][DETECTORS_PER_1KM_BAND],
2107  float32 *Xb1,
2108  int16 *XMS,
2109  int32 satellite_ID)
2110 
2111 
2112 /*
2113 !C****************************************************************************
2114 !Description:
2115  This function calculates the linear calibration coefficient, b1, for the first
2116  number of overlap scans of the trailing L1A granule. The values are placed
2117  in the last set of overlap scans of the return array Xb1. The remaining
2118  scan elements of Xb1 were previously filled within other functions. The
2119  mirror side flags for the scans of Xb1 are also saved and returned in XMS.
2120  If this is band 31, then BB dn values are saved in Xdn_bb_31. Otherwise,
2121  those values are input for bands 32-36.
2122 
2123 
2124 !Input Parameters:
2125  int32 num_scans_middle Number of scans in the middle granule.
2126  Overlap_OBCEng_t * Trailing_OBCEng Contains number of scans in trailing
2127  granule, SV and BB DNs, mirror side and
2128  engineering temperatures.
2129  int16 B Band index within the resolution.
2130  int16 D Detector index within one emissive band.
2131  int16 B_emiss Band index within the set of emissive bands.
2132  int16 D_emiss Detector index within the set of emissive
2133  detectors.
2134  Emiss_Cal_Coeff_t *RVS_Coeff Emissive RVS Correction terms
2135  emiss_tables_t * tables emissive lookup tables, contains ADC
2136  coefficients and the number of overlap
2137  scans for b1.
2138  Moon_arrays_t * moon_arrays Contains the array of flags for the moon
2139  being in the SV keep-out box (KOB) for the
2140  middle granule.
2141  float32 * Xdn_bb_31[][] Array of blackbody dn for each detector in
2142  band 31 and for each scan. It is an input
2143  for bands 32-36 and an output for band 31.
2144  int32 satellite_ID 0 = TERRA, 1 = AQUA, -1 = INVALID_SATELLITE_ID
2145 !Output Parameters:
2146  float32 * Xdn_bb_31[][] (see above)
2147  float32 * Xb1 Per-scans values of b1 in the last number
2148  of overlap scans elements of extended
2149  array.
2150  int16 * XMS Mirror side flags across granule, matching the
2151  scans in Xb1.
2152  int32 satellite_ID 0 = TERRA, 1 = AQUA, -1 = INVALID_SATELLITE_ID
2153 
2154 !Revision History:
2155  Revision 02.10 March 25, 2002 Razor Issue #178
2156  Strip out ADC Correction
2157  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
2158 
2159  Revision 02.03 March 11, 2002 Razor Issue #174
2160  Added passed parameter RVS_Coeff
2161  and added to call to Get_Emiss_Coeffs_Per_Scan
2162  Alice Isaacman SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
2163 
2164  Revision 02.02 January 29, 2002 Razor Issue #175
2165  Added input parameter satellite_ID and passed to Get_Emiss_Coeff_Per_Scan
2166  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
2167 
2168  Revision 02.01 Sep 11, 2000
2169  Made changes for Razor issue 133 (TEB algorithm for calculating <DN-SV> when
2170  moon is in the SVP). Now, pass flag denoting if moon is in the SV KOB into
2171  Get_Emiss_Coeff_Per_Scan.
2172  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
2173 
2174  Revision 02.00 Sep 5, 2000
2175  Made several changes for Razor issue 130. Removed Ecal_On from argument
2176  list. Added check for Ecal_On and Sector_Rotated for the correct scan prior
2177  to calling Get_Emiss_Coeff_Per_Scan.
2178  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
2179 
2180  ... (many revisions not logged) ...
2181 
2182  Revision 01.04 Oct. 22, 1999
2183  Added checking for Ecal on
2184  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
2185 
2186  Revision 01.03 August 1999
2187  Removed the calculation of delta radiance and DN for the black body.
2188  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
2189 
2190  Revision 01.02 August 1999
2191  See SDF, "L1B Code Change to meet ADC correction algorithm change"
2192  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
2193 
2194  Revision 01.01 May, 1999
2195  See SDF, "Stage 3: Changes to Emissive Algorithm and Code" notes.
2196  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
2197 
2198  Revision 01.00 Oct. 1998
2199  Initial development
2200  (This code is part of the original function Process_OBCEng_Emiss written
2201  by Zhidong Hao and modified by Shi-Yue Qiu)
2202  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
2203 
2204 !Team-unique Header:
2205  This software is developed by the MODIS Characterization Support
2206  Team (MCST)for the National Aeronautics and Space Administration,
2207  Goddard Space Flight Center, under contract NAS5-32373.
2208 
2209 !References and Credits:
2210  HDF portions developed at the National Center for Supercomputing
2211  Applications at the University of Illinois at Urbana-Champaign.
2212 
2213 !Design Notes:
2214  If the number of scans in the trailing granule is set to zero, then it is
2215  assumed that the trailing granule is undefined or missing. This function
2216  simply returns normally to allowed continued processing. The values in the
2217  cross-granule arrays remain unchanged from their entry state (the parent
2218  initializes these to an appropriate value).
2219 
2220  On a scan-by-scan basis, we do not compute emissive coefficients if:
2221  (1) Ecal is on, (2) there is a sector
2222  rotation on this scan or (3) the mirror side flag is -1 (which usually
2223  means that all data are missing for the scan).
2224 
2225  We determine if the moon is in the SV KOB and pass a flag into
2226  Get_Emiss_Coeff_Per_Scan. For determining if the moon is in the SVP, we use
2227  the last scan of the middle granule for all scans of the leading granule.
2228 
2229 !END**************************************************************************
2230 */
2231 {
2232  PGSt_SMF_status returnStatus = MODIS_S_OK;
2233  int16 S = 0;
2234  int16 MS = 0;
2235  int16 XS = 0;
2236  int16 track_index = 0;
2237  float32 SNR = 0;
2238  float32 xdLbb = 0;
2239  float32 xdnbb = 0;
2240  float32 xLbb = 0;
2241  float32 xLcav = 0;
2242  float32 xdnsv = 0;
2243  float32 xdnsv_var;
2244  uint32 sv_omask[2];
2245  int16 B_38;
2246 
2247  if (Trailing_OBCEng->num_scans == 0)
2248  return returnStatus;
2249 
2250  B_38 = MODIS_BAND20_INDEX + B;
2251 
2252  for (S = 0; S < tables->num_overlap_scans_b1; S++)
2253  {
2254  MS = Trailing_OBCEng->MirrorSide[S];
2255  XS = tables->num_overlap_scans_b1 + num_scans_middle + S;
2256  XMS[XS] = MS;
2257  track_index = S * DETECTORS_PER_1KM_BAND + D;
2258 
2259  SNR = 0.0;
2260  if (moon_arrays->moon_in_SV_KOB[num_scans_middle-1][B_38] !=
2262  && (MS == 0 || MS == 1)
2263  && Trailing_OBCEng->Ecal_On[S][B_38] == False
2264  && Trailing_OBCEng->Sector_Rotated[S] == False
2265  && Trailing_OBCEng->temps.pclw_adc_index[S] != ELECTRONICS_BOTH)
2266  {
2267  returnStatus = Get_Emiss_Coeff_Per_Scan
2268  (moon_arrays->moon_in_SV_KOB
2269  [num_scans_middle - 1][B_38],
2270  Trailing_OBCEng->BB_1km_night[track_index][B],
2271  Trailing_OBCEng->SV_1km_night[track_index][B],
2272  B,
2273  D,
2274  D_emiss,
2275  MS,
2276  RVS_Coeff,
2277  tables,
2278  Trailing_OBCEng->temps.bb_avg[S],
2279  Trailing_OBCEng->temps.mir_avg[S],
2280  Trailing_OBCEng->temps.cav[S],
2281  Trailing_OBCEng->temps.ins[S],
2282  Trailing_OBCEng->temps.fp[FP_LWIR][S],
2283  &Xdn_bb_31[XS][D],
2284  &Xb1[XS],
2285  &xdLbb,
2286  &xdnbb,
2287  &xLbb,
2288  &xLcav,
2289  &xdnsv,
2290  &xdnsv_var,
2291  sv_omask,
2292  &SNR,
2293  satellite_ID);
2294 
2295  if (returnStatus != MODIS_S_OK)
2296  SMF_ERROR(returnStatus,
2297  "Get_Emiss_Coeff_Per_Scan() in Process_OBCEng_Emiss()");
2298  }
2299  }/*End of loop over trailing scans*/
2300 
2301  return (returnStatus);
2302 }
2303 
2304 PGSt_SMF_status Get_All_Emiss_Coeff
2305  (L1A_granule_OBCEng_t *L1A_OBCEng,
2306  int16 B,
2307  int16 D_emiss,
2308  float32 *Xb1,
2309  int16 *Xmir,
2311  emiss_QA_tables_t *QA_tables,
2312  QA_Emiss_t *QA,
2313  Preprocess_Emiss_t *PP)
2314 
2315 /*
2316 !C************************************************************************
2317 !Description: Calculate averaged b1, a0, a2 for each scan for the current
2318  granule(corresponding to the middle L1A granule) and the b1
2319  change since prelaunch.
2320 
2321 !Input Parameters:
2322  L1A_granule_OBCEng_t *L1A_OBCEng Containing the number of scans
2323  and the mirror side for each
2324  scan for the middle granule.
2325  int16 B Band index within the resolution.
2326  int16 D_emiss Detector index within the set of
2327  emissive detectors.
2328  float32 * Xb1 Cross-granule per-scan values of
2329  b1 calculated in other functions.
2330  int16 * Xmir Cross-granule per-scan values of mirror
2331  side.
2332  emiss_tables_t * tables Containing b1 for band 21 and the
2333  A0 and A2 values for calculating a0
2334  and a2, respectively.
2335  emiss_QA_tables_t * QA_tables Containing the prelaunch values of b1,
2336  i.e. a1.
2337 !Output Parameters:
2338  QA_Emiss_t * QA Containing the value change of b1 since
2339  prelaunch.
2340  Preprocess_Emiss_t * PP Store the coefficients b1, a0 and a2 of
2341  the middle granule.
2342 
2343 !Revision History:
2344  Revision 02.19, October 15, 2004 Razor Issue #201
2345  Changed the for-loop of getting off-line calculated average b1 of Band 21
2346  to include the new dimension for Mirror Side specification.
2347  Liqin Tan, SAIC GSO (ltan@saicmodis.com)
2348 
2349  Revision 02.18, Jan 29, 2001
2350  Improved efficiency of calculation of a0 and a2.
2351  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
2352 
2353  Revision 02.17 Sep. 12, 2000
2354  Corrected the calculation of average b1 in case of missing scans
2355  (where b1 will be set to -1).
2356  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
2357 
2358  Revision 02.16 August 23, 1999
2359  Removed calculation of the delta_bb.
2360  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
2361  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
2362 
2363  Revision 02.15 April 12, 1999
2364  Removed cubic term a3
2365  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
2366 
2367  Revision 01.00 Oct. 1998
2368  Initial development
2369  (This code is part of the original function Process_OBCEng_Emiss written
2370  by Zhidong Hao and modified by Shi-Yue Qiu)
2371  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
2372 
2373 !Team-unique Header:
2374  This software is developed by the MODIS Characterization Support
2375  Team (MCST)for the National Aeronautics and Space Administration,
2376  Goddard Space Flight Center, under contract NAS5-32373.
2377 
2378 !References and Credits:
2379  This function is part of the original function Process_OBCEng_Emiss
2380  written by: Zhidong Hao and modified by Shi-Yue Qiu
2381 
2382  HDF portions developed at the National Center for Supercomputing
2383  Applications at the University of Illinois at Urbana-Champaign.
2384 
2385 !Design Notes:
2386 
2387  "b1" must be a positive number to be valid. In here (and elsewhere),
2388  a negative value of b1 is used as a flag to denote that it could not
2389  be calculated for some reason.
2390 
2391 !END********************************************************************
2392 */
2393 {
2394  PGSt_SMF_status returnStatus = MODIS_S_OK;
2395  int16 MS = 0;
2396  int16 S = 0;
2397  float32 avg_b1 = 0;
2398  float32 ratio = 0;
2399  float32 T_ins = 0;
2400  int16 ns_avg = 0;
2401 
2402  /* Calculate Xgranule running average of b1: PP->b1
2403  */
2404 
2405  if (B == BAND21) /* b1(B21) is fixed */
2406  {
2407  /* use D_emiss - 10 for index to avoid passing in new argument */
2408  for (S = 0; S < L1A_OBCEng->num_scans; S++){
2409  MS = L1A_OBCEng->MirrorSide[S];
2410  PP->b1[D_emiss][S] = tables->Band_21_b1[D_emiss - 10][MS];
2411  }
2412  }
2413  else
2414  {
2415  returnStatus = Cross_Granule_Sliding_Average
2416  (tables->num_overlap_scans_b1,
2417  L1A_OBCEng->num_scans,
2418  Xb1,
2419  Xmir,
2420  PP->b1[D_emiss]);
2421  if (returnStatus != MODIS_S_OK)
2422  SMF_ERROR(returnStatus,
2423  "Cross_Granule_Sliding_Average(b1) in Process_OBCEng_Emiss()");
2424  }
2425 
2426  /* Calculate QA->change_b1 : b1/pre_launch_a1
2427  */
2428 
2429  avg_b1 = 0;
2430  ns_avg = 0;
2431  for ( S = 0; S < L1A_OBCEng->num_scans; S++ ) {
2432  if (PP->b1[D_emiss][S] > 0) {
2433  avg_b1 += PP->b1[D_emiss][S];
2434  ns_avg++;
2435  }
2436  }
2437  if (ns_avg > 0)
2438  avg_b1 = avg_b1/ns_avg;
2439 
2440  ratio = avg_b1 / QA_tables->a1[D_emiss];
2441  CONVERT_TO_UINT8(ratio, QA->change_b1[D_emiss]);
2442 
2443  /* Calculate PP->a0, PP->a2
2444  */
2445  for (S = 0; S < L1A_OBCEng->num_scans; S++)
2446  {
2447  MS = L1A_OBCEng->MirrorSide[S];
2448 
2449  if(PP->T_ins[S] > TOLERANCE && (MS == 0 || MS == 1))
2450  {
2451  T_ins = PP->T_ins[S];
2452  PP->a0[D_emiss][S] = tables->A0[0][MS][D_emiss]
2453  + T_ins * (tables->A0[1][MS][D_emiss]
2454  + T_ins * tables->A0[2][MS][D_emiss]);
2455 
2456  PP->a2[D_emiss][S] = tables->A2[0][MS][D_emiss]
2457  + T_ins * (tables->A2[1][MS][D_emiss]
2458  + T_ins * tables->A2[2][MS][D_emiss]);
2459 
2460  PP->sigma_a0[D_emiss][S] = tables->sigma_a0[0][MS][D_emiss]
2461  + T_ins * (tables->sigma_a0[1][MS][D_emiss]
2462  + T_ins * tables->sigma_a0[2][MS][D_emiss]);
2463 
2464  PP->sigma_a2[D_emiss][S] = tables->sigma_a2[0][MS][D_emiss]
2465  + T_ins * (tables->sigma_a2[1][MS][D_emiss]
2466  + T_ins * tables->sigma_a2[2][MS][D_emiss]);
2467  }
2468  else {
2469  PP->a0[D_emiss][S] = 0.;
2470  PP->a2[D_emiss][S] = 0.;
2471  PP->sigma_a0[D_emiss][S] = 0.;
2472  PP->sigma_a2[D_emiss][S] = 0.;
2473  }
2474  }
2475 
2476  return (returnStatus);
2477 }
2478 
2479 PGSt_SMF_status Get_DN_Avg_SDev_Rejects
2480  (int32 start_index,
2481  int32 N,
2482  int32 index_increment,
2483  int16 *DN_array,
2484  int16 DN_upper_valid_limit,
2485  int16 DN_lower_valid_limit,
2486  float32 *mean_DN,
2487  float32 *sdev_DN,
2488  int16 *rejects)
2489 /*
2490 !C**********************************************************************
2491 !Description:
2492  Given a set of Reflective Solar Band (RSB) or Thermal Emissive Band
2493  (TEB) digital numbers (DNs), compute the mean and standard deviation
2494  of a subset of the set. The subset is determined by supplying a start
2495  index, number of values and an index increment. The DN values are checked
2496  for validity and an outlier-rejection algorithm is included that may also
2497  reduce the final set of values for which mean and standard deviation are
2498  computed. The indices of the values rejected are also returned.
2499 
2500 
2501 !Input Parameters:
2502  int32 start_index starting index for values to include
2503  int32 N number of values to include in the set.
2504  int32 index_increment amount to increment when forming set
2505  of values
2506  int16 * DN_array array of digital numbers. This should
2507  be large enough to extract all data
2508  from the subset.
2509  int16 DN_upper_valid_limit Upper limit of the valid range of
2510  DNs (typically 4094).
2511  int16 DN_lower_valid_limit Lower limit of the valid range of
2512  DNs (typically 0).
2513 !Output Parameters:
2514  float32 * mean_DN Mean value of final set of data after
2515  all invalid and outlier values are
2516  removed. A negative return value means
2517  that all values were rejected for some
2518  reason.
2519  float32 * sdev_DN standard deviation of the final set of
2520  values. A negative return value means
2521  that all values were rejected for some
2522  reason.
2523  int16 * rejects An array of dimension [N], where 1
2524  denotes a value was removed and 0
2525  denotes that a value was used in the
2526  final set.
2527 
2528 !Revision History:
2529 
2530  Revision 01.10 March 25, 2002 Razor Issue #178
2531  Strip out ADC Correction (delta_DN)
2532  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
2533 
2534  Revision 01.02 November 7, 2001
2535  Initialized DN_work to 0 (Razor issue #168)
2536  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
2537 
2538  Revision 01.01 August 1999
2539  Changed interface due to new ADC correction algorithm. See design document for
2540  detail.
2541  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
2542  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
2543 
2544  Revision 01.00 April 1999
2545  Initial development
2546  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
2547  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
2548 
2549 !Team-unique Header:
2550  This software is developed by the MODIS Characterization Support
2551  Team (MCST)for the National Aeronautics and Space Administration,
2552  Goddard Space Flight Center, under contract NAS5-32373.
2553 
2554 !References and Credits:
2555  HDF portions developed at the National Center for Supercomputing
2556  Applications at the University of Illinois at Urbana-Champaign.
2557 
2558 !Design Notes:
2559 
2560 !END********************************************************************
2561 */
2562 {
2563  PGSt_SMF_status returnStatus = MODIS_S_OK;
2564  int32 i;
2565  int16 DN;
2566  double sum1;
2567  double sum2;
2568  float32 mean;
2569  float32 sigma;
2570  float32 three_sigma;
2571  int32 ninclude;
2572  float32 delta;
2573  float32 DN_work[MAX_250M_OBC_FRAME_DIM];
2574 
2575  if (N <= 0 || N > MAX_250M_OBC_FRAME_DIM)
2576  return (MODIS_F_NOK);
2577 
2578  for (i = 0; i < MAX_250M_OBC_FRAME_DIM; i++)
2579  DN_work[i] = 0.;
2580 
2581  *mean_DN = -1;
2582  *sdev_DN = -1;
2583  sum1 = 0;
2584  sum2 = 0;
2585  ninclude = 0;
2586  for (i = 0; i < N; i++)
2587  {
2588  DN = DN_array[start_index + i * index_increment];
2589  if (DN >= DN_lower_valid_limit && DN <= DN_upper_valid_limit)
2590  {
2591  DN_work[i] = DN;
2592 
2593  sum1 += (double) DN_work[i];
2594  sum2 += (double) DN_work[i] * (double) DN_work[i];
2595  ninclude++;
2596  rejects[i] = 0;
2597  }
2598  else
2599  {
2600  rejects[i] = 1;
2601  }
2602  }
2603 
2604  if (ninclude == 0)
2605  return returnStatus;
2606  else if (ninclude == 1) {
2607  *mean_DN = sum1;
2608  *sdev_DN = 0;
2609  return returnStatus;
2610  }
2611 
2612  mean = sum1/ninclude;
2613  sigma = sqrt(fabs((double) (sum2 - sum1 * sum1/(double)ninclude)) /
2614  (double) (ninclude - 1));
2615  three_sigma = 3 * sigma;
2616 
2617  for (i = 0; i < N; i++)
2618  {
2619  delta = fabs((double) (DN_work[i] - mean));
2620  if (rejects[i] == 0 && delta > three_sigma)
2621  {
2622  sum1 -= (double) DN_work[i];
2623  sum2 -= (double) DN_work[i] * (double) DN_work[i];
2624  rejects[i] = 1;
2625  ninclude--;
2626  }
2627  }
2628 
2629  if (ninclude == 0 || ninclude == 1)
2630  return returnStatus;
2631 
2632  mean = sum1/ninclude;
2633  sigma = sqrt(fabs((double) (sum2 - sum1 * sum1/(double)ninclude)) /
2634  (double) (ninclude - 1));
2635  *mean_DN = mean;
2636  *sdev_DN = sigma;
2637 
2638  return returnStatus;
2639 }
2640 
2641 PGSt_SMF_status Pack_Rejects_In_Outlier_Mask(int32 N,
2642  int16 *rejects,
2643  uint32 *packed_rejects)
2644 /*
2645 !C**********************************************************************
2646 !Description:
2647  Store the values of flag array "rejects" into a smaller array
2648  "packed_rejects". Each value is stored in a bit beginning at the least
2649  significant bit of the first element in "packed_rejects".
2650 
2651 !Input Parameters:
2652  int32 N number of elements in the array rejects
2653  int16 rejects array of length N, holding 1's and 0's
2654 !Output Parameters:
2655  uint32 * packed_rejects array to pack the rejects in. It is
2656  assumed that there are enough 32 bit
2657  words in this variable to pack all N
2658  values in the rejects array into.
2659 
2660 !Revision History:
2661  Revision 01.00 April 1999
2662  Initial development
2663  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
2664  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
2665 
2666 !Team-unique Header:
2667  This software is developed by the MODIS Characterization Support
2668  Team (MCST)for the National Aeronautics and Space Administration,
2669  Goddard Space Flight Center, under contract NAS5-32373.
2670 
2671 !References and Credits:
2672  HDF portions developed at the National Center for Supercomputing
2673  Applications at the University of Illinois at Urbana-Champaign.
2674 
2675 !Design Notes:
2676 
2677 !END********************************************************************
2678 */
2679 {
2680  PGSt_SMF_status returnStatus = MODIS_S_OK;
2681  int32 mask;
2682  int32 nvars;
2683  int32 nrem;
2684  int32 ivar;
2685  int32 i;
2686 
2687  nvars = N / 32;
2688  nrem = N % 32;
2689 
2690  for (ivar = 0; ivar < nvars; ivar++)
2691  {
2692  mask = 1;
2693  for (i = ivar * 32; i < (ivar + 1) * 32; i++)
2694  {
2695  if (rejects[i] == 1)
2696  packed_rejects[ivar] = packed_rejects[ivar] | mask;
2697  mask *= 2;
2698  }
2699  }
2700 
2701  mask = 1;
2702  for (i = nvars * 32; i < nvars * 32 + nrem; i++)
2703  {
2704  if (rejects[i] == 1)
2705  packed_rejects[ivar] = packed_rejects[ivar] | mask;
2706  mask *= 2;
2707  }
2708 
2709  return returnStatus;
2710 }
2711 
2712 PGSt_SMF_status Process_OBCEng_Refl
2713  (int32 sd_id,
2714  int32 num_scans,
2715  float32 *T_ins,
2716  int16 *MirrorSide,
2717  refl_tables_t *refl_tables,
2718  Moon_arrays_t *moon_arrays,
2719  L1A_granule_OBCEng_t *L1A_OBCEng,
2720  DN_OBC_Avg_t *DN_OBC_Avg,
2721  QA_Refl_t *QA_refl,
2722  Preprocess_Refl_t *PP_Refl)
2723 /*
2724 !C**********************************************************************
2725 !Description:
2726  Compute the DN OBC averages for all reflective solar bands.
2727  Store in DN_OBC_Avg for writing to the OBC file and store in PP_Refl for
2728  use in reflective calibration.
2729 
2730 !Input Parameters:
2731  int32 sd_id SD file access ID for the L1A middle granule.
2732  int32 num_scans Number of scans in the middle granule.
2733  float32 *T_ins instrument temperature array
2734  int16 *MirrorSide mirror side flags
2735  refl_tables_t *refl_tables Structure which contains all reflective LUTs
2736  Moon_arrays_t *moon_arrays Structure containing the moon_in_SV_KOB array.
2737  L1A_granule_OBCEng_t *L1A_OBCEng Structure containing nir, vis, mwir
2738  adc board index.
2739 !Output Parameters:
2740  DN_OBC_Avg_t DN_OBC_Avg Structure containing arrays that will
2741  ultimately be written to the OBC file.
2742  QA_Refl_t QA_refl Depending on processing values, some
2743  elements of these may be tripped.
2744  Preprocess_Refl_t *PP_Refl Structure containing DN saturation value.
2745 
2746 !Revision History:
2747 
2748  Revision 02.01 March 25, 2002 Razor Issue #178
2749  Stripped out ADC correction.
2750  Alice Isaacman SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
2751 
2752  Revision 02.00 Sep 5, 2000
2753  Made changes for Razor issue 130. Removed Ecal_On from argument list
2754  and modified the passing of Ecal_On in argument lists of subordinate
2755  functions.
2756  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
2757 
2758  ... (many revisions not logged) ...
2759 
2760  Revision 01.03 Oct. 22, 1999
2761  Added checking for Ecal on
2762  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
2763  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
2764 
2765  Revision 01.02 Sept. 2, 1999
2766  Implemented changes to meet the requirements of the new SWIR algorithm. See SDF.
2767  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
2768  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
2769 
2770  Revision 01.01 August 1999
2771  Implemented changes to meet the requirements of the new ADC algorithm. See SDF.
2772  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
2773  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
2774 
2775  Revision 01.00 April 1999
2776  Initial development
2777  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
2778  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
2779 
2780 !Team-unique Header:
2781  This software is developed by the MODIS Characterization Support
2782  Team (MCST)for the National Aeronautics and Space Administration,
2783  Goddard Space Flight Center, under contract NAS5-32373.
2784 
2785 !References and Credits:
2786  HDF portions developed at the National Center for Supercomputing
2787  Applications at the University of Illinois at Urbana-Champaign.
2788 
2789 !Design Notes:
2790 
2791 !END********************************************************************
2792 */
2793 {
2794  PGSt_SMF_status returnStatus = MODIS_S_OK;
2795  int32 S;
2796  float32 avg;
2797 
2798  for (S = 0; S < num_scans; S++)
2799  {
2800  QA_refl->all_SV_DN_bad[S] = 0;
2801  QA_refl->all_BB_DN_bad[S] = 0;
2802  }
2803 
2804  if ((RFLAG & 1) == 0) {
2805  returnStatus = Fill_250m_DN_OBC_Avg(sd_id,
2806  num_scans,
2807  MirrorSide,
2808  refl_tables,
2809  moon_arrays,
2810  L1A_OBCEng->Ecal_On,
2811  DN_OBC_Avg,
2812  QA_refl);
2813  if (returnStatus != MODIS_S_OK)
2814  SMF_ERROR(returnStatus,
2815  "Fill_250m_DN_OBC_Avg() in Preprocess_OBCEng_Refl()");
2816  }
2817 
2818  if ((RFLAG & 2) == 0) {
2819  returnStatus = Fill_500m_DN_OBC_Avg(sd_id,
2820  num_scans,
2821  MirrorSide,
2822  refl_tables,
2823  moon_arrays,
2824  L1A_OBCEng->Ecal_On,
2825  DN_OBC_Avg,
2826  QA_refl);
2827  if (returnStatus != MODIS_S_OK)
2828  SMF_ERROR(returnStatus,
2829  "Fill_500m_DN_OBC_Avg() in Preprocess_OBCEng_Refl()");
2830  }
2831 
2832  if ((RFLAG & 4) == 0) {
2833  returnStatus = Fill_1km_day_DN_OBC_Avg(sd_id,
2834  num_scans,
2835  MirrorSide,
2836  refl_tables,
2837  moon_arrays,
2838  L1A_OBCEng->Ecal_On,
2839  DN_OBC_Avg,
2840  QA_refl);
2841  if (returnStatus != MODIS_S_OK)
2842  SMF_ERROR(returnStatus,
2843  "Fill_1km_day_DN_OBC_Avg() in Preprocess_OBCEng_Refl()");
2844  }
2845 
2846  returnStatus = Fill_Band_26_DN_OBC_Avg(sd_id,
2847  num_scans,
2848  MirrorSide,
2849  refl_tables,
2850  moon_arrays,
2851  L1A_OBCEng->Ecal_On,
2852  DN_OBC_Avg,
2853  QA_refl);
2854  if (returnStatus != MODIS_S_OK)
2855  SMF_ERROR(returnStatus,
2856  "Fill_Band_26_DN_OBC_Avg() in Preprocess_OBCEng_Refl()");
2857 
2858  returnStatus = Get_Temp_Avg_And_Variance(num_scans,
2859  T_ins,
2860  &avg,
2861  &PP_Refl->var_T_ins);
2862 
2863  return (returnStatus);
2864 }
2865 
2866 
2867 PGSt_SMF_status Cross_Granule_Sliding_Average(int32 num_overlapScans,
2868  int32 num_scans_middle,
2869  float32 *Xarray,
2870  int16 *Xmir,
2871  float32 *avg)
2872 /*
2873 !C****************************************************************************
2874 !Description:
2875  For a cross-granule array in the emissive preprocessing code, this function
2876  generates a sliding, windowed average of the input quantity. The output
2877  of the function is an averaged value at each scan of the middle granule. The
2878  window interval for averaging is twice the number of overlap scans. Only
2879  scans of the same mirror side contribute to the average at any scan of the
2880  middle granule. If the number of overlap scans is set to zero, then no
2881  averaging is accomplished. The values are simply assigned on a per-scan basis.
2882 
2883 !Input Parameters:
2884 
2885  int32 num_overlapScans Number of overlap scans the quantity being
2886  averaged.
2887  int32 num_scans_middle Number of scans in the middle granule.
2888  float32 * Xarray Cross-granule array holding data to be averaged.
2889  This should be dimensioned and organized as:
2890  [num_overlapScans + num_scans_middle
2891  + num_overlapScans].
2892  int16 * Xmir Array of mirror side flags having the same
2893  dimension and organization as Xarray.
2894 
2895 !Output Parameters:
2896 
2897  float32 * avg Array of averaged values, dimensioned
2898  [num_scans_middle].
2899 
2900 !Revision History:
2901  Revision 01.01 May, 1999
2902  Formerly "Average_Over"Scans"
2903  See SDF, "Stage 3: Changes to Emissive Algorithm and Code" notes.
2904  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
2905 
2906  Revision 01.00 Jan. 1997
2907  Initial development
2908  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
2909 
2910 !Team-unique Header:
2911  This software is developed by the MODIS Characterization Support
2912  Team (MCST)for the National Aeronautics and Space Administration,
2913  Goddard Space Flight Center, under contract NAS5-32373.
2914 
2915 !References and Credits:
2916  HDF portions developed at the National Center for Supercomputing
2917  Applications at the University of Illinois at Urbana-Champaign.
2918 
2919 !Design Notes:
2920  The quantity being averaged is assumed to be a non-negative number. Negative
2921  numbers indicate that the value was missing or bad for some reason.
2922  Similarly, the mirror side array should contain values of 0 or 1. Any other
2923  value of the mirror side implies that the data for that scan is bad.
2924 
2925 !END**************************************************************************
2926 */
2927 {
2928  PGSt_SMF_status returnStatus = MODIS_S_OK;
2929  int16 XS;
2930  int16 S;
2931  int16 n;
2932  int16 mirror_side;
2933  float32 sum;
2934 
2935  if (num_scans_middle == 0)
2937  "invalid middle granule scan numbers in "
2938  "Cross_Granule_Sliding_Average()");
2939 
2940  if (num_overlapScans == 0)
2941  {
2942  for (S = 0; S < num_scans_middle; S++)
2943  avg[S] = Xarray[S];
2944  return returnStatus;
2945  }
2946 
2947  for (S = 0; S < num_scans_middle; S++)
2948  {
2949  sum = 0;
2950  n = 0;
2951  mirror_side = Xmir[S + num_overlapScans];
2952  if (mirror_side == 0 || mirror_side == 1)
2953  {
2954  for (XS = S; XS < S + 2 * num_overlapScans + 1; XS++)
2955  {
2956  if (Xmir[XS] == mirror_side && Xarray[XS] >= 0)
2957  {
2958  sum = sum + Xarray[XS];
2959  n++;
2960  }
2961  }
2962  }
2963 
2964  if (n > 0)
2965  avg[S] = sum/n;
2966  else
2967  avg[S] = -1;
2968  }
2969 
2970  return returnStatus;
2971 }
2972 
2973 PGSt_SMF_status Granule_Average_Temperature(int32 num_values,
2974  float32 *array,
2975  float32 *avg)
2976 /*
2977 !C****************************************************************************
2978 !Description:
2979  For an array of positive temperature values, this function generates and
2980  returns the average. A value of 0 is assigned if all values of the array
2981  are bad (not positive).
2982 
2983 !Input Parameters:
2984  int32 num_values Number values of the quantity being averaged.
2985  float32 * array Array of temperatures dimension [num_values].
2986 
2987 !Output Parameters:
2988  float32 * avg Average value is assigned to this address.
2989 
2990 !Revision History:
2991  Revision 01.02 May, 1999, Initial Development
2992  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
2993 
2994 !Team-unique Header:
2995  This software is developed by the MODIS Characterization Support
2996  Team (MCST)for the National Aeronautics and Space Administration,
2997  Goddard Space Flight Center, under contract NAS5-32373.
2998 
2999 !References and Credits:
3000  HDF portions developed at the National Center for Supercomputing
3001  Applications at the University of Illinois at Urbana-Champaign.
3002 
3003 !Design Notes:
3004  The quantity being averaged is assumed to be a non-negative number. Negative
3005  numbers indicate that the value was missing or bad for some reason.
3006 
3007 !END**************************************************************************
3008 */
3009 {
3010  PGSt_SMF_status returnStatus = MODIS_S_OK;
3011  int32 n;
3012  float32 sum;
3013  int32 i;
3014 
3015  if (num_values == 0 || array == NULL || avg == NULL)
3017  "invalid argument in Granule_Average_Temperature()");
3018 
3019  sum = 0;
3020  n = 0;
3021  for (i = 0; i < num_values; i++)
3022  {
3023  if (array[i] > 0)
3024  {
3025  sum = sum + array[i];
3026  n++;
3027  }
3028  }
3029 
3030  if (n > 0)
3031  *avg = sum/n;
3032  else
3033  *avg = 0.0;
3034 
3035  return returnStatus;
3036 }
3037 
3038 PGSt_SMF_status Get_Temp_Avg_And_Variance(int32 N,
3039  float32 *T,
3040  float32 *avg,
3041  float32 *var)
3042 /*
3043 !C****************************************************************************
3044 !Description:
3045  Given a set of engineering temperatures, calculate the mean and variance
3046  over all input values. Bad temperatures (flagged as being less than or
3047  equal to zero) are excluded. If all values become excluded, the mean
3048  and variance are set to -1, implying bad values. If all but one value
3049  is excluded, then the mean is set to the remaining value and the variance
3050  is set to -1.
3051 
3052 !Input Parameters:
3053  int32 N number of value in array T
3054  float32 * T array of temperatures
3055 
3056 !Output Parameters:
3057  float32 * avg mean of the values
3058  float32 * var variance of the values
3059 
3060 !Revision History:
3061  Revision 01.00 April 1999
3062  Initial development
3063  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
3064  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
3065 
3066 !Team-unique Header:
3067  This software is developed by the MODIS Characterization Support
3068  Team (MCST)for the National Aeronautics and Space Administration,
3069  Goddard Space Flight Center, under contract NAS5-32373.
3070 
3071 !References and Credits:
3072  HDF portions developed at the National Center for Supercomputing
3073  Applications at the University of Illinois at Urbana-Champaign.
3074 
3075 !Design Notes:
3076 
3077 !END********************************************************************
3078 */
3079 {
3080  PGSt_SMF_status returnStatus = MODIS_S_OK;
3081  int32 i, n;
3082  double sum1;
3083  double sum2;
3084 
3085  if (N <= 0 || !T || !var || !avg)
3086  return (MODIS_F_NOK);
3087 
3088  *avg = -1;
3089  *var = -1;
3090  sum1 = 0;
3091  sum2 = 0;
3092  n = 0;
3093  for (i = 0; i < N; i++)
3094  {
3095  if (T[i] > 0)
3096  {
3097  sum1 += (double) T[i];
3098  sum2 += (double) T[i] * (double) T[i];
3099  n++;
3100  }
3101  }
3102 
3103  if (n == 0)
3104  return returnStatus;
3105 
3106  else if (n == 1)
3107  {
3108  *avg = (float32) sum1;
3109  return returnStatus;
3110  }
3111 
3112  *avg = (float32) (sum1 / ((double) n));
3113  *var = (float32) ( (sum2 - sum1 * sum1 / ((double) n)) /
3114  ((double) (n - 1)) );
3115  return returnStatus;
3116 }
3117 
3118 
3119 PGSt_SMF_status Fill_Invalid_Temp_DNs(int32 num_scans,
3120  uint16 miss_DN,
3121  uint16 sat_DN,
3122  uint16 *DN)
3123 /*
3124 !C****************************************************************************
3125 !Description:
3126  For a set of engineering temperatures, check for missing or saturated values
3127  and if found, then assign the nearest valid value. The only way that any
3128  elements in the array DN do not leave this routine assigned to a valid value
3129  is if none of the values in the array were valid.
3130 
3131 !Input Parameters:
3132  int32 num_scans Number of DN values in the array DN
3133  uint16 miss_DN Value representing the missing DN value
3134  uint16 sat_DN Value representing the saturated DN value
3135  uint16 *DN Array of DN values
3136 
3137 !Output Parameters:
3138  uint16 *DN DN values with invalid values filled in.
3139 
3140 
3141 !Revision History:
3142  Revision 01.00 April 1999
3143  Initial development
3144  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
3145  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
3146 
3147 !Team-unique Header:
3148  This software is developed by the MODIS Science Data Support
3149  Team for the National Aeronautics and Space Administration,
3150  Goddard Space Flight Center, under contract NAS5-32373.
3151 
3152 !References and Credits:
3153  HDF portions developed at the National Center for Supercomputing
3154  Applications at the University of Illinois at Urbana-Champaign.
3155 
3156 !Design Notes:
3157 
3158 !END********************************************************************
3159 */
3160 {
3161  PGSt_SMF_status returnStatus = MODIS_S_OK;
3162  int32 last_good_index, next_good_index, i, j, found;
3163 
3164  if (num_scans <= 0 || !DN)
3165  {
3167  "Fill_Invalid_Temp_DNs, Preprocess.c");
3168  }
3169 
3170  last_good_index = num_scans;
3171  next_good_index = -1;
3172  for (i = 0; i < num_scans; ) /* do not automatically increment i */
3173  {
3174  if (DN[i] != miss_DN && DN[i] != sat_DN)
3175  {
3176  last_good_index = i;
3177  next_good_index = i;
3178  i++;
3179  }
3180  else if (next_good_index > i && last_good_index < i)
3181  {
3182 
3183  /* assign closest one */
3184 
3185  if ((next_good_index - i) < (i - last_good_index))
3186  DN[i] = DN[next_good_index];
3187  else
3188  DN[i] = DN[last_good_index];
3189  i++;
3190  }
3191  else if (next_good_index > i)
3192  {
3193 
3194  /* assign next_good_index value */
3195 
3196  DN[i] = DN[next_good_index];
3197  i++;
3198  }
3199  else /* find the next valid one */
3200  {
3201  for (found = 0, j = i+1; j < num_scans; j++)
3202  {
3203  if (DN[j] != miss_DN && DN[j] != sat_DN)
3204  {
3205  next_good_index = j;
3206  found = 1;
3207  break;
3208  }
3209  }
3210  if (found == 0) /* assign the rest, then return */
3211  {
3212  if (last_good_index < i)
3213  {
3214  for (j = i; j < num_scans; j++)
3215  DN[j] = DN[last_good_index];
3216  }
3217  return returnStatus;
3218  }
3219  }
3220  }
3221  return returnStatus;
3222 }
3223 
3224 PGSt_SMF_status Get_Electronics_index(int32 num_scans,
3225  uint16 *Electronics_pri,
3226  uint16 *Electronics_red,
3227  uint16 *Electronics_index)
3228 
3229 /*
3230 !C**************************************************************************
3231 !Description: This function determines whether electronics side "A" or "B"
3232  of a system was used on each scan over a set of scans. See
3233  design notes.
3234 !Input Parameters:
3235  int32 num_scans Number of scans defining the dimensions of
3236  the input and output arrays(could be all the
3237  scans for a granule or a portion of the scans
3238  of the granule)
3239  uint16 * Electronics_pri the array hold the telemetry values for the
3240  primary electronics
3241  uint16 * Electronics_red the array hold the telemetry values for the
3242  redundant electronics
3243 
3244 !Output Parameters:
3245  uint16 * Electronics_index array with each entry indicating an
3246  electronics is primary (side "A") or
3247  redundant (side "B") in each scan
3248 
3249 !Revision History:
3250  Revision 01.00 Aug 1999
3251  Initial development
3252  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
3253 
3254 !Team-unique Header:
3255  This software is developed by the MODIS Science Data Support
3256  Team for the National Aeronautics and Space Administration,
3257  Goddard Space Flight Center, under contract NAS5-32373.
3258 
3259 !References and Credits:
3260  HDF portions developed at the National Center for Supercomputing
3261  Applications at the University of Illinois at Urbana-Champaign.
3262 
3263 !Design Notes:
3264 
3265 !END********************************************************************
3266 */
3267 {
3268  PGSt_SMF_status returnStatus = MODIS_S_OK;
3269  int16 S = 0;
3270  int16 S2 = 0;
3271  int16 valid_set_found = 0;
3272 
3273  for (S = 0; S < num_scans; S++)
3274  {
3275  if ( Electronics_pri[S] == ON && Electronics_red[S] == OFF )
3276  Electronics_index[S] = ELECTRONICS_PRIMARY;
3277 
3278  else if ( Electronics_pri[S] == OFF && Electronics_red[S] == ON )
3279  Electronics_index[S] = ELECTRONICS_REDUNDANT;
3280 
3281  else if (Electronics_pri [S] == OFF && Electronics_red[S] == OFF )
3282  {
3283  /* missing eng data --> use another scan's Primary/Redundant flag values.
3284 
3285  Search for a valid Electronics Primary/Redundant flag set to use.
3286  It is highly unlikely the electronics side will have changed in
3287  any given granule, so this is not a bad work around.
3288  */
3289 
3290  valid_set_found = 0;
3291 
3292  for (S2 = 0; S2 < num_scans; S2++)
3293  {
3294  if ( Electronics_pri[S2] == ON && Electronics_red[S2] == OFF )
3295  {
3296  Electronics_index[S] = ELECTRONICS_PRIMARY;
3297  valid_set_found = 1;
3298  break; /* usable flag values found, break out of loop */
3299  }
3300  else if ( Electronics_pri[S2] == OFF &&
3301  Electronics_red[S2] == ON )
3302  {
3303  Electronics_index[S] = ELECTRONICS_REDUNDANT;
3304  valid_set_found = 1;
3305  break; /* usable flag values found, break out of loop */
3306  }
3307 
3308  } /* next S2 */
3309 
3310  if ( !valid_set_found )
3311  /* no usable ELECTRONICS Primary/Redundant flag data in the big
3312  chunk of whole granule looked at! */
3313  return (MODIS_F_NOK);
3314  }
3315  else /* unexpected (both Primary and Redundant are 1) --
3316  should never occur */
3317  return (MODIS_F_NOK);
3318 
3319 
3320  }/*Loop over scan*/
3321 
3322  return (returnStatus);
3323 
3324 }
3325 
3326 PGSt_SMF_status Get_Electronics_index_special(int32 num_scans,
3327  uint16 *Electronics_pri,
3328  uint16 *Electronics_red,
3329  uint16 *Electronics_index)
3330 
3331 /*
3332 !C**************************************************************************
3333 !Description: This function is similar to the function Get_Electronics_index,
3334  except that it also handle the case of both sides A and B on
3335  for PCLW, which is permissible according to the design notes.
3336 
3337 !Input Parameters:
3338  int32 num_scans Number of scans defining the dimensions of
3339  the input and output arrays(could be all the
3340  scans for a granule or a portion of the scans
3341  of the granule)
3342  uint16 * Electronics_pri the array hold the telemetry values for the
3343  primary electronics
3344  uint16 * Electronics_red the array hold the telemetry values for the
3345  redundant electronics
3346 
3347 !Output Parameters:
3348  uint16 * Electronics_index array with each entry indicating an
3349  electronics is primary (side "A") or
3350  redundant (side "B") in each scan
3351 
3352 !Revision History:
3353 
3354 !Team-unique Header:
3355  This software is developed by the MCST L1B Team for the
3356  National Aeronautics and Space Administration,
3357  Goddard Space Flight Center.
3358 
3359 !References and Credits:
3360  HDF portions developed at the National Center for Supercomputing
3361  Applications at the University of Illinois at Urbana-Champaign.
3362 
3363 !Design Notes:
3364 
3365 !END********************************************************************
3366 */
3367 {
3368  PGSt_SMF_status returnStatus = MODIS_S_OK;
3369  int16 S = 0;
3370  int16 S2 = 0;
3371  int16 valid_set_found = 0;
3372 
3373  for (S = 0; S < num_scans; S++)
3374  {
3375  if ( Electronics_pri[S] == ON && Electronics_red[S] == OFF )
3376  Electronics_index[S] = ELECTRONICS_PRIMARY;
3377 
3378  else if ( Electronics_pri[S] == OFF && Electronics_red[S] == ON )
3379  Electronics_index[S] = ELECTRONICS_REDUNDANT;
3380 
3381  else if ( Electronics_pri[S] == ON && Electronics_red[S] == ON )
3382  Electronics_index[S] = ELECTRONICS_BOTH;
3383 
3384  else
3385  {
3386  /* missing eng data --> use another scan's Primary/Redundant flag values.
3387 
3388  Search for a valid Electronics Primary/Redundant flag set to use.
3389  It is highly unlikely the electronics side will have changed in
3390  any given granule, so this is not a bad work around.
3391  */
3392 
3393  valid_set_found = 0;
3394 
3395  for (S2 = 0; S2 < num_scans; S2++)
3396  {
3397  if ( Electronics_pri[S2] == ON && Electronics_red[S2] == OFF )
3398  {
3399  Electronics_index[S] = ELECTRONICS_PRIMARY;
3400  valid_set_found = 1;
3401  break; /* usable flag values found, break out of loop */
3402  }
3403  else if ( Electronics_pri[S2] == OFF &&
3404  Electronics_red[S2] == ON )
3405  {
3406  Electronics_index[S] = ELECTRONICS_REDUNDANT;
3407  valid_set_found = 1;
3408  break; /* usable flag values found, break out of loop */
3409  }
3410 
3411  } /* next S2 */
3412 
3413  if ( !valid_set_found )
3414  /* no usable ELECTRONICS Primary/Redundant flag data in the big
3415  chunk of whole granule looked at! */
3416  return (MODIS_F_NOK);
3417 
3418  }
3419 
3420  }/*Loop over scan*/
3421 
3422  return (returnStatus);
3423 
3424 }
3425 
3426 PGSt_SMF_status Read_L1A_OBCEng (emiss_tables_t *emiss_tables,
3427  L1A_granule_t *L1A_Gran,
3428  L1A_granule_OBCEng_t *L1A_OBCEng)
3429 /*
3430 !C****************************************************************************
3431 !Description: This function reads BB, SV and temperature DNs and converts the
3432  temperature DNs into engineering units.
3433 
3434 !Input Parameters:
3435  L1A_granule_t * L1A_Gran Contains SD file interface ID, Vdata
3436  file interface ID, number of scans and
3437  mirror side for every scan.
3438 
3439 !Output Parameters:
3440  L1A_granule_OBCEng_t * L1A_OBCEng Contains BB and SV DNs, number of scans
3441  in the granule, mirror side flags and
3442  engineering temperatures.
3443 
3444 !Revision History:
3445  Revision 01.05 January 4, 2002 Razor Issue #154
3446  Added satellite_ID to parameters fed to Read_Convert_Temperatures.
3447  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
3448 
3449  Revision 01.04 November 22, 1999
3450  Added calls to L1BErrorMsg.
3451  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
3452 
3453  Revision 01.03 August, 1999
3454  Added checking if the data read from L1A are valid.
3455  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
3456 
3457  Revision 01.02 May, 1999
3458  See SDF, "Stage 3: Changes to Emissive Algorithm and Code" notes.
3459  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
3460 
3461  Revision 01.01 Feb, 1999
3462  Added read of Number of Day mode scans, EV start time and Scan Type here
3463  to consolidate read of all members of L1A_Gran in one place and avoid
3464  reading the same data more than once.
3465  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
3466 
3467  Revision 01.00 Jan. 1997
3468  Initial development
3469  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
3470 
3471 !Team-unique Header:
3472  This software is developed by the MODIS Characterization Support
3473  Team (MCST)for the National Aeronautics and Space Administration,
3474  Goddard Space Flight Center, under contract NAS5-32373.
3475 
3476 !References and Credits:
3477  HDF portions developed at the National Center for Supercomputing
3478  Applications at the University of Illinois at Urbana-Champaign.
3479 
3480 !Design Notes:
3481 
3482 !END**************************************************************************
3483 */
3484 {
3485  PGSt_SMF_status returnStatus = MODIS_S_OK;
3486  int32 S;
3487  int32 track_dim;
3488  int32 count;
3489  int32 satellite_ID = INVALID_SATELLITE_ID;
3490  /* 0 = TERRA (PFM); 1 = AQUA (FM1) */
3491  char *location = "Read_L1A_OBCEng";
3492 
3493  /* Determine the satellite platform. */
3494  satellite_ID = L1A_Gran->satellite_id;
3495  /*
3496  * Assign Engineering coefficients depending on whether instrument
3497  * is Terra (PFM) or Aqua (FM1).
3498  * Check the platform name. Currently, the allowed name for Terra is "AM-1"
3499  * and possibly "Terra", and the allowed name for Aqua could be "PM-1" or
3500  * "Aqua".
3501  */
3502 
3503  if (satellite_ID != TERRA && satellite_ID != AQUA)
3504  { returnStatus = MODIS_F_OUT_OF_RANGE;
3505  L1BErrorMsg(location, returnStatus,
3506  "*** Satellite ID is incorrect ***\n"
3507  "Satellite platform must be Terra or Aqua.",
3509  NULL, True);
3510  return returnStatus;
3511  }
3512 
3513 
3514  /*
3515  * Assign number of scans and mirror side to the OBCEng structure for use
3516  * within the preprocess module.
3517  */
3518 
3519  L1A_OBCEng->num_scans = L1A_Gran->num_scans;
3520  for (S = 0; S < L1A_OBCEng->num_scans; S++)
3521  L1A_OBCEng->MirrorSide[S] = L1A_Gran->MirrorSide[S];
3522 
3523  /*
3524  * Compute the track dimension of sector DN SDSs based on actual
3525  * number of scans.
3526  */
3527 
3528  track_dim =
3530 
3531  /*
3532  * Read black-body sector DNs
3533  */
3534 
3535  returnStatus = read_sds_rank3(L1A_Gran->sd_id,
3536  "BB_1km_night",
3537  track_dim,
3539  BB_1km_FRAMES,
3540  (void *)L1A_OBCEng->BB_1km_night);
3541  if ( returnStatus != MODIS_S_OK)
3542  {
3543  L1BErrorMsg(location, returnStatus,
3544  "Could not read BB_1km_night.",
3545  "read_sds_rank3", FIRST_L1A_GRANULE,
3547  return returnStatus;
3548  }
3549 
3550  /*
3551  * Check valid range on black-body sector DNs
3552  */
3553 
3554  count = track_dim * NUM_1000M_NIGHT_BANDS * BB_1km_FRAMES;
3555  returnStatus = Check_Valid_Range("BB_1km_night",
3556  DFNT_INT16,
3557  L1A_DN_SDS_LB,
3558  L1A_DN_SDS_UB,
3559  L1A_DN_SDS_FV,
3560  count,
3561  L1A_OBCEng->BB_1km_night);
3562  if (returnStatus != MODIS_S_OK)
3563  {
3564  L1BErrorMsg(location, returnStatus, NULL, "Check_Valid_Range",
3566  return returnStatus;
3567  }
3568 
3569  /*
3570  * Read space-view sector DNs
3571  */
3572 
3573  returnStatus = read_sds_rank3(L1A_Gran->sd_id,
3574  "SV_1km_night",
3575  track_dim,
3577  SV_1km_FRAMES,
3578  (void *)L1A_OBCEng->SV_1km_night);
3579  if ( returnStatus != MODIS_S_OK)
3580  {
3581  L1BErrorMsg(location, returnStatus,
3582  "Could not read SV_1km_night.",
3583  "read_sds_rank3",
3586  True);
3587  return returnStatus;
3588  }
3589 
3590  /*
3591  * Check valid range on space-view sector DNs
3592  */
3593 
3594  count = track_dim * NUM_1000M_NIGHT_BANDS * SV_1km_FRAMES;
3595  returnStatus = Check_Valid_Range("SV_1km_night",
3596  DFNT_INT16,
3597  L1A_DN_SDS_LB,
3598  L1A_DN_SDS_UB,
3599  L1A_DN_SDS_FV,
3600  count,
3601  L1A_OBCEng->SV_1km_night);
3602  if (returnStatus != MODIS_S_OK)
3603  {
3604  L1BErrorMsg(location, returnStatus, NULL, "Check_Valid_Range",
3606  return returnStatus;
3607  }
3608 
3609  /*
3610  * Determine the scan-by-scan flags Ecal_On for this granule.
3611  */
3612 
3613  returnStatus = Check_For_Ecal_On(FIRST_L1A_GRANULE,
3614  L1A_Gran->num_scans,
3615  L1A_Gran->v_id,
3616  L1A_OBCEng->Ecal_On);
3617  if (returnStatus != MODIS_S_OK)
3618  {
3619  L1BErrorMsg(location, returnStatus, NULL,
3620  "Check_For_Ecal_On", FIRST_L1A_GRANULE, NULL, True);
3621  return returnStatus;
3622  }
3623 
3624  /*
3625  * Determine the scan-by-scan flags Sector_Rotated for this granule.
3626  */
3627 
3629  L1A_Gran->num_scans,
3630  L1A_Gran->v_id,
3631  L1A_OBCEng->Sector_Rotated);
3632  if (returnStatus != MODIS_S_OK)
3633  {
3634  L1BErrorMsg(location, returnStatus, NULL,
3635  "Check_If_Sector_Rotated", FIRST_L1A_GRANULE, NULL, True);
3636  return returnStatus;
3637  }
3638 
3639 
3640  /*
3641  * Read temperature DNs and convert them into engineering units
3642  */
3643 
3644  returnStatus = Read_Convert_Temperatures (emiss_tables,
3645  L1A_Gran->v_id,
3646  0,
3647  L1A_Gran->num_scans,
3648  satellite_ID,
3649  &L1A_OBCEng->temps);
3650  if (returnStatus != MODIS_S_OK)
3651  {
3652  L1BErrorMsg(location, returnStatus, NULL,
3653  "Read_Convert_Temperatures", FIRST_L1A_GRANULE, NULL, True);
3654  return returnStatus;
3655  }
3656 
3657  return returnStatus;
3658 }
3659 
3660 PGSt_SMF_status Read_Overlap_OBCEng (L1A_granule_t *L1A_Gran,
3661  emiss_tables_t *emiss_tables,
3662  PGSt_PC_Logical lun,
3663  Overlap_OBCEng_t *Overlap_OBCEng,
3664  boolean *scan_gap)
3665 
3666 /*
3667 !C****************************************************************************
3668 !Description:
3669  This function reads data needed for emissive calibration preprocessing
3670  from a subset of the total number of scans from the leading or trailing
3671  L1A granule. These data include the black-body digital numbers (DNs),
3672  space-view DNs, mirror side flags and engineering temperatures. For the
3673  leading granule, we read a set of scans at the end of the granule. For the
3674  trailing granule, we read a set of scans at the start of the granule.
3675 
3676 !Input Parameters:
3677  L1A_granule_t *L1A_Gran Contains the satellite id
3678  emiss_tables_t *emiss_tables Contains the number of overlap scans for
3679  processing of b1 and T BB and for other
3680  temperatures (2 different values).
3681  int32 satellite_ID 0 = TERRA, 1 = AQUA, -1 = INVALID_SATELLITE_ID
3682  PGSt_PC_Logical lun Logical unit number, must be for leading
3683  or trailing L1A granules only.
3684 
3685 !Output Parameters:
3686  Overlap_OBCEng_t *Overlap_OBCEng Contains BB and SV DNs, number of scans
3687  in the granule, mirror side flags and
3688  engineering temperatures.
3689  boolean *scan_gap Indicates gap of a few scans
3690  between granules.
3691 
3692 !Revision History:
3693 
3694  Revision 01.13 March 2003, Razor Issue #173
3695  Initialized variables "time_to_first_finish", "first_valid_second_time",
3696  and "time_from_second_start" to 0.0 for ANSI-C compliance.
3697  Liqin Tan, SAIC GSO (ltan@saicmodis.com)
3698 
3699  Revision 01.12 April 16, 2002 Razor Issue #166
3700  Refined time check on leading/trailing granules to allow processing but
3701  print a warning message if a small gap of a few scans between granules
3702  exists.
3703  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
3704 
3705  Revision 01.11 January 4, 2002 (Razor Issue #154)
3706  Passed satellite_ID to Read_Convert_Temperatures.
3707  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
3708 
3709  Revision 01.1 November 5, 2001 (Razor Issue #166)
3710  Added a check on time of leading and trailing granules.
3711  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
3712 
3713  Revision 01.00 November 3, 1999
3714  Initial Development -- combination of two functions: Read_LeadingOverlap
3715  and Read_TrailingOverlap
3716  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
3717 
3718 !Team-unique Header:
3719  This software is developed by the MODIS Characterization Support
3720  Team (MCST)for the National Aeronautics and Space Administration,
3721  Goddard Space Flight Center, under contract NAS5-32373.
3722 
3723 !References and Credits:
3724  The previous functions (Read_LeadingOverlap Read_TrailingOverlap) were
3725  substantially developed by Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and
3726  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
3727 
3728  HDF portions developed at the National Center for Supercomputing
3729  Applications at the University of Illinois at Urbana-Champaign.
3730 
3731 !Design Notes:
3732  The macro ALLOW_MISSING_GRANULES is used as a switch to allow the code to
3733  process if a granule is determined to be missing or if all data are missing
3734  from the granule. If the production rules change to allow this, then
3735  define this macro to turn on the capability.
3736 
3737  The use of "return" statements after the L1BErrorMsg (with a "True" for the
3738  error-out argument) is to allow easier testing of all paths in unit testing.
3739  Generally, if the error-out flag is True, we do not need the extra return.
3740  This assumes that a non-OK return status is fatal, which is the case for
3741  L1B.
3742 
3743  Regardless of the existence of the macro ALLOW_MISSING_GRANULES, there are
3744  some instances where the granule will be treated as missing and processing
3745  will continue:
3746  a) The number of scans in the MOD01 granule is zero (empty granule)
3747  b) The number of scans in the MOD01 granule exceeds MAX_NUM_SCANS
3748  c) All telemetry data for key telemetries (in Read_Convert_Temperatures)
3749  is missing or invalid.
3750  d) The leading/trailing MOD01 granule does not immediately precede/follow
3751  the middle granule in time (respectively).
3752 
3753  The value of Overlap_OBCEng->num_scans = 0 upon return from this function
3754  means that the rest of the program will treat this granule as MISSING.
3755 
3756 !END**************************************************************************
3757 */
3758 {
3759  PGSt_SMF_status returnStatus = MODIS_S_OK;
3760  intn hdf_return = FAIL;
3761  PGSt_integer Version = 1;
3762  char file_name[PGSd_PC_FILE_PATH_MAX];
3763  int32 file_id = FAIL;
3764  int32 v_id = FAIL;
3765  int32 num_scans = 0;
3766  int16 T = 0; /*Target index*/
3767  int16 R = 0; /*Resolution index*/
3768  int16 S = 0; /*Scan index*/
3769  int32 track_dim = 0;
3770  int32 start0 = 0; /* values used in read_part_sds routines*/
3771  int32 start1 = 0;
3772  int32 start2 = 0;
3773  int32 num_overlap_scans_b1 = 0;
3774  int16 track; /* track index */
3775  int16 band; /* band index */
3776  int16 frame; /* frame index */
3777  int16 j; /* minor loop index */
3778  int32 satellite_ID = INVALID_SATELLITE_ID;
3779  /* 0 = TERRA (PFM); 1 = AQUA (FM1) */
3780 
3781  /* start times (to determine data collection time */
3782  float64 EVStartTime_TAIsecond[MAX_NUM_SCANS];
3783 
3784  /*
3785  * Last valid time of leading/middle (if LEADING/TRAILING resp.)
3786  * granule
3787  */
3788  float64 last_valid_first_time;
3789 
3790  /*
3791  * time interval from last_valide_first_time to end of
3792  * leading/middle (if LEADING/TRAILING resp.) granule
3793  */
3794  float64 time_to_first_finish = 0.0;
3795 
3796  /*
3797  * first valid time of mid/trailing (if LEADING/TRAILING resp.)
3798  * granule
3799  */
3800  float64 first_valid_second_time = 0.0;
3801 
3802  /*
3803  * time interval from start of mid/trailing
3804  * (if LEADING/TRAILING resp.) granule
3805  */
3806  float64 time_from_second_start = 0.0;
3807 
3808  /*
3809  * Time difference between granules based on times of valid scans and
3810  * estimate of time difference between first and second granules based
3811  * on scan numbersof valid times, respectively
3812  */
3813  float64 time_difference, estimated_time_difference;
3814 
3815  char *location = "Read_Overlap_OBCEng";
3816  int32 count;
3817 
3818  /* Leading/Trailing granule indicator, determined by LUN */
3819  boolean leading = FALSE;
3820  boolean trailing = FALSE;
3821 
3822  char *leading_missing_granule_msg = "\
3823 The leading MOD01 granule will be treated as missing.\n\
3824 The resulting L1B output will be valid if no other errors occur.";
3825 
3826  char *trailing_missing_granule_msg = "\
3827 The trailing MOD01 granule will be treated as missing.\n\
3828 The resulting L1B output will be valid if no other errors occur.";
3829 
3830 #ifdef ALLOW_MISSING_GRANULES
3831 
3832  char *leading_granule_time_msg = "\
3833 The leading MOD01 granule has an undefined data collection time or a\n\
3834 data collection time which does not synchronize with the middle\n\
3835 granule data collection time and will be treated as missing. \n\
3836 The resulting L1B output will be valid if no other errors occur.";
3837 
3838  char *trailing_granule_time_msg = "\
3839 The trailing MOD01 granule has an undefined data collection time or a\n\
3840 data collection time which does not synchronize with the middle\n\
3841 granule data collection time and will be treated as missing. \n\
3842 The resulting L1B output will be valid if no other errors occur.";
3843 
3844 #endif /* ALLOW_MISSING_GRANULES */
3845 
3846  char *leading_dropped_scan_msg = "\
3847 At least one and no more than";
3848 
3849  char *leading_dropped_scan_msg_end = "\n\
3850 scans were dropped between the leading and middle granules. \n\
3851 The resulting L1B output will be valid if no other errors occur.";
3852 
3853  char *trailing_dropped_scan_msg = "\
3854 At least one and no more than";
3855 
3856  char *trailing_dropped_scan_msg_end = "\n\
3857 scans were dropped between the middle and trailing granules. \n\
3858 The resulting L1B output will be valid if no other errors occur.";
3859 
3860  /*
3861  * Check input arguments. The LUN should correspond to leading or trailing
3862  * L1A granule only.
3863  */
3864 
3865  if (!(lun == LEADING_L1A_GRANULE || lun == TRAILING_L1A_GRANULE)) {
3866  returnStatus = MODIS_F_INVALID_ARGUMENT;
3867  L1BErrorMsg(location, returnStatus,
3868  "LUN is invalid. Must be for previous or "
3869  "following MOD01 granule only",
3870  NULL, lun, NULL, True);
3871  }
3872 
3873  if (lun == LEADING_L1A_GRANULE) leading = TRUE;
3874  if (lun == TRAILING_L1A_GRANULE) trailing = TRUE;
3875 
3876  /*
3877  * Initialize members of the OBCEng structure to fill values.
3878  * The most important of these is num_scans. num_scans = 0 implies that
3879  * the granule is missing.
3880  */
3881 
3882  Overlap_OBCEng->num_scans = 0;
3883  for (track = 0; track < MAX_OVERLAP_TRACK_DIM; track++)
3884  for (band = 0; band < NUM_1000M_NIGHT_BANDS; band++)
3885  for (frame = 0; frame < BB_1km_FRAMES; frame++)
3886  Overlap_OBCEng->BB_1km_night[track][band][frame] =
3888  for (track = 0; track < MAX_OVERLAP_TRACK_DIM; track++)
3889  for (band = 0; band < NUM_1000M_NIGHT_BANDS; band++)
3890  for (frame = 0; frame < SV_1km_FRAMES; frame++)
3891  Overlap_OBCEng->SV_1km_night[track][band][frame] =
3893  for (S = 0; S < MAX_NUM_SCANS; S++)
3894  {
3895  Overlap_OBCEng->MirrorSide[S] = -1;
3896  for (j = 0; j < NUM_FOCAL_PLANES; j++)
3897  Overlap_OBCEng->temps.fp[j][S] = 0;
3898  Overlap_OBCEng->temps.mir1[S] = 0;
3899  Overlap_OBCEng->temps.mir2[S] = 0;
3900  Overlap_OBCEng->temps.mir_avg[S] = 0;
3901  Overlap_OBCEng->temps.cav[S] = 0;
3902  Overlap_OBCEng->temps.ins[S] = 0;
3903  for (j = 0; j < NUM_BB_THERMISTORS; j++)
3904  Overlap_OBCEng->temps.bb[j][S] = 0;
3905  Overlap_OBCEng->temps.bb_avg[S] = 0;
3906  Overlap_OBCEng->temps.fp_set_point_state[S] = 0;
3907  Overlap_OBCEng->temps.lwir_adc_index[S] = 0;
3908  Overlap_OBCEng->temps.mwir_adc_index[S] = 0;
3909  Overlap_OBCEng->temps.nir_adc_index[S] = 0;
3910  Overlap_OBCEng->temps.vis_adc_index[S] = 0;
3911  Overlap_OBCEng->temps.pclw_adc_index[S] = 0;
3912  Overlap_OBCEng->temps.num_thermistor_outliers[S] = 0;
3913  }
3914 
3915  /*
3916  * Prepare for opening file: convert logical ID to physical name
3917  */
3918 
3919  returnStatus = PGS_PC_GetReference (lun, &Version, file_name);
3920 #ifdef ALLOW_MISSING_GRANULES
3921  if (returnStatus != PGS_S_SUCCESS)
3922  { /* allow continued processing */
3923  returnStatus = MODIS_S_OK;
3924  if (leading) L1BErrorMsg(location, returnStatus,
3925  "WARNING: Could not retrieve leading granule file name from PCF.",
3926  "PGS_PC_GetReference", lun, leading_missing_granule_msg, False);
3927  if (trailing) L1BErrorMsg(location, returnStatus,
3928  "WARNING: Could not retrieve trailing granule file name from PCF.",
3929  "PGS_PC_GetReference", lun, trailing_missing_granule_msg, False);
3930  return returnStatus;
3931  }
3932 #else
3933  if (returnStatus != PGS_S_SUCCESS)
3934  {
3935  returnStatus = MODIS_F_FILE_NOT_FOUND;
3936  if (leading) L1BErrorMsg(location, returnStatus,
3937  "Could not retrieve leading granule file name from PCF.",
3938  "PGS_PC_GetReference", lun, NULL, True);
3939  if (trailing) L1BErrorMsg(location, returnStatus,
3940  "Could not retrieve trailing granule file name from PCF.",
3941  "PGS_PC_GetReference", lun, NULL, True);
3942  return returnStatus;
3943  }
3944 #endif /* ALLOW_MISSING_GRANULES */
3945 
3946  /*
3947  * Open file for HDF science data (SD) access.
3948  */
3949 
3950  file_id = SDstart(file_name, DFACC_RDONLY);
3951 #ifdef ALLOW_MISSING_GRANULES
3952  if (file_id == FAIL)
3953  { /* allow continued processing */
3954  returnStatus = MODIS_S_OK;
3955  if (leading) L1BErrorMsg(location, returnStatus,
3956  "WARNING: Could not open leading granule file for SD read access.",
3957  "SDstart", lun, leading_missing_granule_msg, False);
3958  if (trailing) L1BErrorMsg(location, returnStatus,
3959  "WARNING: Could not open trailing granule file for SD read access.",
3960  "SDstart", lun, trailing_missing_granule_msg, False);
3961  return returnStatus;
3962  }
3963 #else
3964  if (file_id == FAIL)
3965  {
3966  returnStatus = MODIS_F_FILE_NOT_OPENED;
3967  if (leading) L1BErrorMsg(location, returnStatus,
3968  "Could not open leading granule file for SD read access.",
3969  "SDstart", lun,
3970  "The file may be missing, corrupted or not an HDF-4 file.", True);
3971  if (trailing) L1BErrorMsg(location, returnStatus,
3972  "Could not open trailing granule file for SD read access.",
3973  "SDstart", lun,
3974  "The file may be missing, corrupted or not an HDF-4 file.", True);
3975  return returnStatus;
3976  }
3977 #endif /* ALLOW_MISSING_GRANULES */
3978 
3979  /*
3980  * Determine the satellite instrument is from the leading or trailing granule
3981  * and check if it matches that determined from the middle granule.
3982  */
3983 
3984  returnStatus = Get_Satellite_ID(lun, &satellite_ID);
3985  if (returnStatus != MODIS_S_OK)
3986  {
3987  if (leading) L1BErrorMsg(location, returnStatus,
3988  "Failed to get satellite id from leading granule.",
3989  "Get_Satellite_ID", lun,
3990  "The leading granule is invalid.", True);
3991  if (trailing) L1BErrorMsg(location, returnStatus,
3992  "Failed to get satellite id from trailing granule.",
3993  "Get_Satellite_ID", lun,
3994  "The trailing granule is invalid.", True);
3995  return returnStatus;
3996  }
3997 
3998  if (satellite_ID != L1A_Gran->satellite_id)
3999  {
4000  returnStatus = MODIS_F_NOK;
4001  if (leading) L1BErrorMsg(location, returnStatus,
4002  "The satellite instrument name in the leading granule\n"
4003  "does not match that in the middle granule.",
4004  NULL, lun, NULL, True);
4005  if (trailing) L1BErrorMsg(location, returnStatus,
4006  "The satellite instrument name in the trailing granule\n"
4007  "does not match that in the middle granule.",
4008  NULL, lun, NULL, True);
4009  return returnStatus;
4010  }
4011 
4012  /*
4013  * Open file for HDF Vdata access and initialize Vdata interface.
4014  * Call Hopen() and Vstart() in the same place. Here, do not allow
4015  * processing with a missing granule since we were able to open the
4016  * file using SDstart. If we cannot open it with Hopen and Vstart, then
4017  * the file must be bad and we should terminate.
4018  */
4019 
4020  v_id = Hopen(file_name,DFACC_RDONLY,0);
4021  if (v_id == FAIL)
4022  {
4023  SDend (file_id);
4024  returnStatus = MODIS_F_FILE_NOT_OPENED;
4025  if (leading) L1BErrorMsg(location, returnStatus,
4026  "Could not open leading granule file for Vdata read access.",
4027  "Hopen", lun,
4028  "The file may be corrupted or not an HDF-4 file.", True);
4029  if (trailing) L1BErrorMsg(location, returnStatus,
4030  "Could not open trailing granule file for Vdata read access.",
4031  "Hopen", lun,
4032  "The file may be corrupted or not an HDF-4 file.", True);
4033  return returnStatus;
4034  }
4035  hdf_return = Vstart (v_id);
4036  if (hdf_return == FAIL)
4037  {
4038  SDend (file_id); Hclose (v_id);
4039  returnStatus = MODIS_F_HDF_ERROR;
4040  if (leading) L1BErrorMsg(location, returnStatus,
4041  "Could not initialize Vdata interface for leading granule file.",
4042  "Vstart", lun,
4043  "The file may be corrupted or not an HDF-4 file.", True);
4044  if (trailing) L1BErrorMsg(location, returnStatus,
4045  "Could not initialize Vdata interface for trailing granule file.",
4046  "Vstart", lun,
4047  "The file may be corrupted or not an HDF-4 file.", True);
4048  return returnStatus;
4049  }
4050 
4051  /*
4052  * Read & check num_scans. If the number of scans is zero, assume that the
4053  * L1A granule is valid, but empty. Treat it as a missing granule.
4054  * Other errors (except time errors) will cause error out.
4055  */
4056 
4057  returnStatus = read_attribute (file_id, "Number of Scans",
4058  DFNT_INT32, (void *)&num_scans);
4059  if (returnStatus != MODIS_S_OK)
4060  {
4061  if (leading)
4062  L1BErrorMsg(location, returnStatus,
4063  "Could not read Number of Scans from leading granule file.",
4064  "read_attribute", lun, Invalid_MOD01_Msg, True);
4065  if (trailing)
4066  L1BErrorMsg(location, returnStatus,
4067  "Could not read Number of Scans from trailing granule file.",
4068  "read_attribute", lun, Invalid_MOD01_Msg, True);
4069  return returnStatus;
4070  }
4071 
4072  if (num_scans == 0)
4073  { /* allow continued processing */
4074  returnStatus = MODIS_S_OK;
4075  if (leading)
4076  L1BErrorMsg(location, returnStatus,
4077  "WARNING: Number of scans in leading granule is zero.",
4078  NULL, lun, leading_missing_granule_msg, False);
4079  if (trailing)
4080  L1BErrorMsg(location, returnStatus,
4081  "WARNING: Number of scans in trailing granule is zero.",
4082  NULL, lun, trailing_missing_granule_msg, False);
4083  goto Read_Overlap_OBCEng_exit; /* close accesses and files. */
4084  }
4085 
4086  if (num_scans < 0)
4087  {
4088  returnStatus = MODIS_F_OUT_OF_RANGE;
4089  if (leading) L1BErrorMsg(location, returnStatus,
4090  "Number of Scans in the leading granule is negative.",
4091  NULL, lun, Invalid_MOD01_Msg, True);
4092  if (trailing) L1BErrorMsg(location, returnStatus,
4093  "Number of Scans in the trailing granule is negative.",
4094  NULL, lun, Invalid_MOD01_Msg, True);
4095  return returnStatus;
4096  }
4097 
4098  if (num_scans > MAX_NUM_SCANS)
4099  { /* allow continued processing */
4100  returnStatus = MODIS_S_OK;
4101  if (leading)
4102  L1BErrorMsg(location, returnStatus,
4103  "WARNING: Number of scans in leading granule is > MAX_NUM_SCANS.",
4104  NULL, lun, leading_missing_granule_msg, False);
4105  if (trailing)
4106  L1BErrorMsg(location, returnStatus,
4107  "WARNING: Number of scans in trailing granule is > MAX_NUM_SCANS.",
4108  NULL, lun, trailing_missing_granule_msg, False);
4109  goto Read_Overlap_OBCEng_exit; /* close accesses and files. */
4110  }
4111 
4112  /*
4113  * Assign num_scans now because it is a valid number.
4114  */
4115 
4116  Overlap_OBCEng->num_scans = num_scans;
4117 
4118  /*
4119  * Check to see if number of overlap scans is zero. If so, then there is
4120  * nothing to read from the file (no data will be used). Go to function
4121  * exit point, close up files and continue processing.
4122  */
4123 
4124  num_overlap_scans_b1 = emiss_tables->num_overlap_scans_b1;
4125  if (num_overlap_scans_b1 == 0)
4126  {
4127  returnStatus = MODIS_S_OK;
4128  goto Read_Overlap_OBCEng_exit;
4129  }
4130 
4131  /*
4132  * Check number of scans against the emissive LUTs
4133  */
4134 
4135  if (num_scans < num_overlap_scans_b1)
4136  {
4137  returnStatus = MODIS_F_NOK;
4138  if (leading)
4139  L1BErrorMsg(location, returnStatus,
4140  "Number of Scans in the leading granule "
4141  "less than number of overlap scans b1.",
4142  NULL, lun,
4143  "There are not enough scans in the leading MOD01 granule to allow\n"
4144  "processing with the current L1B emissive algorithm.", True);
4145  if (trailing)
4146  L1BErrorMsg(location, returnStatus,
4147  "Number of Scans in the trailing granule "
4148  "less than number of overlap scans b1.",
4149  NULL, lun,
4150  "There are not enough scans in the trailing MOD01 granule to allow\n"
4151  "processing with the current L1B emissive algorithm.", True);
4152  return returnStatus;
4153  }
4154 
4155  /*
4156  * Check the LUT values against the dimension macros. These checks are
4157  * independent of which granule it is.
4158  */
4159 
4160  if (num_overlap_scans_b1 > MAX_NUM_OVERLAP_SCANS)
4161  {
4162  returnStatus = MODIS_F_NOK;
4163  if (leading)
4164  L1BErrorMsg(location, returnStatus,
4165  "num_overlap_scans_b1 in the leading granule is greater than \n"
4166  "macro MAX_NUM_OVERLAP_SCANS.",
4167  NULL, 0,
4168  "The L1B code macro must be increased or the LUT value reduced.",
4169  True);
4170  if (trailing)
4171  L1BErrorMsg(location, returnStatus,
4172  "num_overlap_scans_b1 in the trailing granule is greater than \n"
4173  "macro MAX_NUM_OVERLAP_SCANS.",
4174  NULL, 0,
4175  "The L1B code macro must be increased or the LUT value reduced.",
4176  True);
4177  return returnStatus;
4178  }
4179 
4180  /* Read the scan times to check against the leading/trailing positions. */
4181 
4182  returnStatus = read_sds_rank1 (file_id, "EV start time",
4183  num_scans, (void *)EVStartTime_TAIsecond);
4184  if (returnStatus != MODIS_S_OK)
4185  {
4186  if (leading) L1BErrorMsg(location, returnStatus,
4187  "Could not read EV start time for the leading granule.",
4188  "read_sds_rank1", lun, Invalid_MOD01_Msg, True);
4189  if (trailing) L1BErrorMsg(location, returnStatus,
4190  "Could not read EV start time for the trailing granule.",
4191  "read_sds_rank1", lun, Invalid_MOD01_Msg, True);
4192  return returnStatus;
4193  }
4194 
4195  last_valid_first_time = 0;
4196  first_valid_second_time = 0;
4197 
4198  if (leading)
4199  /*
4200  * Determine the times of the first valid scan of the middle granule and
4201  * the last valid scan of the leading granule.
4202  */
4203  {
4204 
4205  for (S = num_scans - 1; S >= 0; S--) /* Count backwards for last time */
4206  {
4207  if (EVStartTime_TAIsecond[S] > 0)
4208  {
4209  last_valid_first_time = EVStartTime_TAIsecond[S];
4210  time_to_first_finish =
4211  SCAN_TIME_INTERVAL*((float64) (num_scans - .5 - S));
4212  break;
4213  }
4214  }
4215 
4216  for (S = 0; S < L1A_Gran->num_scans; S++)
4217  {
4218  if (L1A_Gran->EVStartTime_TAIsecond[S] > 0)
4219  {
4220  first_valid_second_time = L1A_Gran->EVStartTime_TAIsecond[S];
4221  time_from_second_start =
4222  SCAN_TIME_INTERVAL*((float64) (.5 + S));
4223  break;
4224  }
4225  }
4226  }
4227 
4228  if (trailing)
4229  /*
4230  * Determine the times of the first valid scan of the trailing granule and
4231  * the last valid scan of the middle granule.
4232  */
4233  {
4234  for (S = L1A_Gran->num_scans - 1; S >= 0; S--)
4235  {
4236  if (L1A_Gran->EVStartTime_TAIsecond[S] > 0)
4237  {
4238  last_valid_first_time = L1A_Gran->EVStartTime_TAIsecond[S];
4239  time_to_first_finish =
4240  SCAN_TIME_INTERVAL*((float64) (L1A_Gran->num_scans - .5 - S));
4241  break;
4242  }
4243  }
4244 
4245  for (S = 0; S < num_scans; S++)
4246  {
4247  if (EVStartTime_TAIsecond[S] > 0)
4248  {
4249  first_valid_second_time = EVStartTime_TAIsecond[S];
4250  time_from_second_start =
4251  SCAN_TIME_INTERVAL*((float64) (.5 + S));
4252  break;
4253  }
4254  }
4255  }
4256 
4257  /*
4258  * In the following explanation, "first" and "second" granule
4259  * refer to the leading and middle granule respectively if the
4260  * LEADING granule is being read, and to the middle and trailing
4261  * granule respectively if the TRAILING granule is being read.
4262  *
4263  * The first valid scan of the second granule must have a time
4264  * after that of the last valid time of the first granule. The
4265  * time difference between the last valid time of the first
4266  * granule and the first valid time of the second granule should
4267  * be approximately the same as the time difference estimated from
4268  * the scan numbers of the last valid scan of the first granule
4269  * and the first valid scan of the second granule. If the time
4270  * difference is not acceptable (less than 0 or greater than a set
4271  * number of scans) then set the number of scans to 0
4272  * so that the data will be treated as missing, or stop with an
4273  * error if D_ALLOW_MISSING_GRANULES is false. If the time difference
4274  * indicates at least one scan was dropped, continue with a warning message
4275  * and set a new bit qa flag.
4276  */
4277 
4278  time_difference = first_valid_second_time - last_valid_first_time;
4279  estimated_time_difference =
4280  time_to_first_finish + time_from_second_start;
4281 
4282  /*
4283  * If the time difference is more than 1 scan but less than the upper
4284  * allowed number of scans, print a warning message but allow the
4285  * granule to be used for calibration purposes. Set a qa flag bit.
4286  */
4287 
4288  if ((time_difference >= 0.) &&
4289  (fabs(estimated_time_difference - time_difference) >=
4291  (fabs(estimated_time_difference - time_difference) <=
4293  {
4294 
4295  *scan_gap = True;
4296 
4297  if (leading)
4298  {
4299  char dropped_scan_msg[256];
4300  sprintf (dropped_scan_msg, "%s %d %s", leading_dropped_scan_msg,
4301  DROPPED_SCAN_UPPER_LIMIT, leading_dropped_scan_msg_end);
4302 
4303  L1BErrorMsg(location, returnStatus,
4304  "WARNING: the leading granule does not immediately precede \n"
4305  "the middle granule.",
4306  NULL, lun, dropped_scan_msg, False);
4307  }
4308  if (trailing)
4309  {
4310  char dropped_scan_msg[256];
4311  sprintf (dropped_scan_msg, "%s %d %s", trailing_dropped_scan_msg,
4312  DROPPED_SCAN_UPPER_LIMIT, trailing_dropped_scan_msg_end);
4313  L1BErrorMsg(location, returnStatus,
4314  "WARNING: the trailing granule does not immediately follow \n"
4315  "the middle granule.",
4316  NULL, lun, dropped_scan_msg, False);
4317  }
4318  }
4319 
4320  /*
4321  * Otherwise check to see whether there is a significant time
4322  * discrepancy and do not use the leading/trailing granule if so.
4323  */
4324 
4325  else
4326  {
4327  if ((time_difference < 0.) ||
4328  (fabs(estimated_time_difference - time_difference) >=
4330 #ifdef ALLOW_MISSING_GRANULES
4331  { /* allow continued processing */
4332 
4333  Overlap_OBCEng->num_scans = 0; /* flag this granule as missing */
4334  returnStatus = MODIS_S_OK;
4335  if (leading)
4336  L1BErrorMsg(location, returnStatus,
4337  "WARNING: the leading granule does not immediately precede \n"
4338  "the middle granule.",
4339  NULL, lun, leading_granule_time_msg, False);
4340  if (trailing)
4341  L1BErrorMsg(location, returnStatus,
4342  "WARNING: the trailing granule does not immediately follow \n"
4343  "the middle granule.",
4344  NULL, lun, trailing_granule_time_msg, False);
4345 
4346  goto Read_Overlap_OBCEng_exit; /* close accesses and files. */
4347 
4348  }
4349 #else
4350  { /* do not allow continued processing */
4351 
4352  Overlap_OBCEng->num_scans = 0; /* flag this granule as missing */
4353  returnStatus = MODIS_F_NOK;
4354  if (leading) L1BErrorMsg(location, returnStatus,
4355  "The leading granule does not immediately precede \n"
4356  "the middle granule.",
4357  NULL, lun, NULL, True);
4358  if (trailing) L1BErrorMsg(location, returnStatus,
4359  "The trailing granule does not immediately follow \n"
4360  "the middle granule.",
4361  NULL, lun, NULL, True);
4362 
4363  goto Read_Overlap_OBCEng_exit; /* close accesses and files. */
4364  }
4365 #endif /* ALLOW_MISSING_GRANULES */
4366  }
4367 
4368  /*
4369  * Read the sector DN data for BB and SV for the 1km Emissive bands. We
4370  * only need to read these if the number of overlap scans for b1 is > 0.
4371  * The value of overlap scans for b1 could be zero and yet the value of
4372  * overlap scans for tempes is non-zero (we have already checked to see
4373  * if both are zero).
4374  */
4375 
4376  if (num_overlap_scans_b1 > 0)
4377  {
4378  R = INDEX_1000M_EMISS;
4379  if (leading)
4380  start0 = (num_scans - num_overlap_scans_b1) *
4382  else
4383  start0 = 0;
4384 
4385  track_dim = num_overlap_scans_b1 * DETECT_PER_BAND_AT_RES[R];
4386 
4387  /*
4388  * Read BB data and check that values are not out of bounds.
4389  */
4390 
4391  T = BB_INDEX;
4392  returnStatus = read_part_sds_rank3 (file_id,
4393  L1A_TARGET_SDS_NAME[T][R],
4394  start0,
4395  start1,
4396  start2,
4397  track_dim,
4399  BB_1km_FRAMES,
4400  Overlap_OBCEng->BB_1km_night);
4401  if (returnStatus != MODIS_S_OK)
4402  {
4403  L1BErrorMsg(location, returnStatus, NULL,
4404  "read_part_sds_rank3", lun, NULL, True);
4405  return returnStatus;
4406  }
4407  count = track_dim * NUM_1000M_NIGHT_BANDS * BB_1km_FRAMES;
4408  returnStatus = Check_Valid_Range(L1A_TARGET_SDS_NAME[T][R],
4409  DFNT_INT16,
4410  L1A_DN_SDS_LB,
4411  L1A_DN_SDS_UB,
4412  L1A_DN_SDS_FV,
4413  count,
4414  Overlap_OBCEng->BB_1km_night);
4415  if (returnStatus != MODIS_S_OK)
4416  {
4417  L1BErrorMsg(location, returnStatus, NULL,
4418  "Check_Valid_Range", lun, NULL, True);
4419  return returnStatus;
4420  }
4421 
4422  /*
4423  * Read SV data and check that values are not out of bounds.
4424  */
4425 
4426  T = SV_INDEX;
4427  returnStatus = read_part_sds_rank3 (file_id,
4428  L1A_TARGET_SDS_NAME[T][R],
4429  start0,
4430  start1,
4431  start2,
4432  track_dim,
4434  SV_1km_FRAMES,
4435  Overlap_OBCEng->SV_1km_night);
4436  if (returnStatus != MODIS_S_OK)
4437  {
4438  L1BErrorMsg(location, returnStatus, NULL,
4439  "read_part_sds_rank3", lun, NULL, False);
4440  return returnStatus;
4441  }
4442  count = track_dim * NUM_1000M_NIGHT_BANDS * SV_1km_FRAMES;
4443  returnStatus = Check_Valid_Range(L1A_TARGET_SDS_NAME[T][R],
4444  DFNT_INT16,
4445  L1A_DN_SDS_LB,
4446  L1A_DN_SDS_UB,
4447  L1A_DN_SDS_FV,
4448  count,
4449  Overlap_OBCEng->SV_1km_night);
4450  if (returnStatus != MODIS_S_OK)
4451  {
4452  L1BErrorMsg(location, returnStatus, NULL,
4453  "Check_Valid_Range", lun, NULL, True);
4454  return returnStatus;
4455  }
4456 
4457  } /* end of if (num_overlap_scans_b1 > 0) */
4458 
4459  /*
4460  * Read and check MirrorSide array.
4461  */
4462 
4463  returnStatus = read_sds_rank1(file_id,
4464  "Mirror side",
4465  Overlap_OBCEng->num_scans,
4466  Overlap_OBCEng->MirrorSide);
4467  if (returnStatus != MODIS_S_OK)
4468  {
4469  L1BErrorMsg(location, returnStatus, NULL,
4470  "read_sds_rank1", lun, NULL, True);
4471  return returnStatus;
4472  }
4473  returnStatus = Check_Valid_Range("Mirror side",
4474  DFNT_INT16,
4475  "-1",
4476  "1",
4477  NULL,
4478  Overlap_OBCEng->num_scans,
4479  Overlap_OBCEng->MirrorSide);
4480  if (returnStatus != MODIS_S_OK)
4481  {
4482  L1BErrorMsg(location, returnStatus, NULL, "Check_Valid_Range",
4483  lun, NULL, True);
4484  return returnStatus;
4485  }
4486 
4487  /*
4488  * Determine the scan-by-scan flags Ecal_On for this granule.
4489  */
4490 
4491  returnStatus = Check_For_Ecal_On(lun,
4492  Overlap_OBCEng->num_scans,
4493  v_id,
4494  Overlap_OBCEng->Ecal_On);
4495  if (returnStatus != MODIS_S_OK)
4496  {
4497  L1BErrorMsg(location, returnStatus, NULL,
4498  "Check_For_Ecal_On", lun, NULL, True);
4499  return returnStatus;
4500  }
4501 
4502  /*
4503  * Determine the scan-by-scan flags Sector_Rotated for this granule.
4504  */
4505 
4506  returnStatus = Check_If_Sector_Rotated(lun,
4507  Overlap_OBCEng->num_scans,
4508  v_id,
4509  Overlap_OBCEng->Sector_Rotated);
4510  if (returnStatus != MODIS_S_OK)
4511  {
4512  L1BErrorMsg(location, returnStatus, NULL,
4513  "Check_If_Sector_Rotated", lun, NULL, True);
4514  return returnStatus;
4515  }
4516 
4517 
4518  /*
4519  * Read engineering telemetry data (temperatures, ADC indexes, etc.)
4520  * and convert those that are temperatures into physical units.
4521  */
4522 
4523  if (lun == LEADING_L1A_GRANULE)
4524  start0 = num_scans - num_overlap_scans_b1;
4525  else
4526  start0 = 0;
4527  returnStatus = Read_Convert_Temperatures (emiss_tables,
4528  v_id,
4529  start0,
4530  num_overlap_scans_b1,
4531  satellite_ID,
4532  &Overlap_OBCEng->temps);
4533 
4534 
4535  /*
4536  * Error code logic: If the return status is MODIS_F_OUT_OF_RANGE,
4537  * terminate execution because there is something seriously wrong with the
4538  * granule. Otherwise, assume that telemetry was missing and simply proceed
4539  * as if the granule were missing.
4540  */
4541 
4542 
4543  if (returnStatus == MODIS_F_OUT_OF_RANGE)
4544  {
4545  L1BErrorMsg(location, returnStatus, NULL,
4546  "Read_Convert_Temperatures", lun, NULL, True);
4547  return returnStatus;
4548  }
4549  else if (returnStatus != MODIS_S_OK)
4550  { /* allow continued processing */
4551  Overlap_OBCEng->num_scans = 0; /* flag this granule as missing */
4552  returnStatus = MODIS_S_OK;
4553  if (leading)
4554  L1BErrorMsg(location, returnStatus,
4555  "WARNING: the leading granule cannot be used "
4556  "(possible missing telemetry).",
4557  "Read_Convert_Temperatures", lun,
4558  leading_missing_granule_msg, False);
4559  if (trailing)
4560  L1BErrorMsg(location, returnStatus,
4561  "WARNING: the trailing granule cannot be used "
4562  "(possible missing telemetry).",
4563  "Read_Convert_Temperatures", lun,
4564  trailing_missing_granule_msg, False);
4565  goto Read_Overlap_OBCEng_exit; /* close accesses and files. */
4566  }
4567 
4568  /*
4569  * Successfully completed exit code:
4570  */
4571 
4572  returnStatus = MODIS_S_OK;
4573 
4574  /*
4575  * Function exit point.
4576  */
4577 
4578 Read_Overlap_OBCEng_exit:
4579 
4580  /*
4581  * Close file and all accesses.
4582  */
4583 
4584  if (v_id != FAIL)
4585  {
4586  hdf_return = Vend(v_id);
4587  if (hdf_return == FAIL)
4588  {
4589  L1BErrorMsg(location, MODIS_F_HDF_ERROR, NULL, "Vend", lun,
4590  "Memory or the disk file must have become corrupted.", True);
4591  }
4592  hdf_return = Hclose(v_id);
4593  if (hdf_return == FAIL)
4594  {
4595  L1BErrorMsg(location, MODIS_F_HDF_ERROR, NULL, "Hclose", lun,
4596  "Memory or the disk file must have become corrupted.", True);
4597  }
4598  }
4599  if (file_id != FAIL)
4600  {
4601  if (SDend(file_id) == FAIL)
4602  {
4603  L1BErrorMsg(location, MODIS_F_HDF_ERROR, NULL, "SDend", lun,
4604  "Memory or the disk file must have become corrupted.", True);
4605  }
4606  }
4607  return returnStatus;
4608 }
4609 
4611  int32 v_id,
4612  int32 start_scan,
4613  int32 num_scans,
4614  int32 satellite_ID,
4615  Temperatures_t *temps)
4616 /*
4617 !C**************************************************************************
4618 !Description: Read engineering temperature DNs and convert them into
4619  temperatures in physical units.
4620 
4621 !Input Parameters:
4622  int32 v_id file id for vdata interfaces
4623  int32 start_scan starting scan to read
4624  int32 num_scans number of scans to read
4625  int32 satellite_ID TERRA = 0, AQUA = 1, INVALID_SATELLITE_ID = -1
4626 
4627 !Output Parameters:
4628  Temperatures_t *temps
4629 
4630 !Revision History:
4631  Revision 02.18 March 2003, Razor Issue #173
4632  Enclosed the rows in the initializers of array-of-struct "temp" with braces,
4633  and changed the type of variables "FP_SPS" and "thermistor" from "int8" to
4634  "int16" for ANSI-C compliance.
4635  Liqin Tan, SAIC GSO (ltan@saicmodis.com)
4636 
4637  Revision 02.17 January 4, 2002 (Razor Issue #154)
4638  Added input variable satellite_ID and passed it to Compute_BB_Temperature.
4639  Added structure Eng_Coeffs determined by satellite ID and used it for
4640  conversion coefficients. Moved computation of CPA/CPB index to this module.
4641 
4642  Revision 02.16 October 24, 2000
4643  Added code for granule average QA values as per issue 140.
4644  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
4645 
4646  ... (many changes not logged) ...
4647 
4648  Revision 02.15 November 22, 1999
4649  Added calls to L1BErrorMsg. Changed logic of immediately error-out
4650  to instead simply write error message and return to parent (so that
4651  parent can identify LUN of file).
4652  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
4653 
4654  Revision 02.14 August 28, 1999
4655  Added checking if the data read from L1A are valid.
4656  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
4657 
4658  Revision 02.13 August, 1999
4659  Implemented changes to meet the requirements of the new ADC algorithm. See SDF.
4660  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
4661  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
4662 
4663  Revision 02.12 May, 1999
4664  Implemented changes described in SDF.
4665  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
4666 
4667  Revision 02.11 Oct 26 1998
4668  put the BB temperature part into function "Compute_BB_Temperature"
4669  and put the adc index part into function "Get_ADC_Index"
4670  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
4671 
4672  Revision 02.10 Apr 20 1998
4673  Change "TA_RC_SWIR_CFPAE" back to "TA_RC_SMIR_CFPAE",
4674  and TP_AO_SWIR_OBJ to TP_AO_SMIR_OBJ.
4675  That's the way it is in the L1A file.
4676  David Catozzi (cato@ltpmail)
4677 
4678  Revision 02.10 Mar 1998
4679  Change "TA_RC_SMIR_CFPAE" to "TA_RC_SWIR_CFPAE",
4680  Add new temperatures for the V2.1 TEB algorithm
4681  Implement the 1/ln algorithm for T_BB
4682  Shi-Yue Qiu (syqiu@ltpmail.gsfc.nasa.gov)
4683 
4684  Revision 01.00 Aug 1997
4685  Initial development
4686  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
4687 
4688 !Team-unique Header:
4689  This software is developed by the MODIS Science Data Support
4690  Team for the National Aeronautics and Space Administration,
4691  Goddard Space Flight Center, under contract NAS5-32373.
4692 
4693 !References and Credits:
4694  HDF portions developed at the National Center for Supercomputing
4695  Applications at the University of Illinois at Urbana-Champaign.
4696 
4697 !Design Notes:
4698 
4699  If an error occurs in this function, write the error message and then
4700  return to the parent (so that the parent can identify the LUN of
4701  the file).
4702 
4703 !END********************************************************************
4704 */
4705 {
4706  char *location = "Read_Convert_Temperatures";
4707  PGSt_SMF_status returnStatus = MODIS_S_OK;
4708  enum {
4709  FP_T1SET,
4710  FP_T3SET,
4711  LWHTR_ON,
4712  SMHTR_ON,
4713  FP1,
4714  FP2,
4715  FP3,
4716  FP4,
4717  MIR1,
4718  MIR2,
4719  SCN_MTR,
4720  CAV1,
4721  CAV2,
4722  CAV3,
4723  CAV4,
4724  ADC_LWIR,
4725  ADC_MWIR,
4726  INS1,
4727  INS2,
4728  INS3,
4729  INS4,
4730  CPA,
4731  CPB,
4732  BB1,
4733  BB2,
4734  BB3,
4735  BB4,
4736  BB5,
4737  BB6,
4738  BB7,
4739  BB8,
4740  BB9,
4741  BB10,
4742  BB11,
4743  BB12,
4744  LWIR_ADC_PRI,
4745  LWIR_ADC_RED,
4746  MWIR_ADC_PRI,
4747  MWIR_ADC_RED,
4748  NIR_ADC_PRI,
4749  NIR_ADC_RED,
4750  VIS_ADC_PRI,
4751  VIS_ADC_RED,
4752  PCLW_ADC_PRI,
4753  PCLW_ADC_RED,
4754  RC1,
4755  RC2,
4756  RC3,
4757  RC4,
4758  RC5,
4759  VR_RC_LW_FPA,
4760  NUM_TEMPS
4761  } i;
4762 
4763  struct {
4764  char *vname; /*vdata_name*/
4765  char *fname; /*field_name*/
4766  uint16 buffer[MAX_NUM_SCANS]; /*data buffer; all eng_vdata are type of uint16*/
4767  uint16 max_valid_value;
4768  } temp[NUM_TEMPS] = {
4769  {"Telemetry Major Cycle 5A of 7" , "CR_RC_CFPA_T1SET", {0}, 1 }, /* FP_T1SET */
4770  {"Telemetry Major Cycle 5A of 7" , "CR_RC_CFPA_T3SET", {0}, 1 }, /* FP_T3SET */
4771  {"Telemetry Major Cycle 5A of 7" , "CR_RC_LWHTR_ON" , {0}, 1 }, /* LWHTR_ON */
4772  {"Telemetry Major Cycle 5A of 7" , "CR_RC_SMHTR_ON" , {0}, 1 }, /* SMHTR_ON */
4773  {"Engineering Temperature data" , "TA_AO_VIS_FPAE" , {0}, 4095}, /* FP1 */
4774  {"Engineering Temperature data" , "TA_AO_NIR_FPAE" , {0}, 4095}, /* FP2 */
4775  {"Engineering Temperature data" , "TA_RC_SMIR_CFPAE", {0}, 4095}, /* FP3 */
4776  {"Engineering Temperature data" , "TA_RC_LWIR_CFPAE", {0}, 4095}, /* FP4 */
4777  {"Engineering Temperature data" , "TP_SA_RCT1_MIRE" , {0}, 4095}, /* MIR1 */
4778  {"Engineering Temperature data" , "TP_SA_RCT2_MIRE" , {0}, 4095}, /* MIR2 */
4779  {"Telemetry Major Cycle 20 of 63", "TP_SA_A_MTR" , {0}, 511 }, /* SCN_MTR */
4780  {"Telemetry Major Cycle 3 of 63" , "TP_MF_CALBKHD_SR", {0}, 511 }, /* CAV1 */
4781  {"Telemetry Major Cycle 23 of 63", "TP_SR_SNOUT" , {0}, 511 }, /* CAV2 */
4782  {"Telemetry Major Cycle 4 of 63" , "TP_MF_Z_BKHD_BB" , {0}, 511 }, /* CAV3 */
4783  {"Telemetry Major Cycle 3 of 63" , "TP_MF_CVR_OP_SR" , {0}, 511 }, /* CAV4 */
4784  {"Telemetry Major Cycle 14 of 63", "TA_PVLW_PWB4_10" , {0}, 511 }, /* ADC_LWIR */
4785  {"Telemetry Major Cycle 14 of 63", "TA_PVSM_PWB6_12" , {0}, 511 }, /* ADC_MWIR */
4786  {"Telemetry Major Cycle 0 of 63" , "TP_AO_SMIR_OBJ" , {0}, 4095}, /* INS1 */
4787  {"Telemetry Major Cycle 0 of 63" , "TP_AO_LWIR_OBJ" , {0}, 4095}, /* INS2 */
4788  {"Telemetry Major Cycle 0 of 63" , "TP_AO_SMIR_LENS" , {0}, 4095}, /* INS3 */
4789  {"Telemetry Major Cycle 0 of 63" , "TP_AO_LWIR_LENS" , {0}, 4095}, /* INS4 */
4790  {"Telemetry Major Cycle 1 of 7" , "CR_CP_A_ON_M" , {0}, 1 }, /* CPA A on (1553 telemetry) */
4791  {"Telemetry Major Cycle 1 of 7" , "CR_CP_B_ON_M" , {0}, 1 }, /* CPB B on (1553 telemetry) */
4792  {"Engineering BB data" , "TP_BB_TEMP01" , {0}, 4095}, /* BB1 */
4793  {"Engineering BB data" , "TP_BB_TEMP02" , {0}, 4095}, /* BB2 */
4794  {"Engineering BB data" , "TP_BB_TEMP03" , {0}, 4095}, /* BB3 */
4795  {"Engineering BB data" , "TP_BB_TEMP04" , {0}, 4095}, /* BB4 */
4796  {"Engineering BB data" , "TP_BB_TEMP05" , {0}, 4095}, /* BB5 */
4797  {"Engineering BB data" , "TP_BB_TEMP06" , {0}, 4095}, /* BB6 */
4798  {"Engineering BB data" , "TP_BB_TEMP07" , {0}, 4095}, /* BB7 */
4799  {"Engineering BB data" , "TP_BB_TEMP08" , {0}, 4095}, /* BB8 */
4800  {"Engineering BB data" , "TP_BB_TEMP09" , {0}, 4095}, /* BB9 */
4801  {"Engineering BB data" , "TP_BB_TEMP10" , {0}, 4095}, /* BB10 */
4802  {"Engineering BB data" , "TP_BB_TEMP11" , {0}, 4095}, /* BB11 */
4803  {"Engineering BB data" , "TP_BB_TEMP12" , {0}, 4095}, /* BB12 */
4804  {"Telemetry Major Cycle 4A of 7" , "CR_PVLW_A_ON" , {0}, 1 }, /* LWIR_PRI_ADC A on */
4805  {"Telemetry Major Cycle 4A of 7" , "CR_PVLW_B_ON" , {0}, 1 }, /* LWIR_RED_ADC B on */
4806  {"Telemetry Major Cycle 4B of 7" , "CR_PVSM_A_ON" , {0}, 1 }, /* MWIR_PRI_ADC A on */
4807  {"Telemetry Major Cycle 4B of 7" , "CR_PVSM_B_ON" , {0}, 1 }, /* MWIR_RED_ADC B on */
4808  {"Telemetry Major Cycle 4B of 7" , "CR_PVNIR_A_ON" , {0}, 1 }, /* NIR_PRI_ADC A on */
4809  {"Telemetry Major Cycle 4B of 7" , "CR_PVNIR_B_ON" , {0}, 1 }, /* NIR_RED_ADC B on */
4810  {"Telemetry Major Cycle 4B of 7" , "CR_PVVIS_A_ON" , {0}, 1 }, /* VIS_PRI_ADC A on */
4811  {"Telemetry Major Cycle 4B of 7" , "CR_PVVIS_B_ON" , {0}, 1 }, /* VIS_RED_ADC B on */
4812  {"Telemetry Major Cycle 4A of 7" , "CR_PCLW_A_ON" , {0}, 1 }, /* PCLW_PRI_ADC A on */
4813  {"Telemetry Major Cycle 4A of 7" , "CR_PCLW_B_ON" , {0}, 1 }, /* PCLW_RED_ADC B on */
4814  {"Telemetry Major Cycle 18 of 63", "TA_RC_CS" , {0}, 4095}, /* RC1 */
4815  {"Telemetry Major Cycle 18 of 63", "TA_RC_CS_OG" , {0}, 4095}, /* RC2 */
4816  {"Telemetry Major Cycle 19 of 63", "TA_RC_IS" , {0}, 4095}, /* RC3 */
4817  {"Telemetry Major Cycle 19 of 63", "TA_RC_IS_OG" , {0}, 4095}, /* RC4 */
4818  {"Telemetry Major Cycle 19 of 63", "TA_RC_OS_OG" , {0}, 4095}, /* RC5 */
4819  {"Telemetry Major Cycle 30 of 63", "VR_RC_LW_FPA_HTR", {0}, 1023} /* VR_RC_LW_FPA */
4820  };
4821 
4822  int16 FP_SPS = 0; /*FP Set Point State; temporary value*/
4823  int16 thermistor;
4824  uint16 *BB_temp[NUM_BB_THERMISTORS];
4825  int16 S = 0; /*scan_index*/
4826  int16 XS = 0;
4827 
4828  float32 tcavsum;
4829  int32 j, ncav;
4830  uint16 CP_index[MAX_NUM_SCANS];
4831  float32 *C_CAV;
4832  float32 *C_INS;
4833  float32 *C_MIR;
4834  Engineering_Coefficients_t Eng_Coeffs;
4835 
4836  int32 vd_id;
4837 
4838 /********* Macro: CONVERT_TEMP_POLY(tdk,tdn,c,dnsat,toffset) *************/
4839 /* This macro converts the temperature DN using the 5th order polynomial
4840  * coefficients appropriate to the DN being converted. It also checks for
4841  * invalid DN (zero or saturated). If invalid, nothing is assigned to the
4842  * variable being computed (remains at its initialized state).
4843  * tdk = temperature in degrees (Kelvin)
4844  * tdn = temperature digital number
4845  * c = polynomial coefficients
4846  * dnsat = saturation DN for this temperature DN
4847  * toffset = offset in degrees to add to converted temperature.
4848  * (this may be required to convert from Celsius to Kelvin)
4849  */
4850 #define CONVERT_TEMP_POLY(tdk,tdn,c,dnsat,toffset) \
4851  if (tdn > 0 && tdn < dnsat) tdk = toffset + \
4852  c[0] + tdn * (c[1] + tdn * (c[2] + tdn * (c[3] + tdn * (c[4] + tdn * c[5]))));
4853 
4854 /***************************************************************************/
4855 
4856 
4857  /* Use different sets of engineering coefficients for
4858  * Terra (PFM) and Aqua (FM1)
4859  */
4860 
4861  if (satellite_ID == TERRA) /* Satellite is Terra */
4862  Eng_Coeffs = Engineering_Coefficients_PFM;
4863  else /* Satellite is Aqua */
4864  Eng_Coeffs = Engineering_Coefficients_FM1;
4865 
4866  /* Initialize structure members */
4867 
4868  for (S = 0; S < MAX_NUM_SCANS; S++)
4869  {
4870  for (j = 0; j < NUM_FOCAL_PLANES; j++)temps->fp[j][S] = 0;
4871  temps->mir1[S] = 0;
4872  temps->mir2[S] = 0;
4873  temps->mir_avg[S] = 0;
4874  temps->scn_mtr[S] = 0;
4875  temps->cav[S] = 0;
4876  temps->ins[S] = temps->bb_avg[S] = 0;
4877  for (j = 0; j < NUM_BB_THERMISTORS; j++)temps->bb[j][S] = 0;
4878  temps->fp_set_point_state[S] = 0;
4879  temps->lwir_adc_index[S] = 0;
4880  temps->mwir_adc_index[S] = 0;
4881  for (j = 0; j < NUM_T_CAV_THERMISTORS; j++) temps->cav_temp[j][S] = 0;
4882  for (j = 0; j < NUM_T_INS_THERMISTORS; j++) temps->ins_temp[j][S] = 0;
4883  for (j = 0; j < NUM_T_RC_VALUES; j++) temps->rc_temp[j][S] = 0;
4884  temps->vr_lwir[S] = VOLTAGE_BAD_VALUE;
4885  }
4886 
4887  /* read in data */
4888 
4889  for (i = FP_T1SET; i < NUM_TEMPS; i++)
4890  {
4891  /* Must read entire vdata for INS1 through INS4 for extracts. */
4892  if (i >= INS1 && i <= INS4) {
4893  returnStatus = read_vdata (v_id, start_scan, -1,
4894  temp[i].vname, temp[i].fname,
4895  (VOIDP)temp[i].buffer);
4896  } else {
4897  returnStatus = read_vdata (v_id, start_scan, num_scans,
4898  temp[i].vname, temp[i].fname,
4899  (VOIDP)temp[i].buffer);
4900  }
4901 
4902  if (returnStatus != MODIS_S_OK)
4903  {
4904  L1BErrorMsg(location, returnStatus, NULL, "read_vdata", 0, NULL, False);
4905  return returnStatus;
4906  }
4907 
4908  /* Check values against valid range. */
4909 
4910  for (S = 0; S < num_scans; S++)
4911  {
4912  if (temp[i].buffer[S] > temp[i].max_valid_value)
4913  {
4914  char msgbuf[256];
4915  sprintf(msgbuf, "Value[%d] of \"%s\" is out of the range [0,%d].",
4916  (int) S, temp[i].fname, (int) temp[i].max_valid_value);
4917  returnStatus = MODIS_F_OUT_OF_RANGE;
4918  L1BErrorMsg(location, returnStatus, msgbuf, NULL, 0,
4920  return returnStatus;
4921  }
4922  }
4923  }
4924 
4925  /* fill in values for instrument temperatures */
4926 
4927  for (i = INS1; i <= INS4; i++)
4928  {
4929  vd_id = VSattach(v_id, VSfind(v_id, "Telemetry Major Cycle 0 of 63"), "r");
4930  returnStatus = Fill_Invalid_Temp_DNs(VSelts(vd_id), 0,
4931  DN_SAT_12BITS, temp[i].buffer);
4932  if (returnStatus != MODIS_S_OK)
4933  {
4934  L1BErrorMsg(location, returnStatus, NULL,
4935  "Fill_Invalid_Temp_DNs", 0, NULL, False);
4936  return returnStatus;
4937  }
4938  VSdetach(vd_id);
4939  if (extract_line_offset > 0)
4940  memcpy(&temp[i].buffer[0], &temp[i].buffer[extract_line_offset],
4941  sizeof(int16)*extract_line_count);
4942  }
4943 
4944 
4945  /* Determine Primary or Redundant CP indicator for each scan. */
4946 
4947  returnStatus = Get_Electronics_index(num_scans, temp[CPA].buffer,
4948  temp[CPB].buffer, CP_index);
4949  if (returnStatus != MODIS_S_OK)
4950  {
4951  L1BErrorMsg(location, returnStatus, "Could not get CPA or CPB indexes",
4952  "Get_Electronics_index", 0, NULL, False);
4953  return returnStatus;
4954  }
4955 
4956 
4957  for (i = BB1; i <= BB12; i++)
4958  {
4959  thermistor = i - BB1;
4960  BB_temp[thermistor] = temp[i].buffer;
4961  }
4962 
4963  /*
4964  * Compute black_body temperature with outlier algorithm implemented
4965  */
4966 
4967  returnStatus = Compute_BB_Temperature(tables,
4968  start_scan,
4969  num_scans,
4970  CP_index,
4971  BB_temp,
4972  satellite_ID,
4973  temps);
4974  if (returnStatus != MODIS_S_OK)
4975  {
4976  L1BErrorMsg(location, returnStatus, NULL,
4977  "Compute_BB_Temperature", 0, NULL, False);
4978  return returnStatus;
4979  }
4980 
4981  /*
4982  * Determine primary or redundant mwir adc board value for each scan.
4983  */
4984 
4985  returnStatus = Get_Electronics_index(num_scans,
4986  temp[MWIR_ADC_PRI].buffer,
4987  temp[MWIR_ADC_RED].buffer,
4988  &temps->mwir_adc_index[start_scan]);
4989  if (returnStatus != MODIS_S_OK)
4990  {
4991  L1BErrorMsg(location, returnStatus, "Could not get MWIR ADC indexes",
4992  "Get_Electronics_index", 0, NULL, False);
4993  return returnStatus;
4994  }
4995 
4996  /*
4997  * Determine primary or redundant lwir adc board value for each scan.
4998  */
4999 
5000  returnStatus = Get_Electronics_index(num_scans,
5001  temp[LWIR_ADC_PRI].buffer,
5002  temp[LWIR_ADC_RED].buffer,
5003  &temps->lwir_adc_index[start_scan]);
5004  if (returnStatus != MODIS_S_OK)
5005  {
5006  L1BErrorMsg(location, returnStatus, "Could not get LWIR ADC indexes",
5007  "Get_Electronics_index", 0, NULL, False);
5008  return returnStatus;
5009  }
5010 
5011  /*
5012  * Determine primary or redundant nir adc board value for each scan.
5013  */
5014 
5015  returnStatus = Get_Electronics_index(num_scans,
5016  temp[NIR_ADC_PRI].buffer,
5017  temp[NIR_ADC_RED].buffer,
5018  &temps->nir_adc_index[start_scan]);
5019  if (returnStatus != MODIS_S_OK)
5020  {
5021  L1BErrorMsg(location, returnStatus, "Could not get NIR ADC indexes",
5022  "Get_Electronics_index", 0, NULL, False);
5023  return returnStatus;
5024  }
5025 
5026  /*
5027  * Determine primary or redundant vis adc board value for each scan.
5028  */
5029 
5030  returnStatus = Get_Electronics_index(num_scans,
5031  temp[VIS_ADC_PRI].buffer,
5032  temp[VIS_ADC_RED].buffer,
5033  &temps->vis_adc_index[start_scan]);
5034  if (returnStatus != MODIS_S_OK)
5035  {
5036  L1BErrorMsg(location, returnStatus, "Could not get VIS ADC indexes",
5037  "Get_Electronics_index", 0, NULL, False);
5038  return returnStatus;
5039  }
5040 
5041  /*
5042  * Determine primary or redundant pclw adc board value for each scan.
5043  */
5044 
5045  returnStatus = Get_Electronics_index_special(num_scans,
5046  temp[PCLW_ADC_PRI].buffer,
5047  temp[PCLW_ADC_RED].buffer,
5048  &temps->pclw_adc_index[start_scan]);
5049  if (returnStatus != MODIS_S_OK)
5050  {
5051  L1BErrorMsg(location, returnStatus, "Could not get PCLW ADC indexes",
5052  "Get_Electronics_index", 0, NULL, False);
5053  return returnStatus;
5054  }
5055 
5056  for (S = 0; S < num_scans; S++)
5057  {
5058  XS = S + start_scan;
5059 
5060  /* Compute focal plane assembly 1 and 2 temperatures.
5061  * The polynomial result is in degrees Celsius, so we
5062  * use the CTOK macro.
5063  */
5064 
5065  CONVERT_TEMP_POLY(temps->fp[0][XS],temp[FP1].buffer[S],Eng_Coeffs.C_FP1,
5067  CONVERT_TEMP_POLY(temps->fp[1][XS],temp[FP2].buffer[S],Eng_Coeffs.C_FP2,
5069 
5070  /* Determine FP_Set_Point_State, needed for FP_3 & _4 */
5071 
5072  if (temp[LWHTR_ON].buffer[S] == 0 && temp[SMHTR_ON].buffer[S] == 0)
5073  FP_SPS = 0; /*FP heaters off, running open loop*/
5074  else if (temp[FP_T1SET].buffer[S] == 1 && temp[FP_T3SET].buffer[S] == 0)
5075  FP_SPS = 0;
5076  else if (temp[FP_T1SET].buffer[S] == 0 && temp[FP_T3SET].buffer[S] == 0)
5077  FP_SPS = 1;
5078  else if (temp[FP_T1SET].buffer[S] == 0 && temp[FP_T3SET].buffer[S] == 1)
5079  FP_SPS = 2;
5080  else /*temp[FP_T1SET].buffer[S] == 1 && temp[FP_T3SET].buffer[S] ==1,
5081  not expected!*/
5082  return (MODIS_F_NOK);
5083 
5084  /* Keep FP_SPS
5085  */
5086  if (temp[LWHTR_ON].buffer[S] == 0 && temp[SMHTR_ON].buffer[S] == 0)
5087  temps->fp_set_point_state[XS] = FP_SPS;
5088  else
5089  temps->fp_set_point_state[XS] = FP_SPS + 1;
5090 
5091  /* Note that for focal planes 3 and 4, the polynomial evaluates
5092  * the temperature in degrees Kelvin and no conversion from
5093  * Celsius to Kelvin is needed.
5094  */
5095 
5096  CONVERT_TEMP_POLY(temps->fp[2][XS], temp[FP3].buffer[S],
5097  Eng_Coeffs.C_FP3[FP_SPS], DN_SAT_12BITS,0.);
5098  CONVERT_TEMP_POLY(temps->fp[3][XS], temp[FP4].buffer[S],
5099  Eng_Coeffs.C_FP4[FP_SPS], DN_SAT_12BITS,0.);
5100 
5101  /* Coefficients which may differ for A/B side */
5102  if (CP_index[S] == ELECTRONICS_PRIMARY)
5103  {
5104  C_CAV = Eng_Coeffs.C_CAV_A;
5105  C_INS = Eng_Coeffs.C_INS_A;
5106  C_MIR = Eng_Coeffs.C_MIR_A;
5107  }
5108  else
5109  {
5110  C_CAV = Eng_Coeffs.C_CAV_B;
5111  C_INS = Eng_Coeffs.C_INS_B;
5112  C_MIR = Eng_Coeffs.C_MIR_B;
5113  }
5114  /* compute scan mirror temperature */
5115 
5116  CONVERT_TEMP_POLY(temps->mir1[XS], temp[MIR1].buffer[S],
5118  CONVERT_TEMP_POLY(temps->mir2[XS], temp[MIR2].buffer[S],
5120 
5121  /* Compute average mirror temperature. The algorithm similar
5122  * to that for the cavity below. Note, we use the local variables
5123  * ncav and tcavsum as a convenience only.
5124  */
5125 
5126  ncav = 0;
5127  tcavsum = 0.0;
5128  if (tables->T_mir_function_flag[0] == ON && temp[MIR1].buffer[S] > 0 &&
5129  temp[MIR1].buffer[S] < DN_SAT_12BITS)
5130  {
5131  ncav++;
5132  tcavsum += temps->mir1[XS];
5133  }
5134 
5135  if (tables->T_mir_function_flag[1] == ON && temp[MIR2].buffer[S] > 0 &&
5136  temp[MIR2].buffer[S] < DN_SAT_12BITS)
5137  {
5138  ncav++;
5139  tcavsum += temps->mir2[XS];
5140  }
5141  if (ncav > 0)
5142  temps->mir_avg[XS] = tcavsum/(float32)ncav;
5143  else
5144  temps->mir_avg[XS] = tables->T_mir_default;
5145 
5146  /* Compute the Scan Motor Temperature. */
5147 
5148  CONVERT_TEMP_POLY(temps->scn_mtr[XS], temp[SCN_MTR].buffer[S], C_CAV,
5150 
5151  /* Compute cavity temperature. The algorithm is to average the valid
5152  * values (checking function flag and DN). If there are no valid values,
5153  * use the default from the LUT.
5154  */
5155 
5156  ncav = 0;
5157  tcavsum = 0.;
5158  for (j = 0, i = CAV1; j < NUM_T_CAV_THERMISTORS && i <= CAV4; j++, i++)
5159  {
5160  if (temp[i].buffer[S] > 0 && temp[i].buffer[S] < DN_SAT_9BITS)
5161  {
5162  CONVERT_TEMP_POLY(temps->cav_temp[j][XS],
5163  temp[i].buffer[S],
5164  C_CAV,
5165  DN_SAT_9BITS,
5167  if (tables->T_cav_function_flag[j] == ON)
5168  {
5169  ncav++;
5170  tcavsum += temps->cav_temp[j][XS];
5171  }
5172  }
5173  }
5174  if (ncav > 0)
5175  temps->cav[XS] = tcavsum / (float32) ncav;
5176  else
5177  temps->cav[XS] = tables->T_cav_default;
5178 
5179 
5180  /* Compute instrument temperature. The algorithm is to use the first
5181  * valid value of the available thermistors. If none are valid,
5182  * then use the default.
5183  */
5184 
5185  temps->ins[XS] = -1;
5186  for (j = 0, i = INS1; j < NUM_T_INS_THERMISTORS && i <= INS4; j++, i++)
5187  {
5188  if (temp[i].buffer[S] > 0 && temp[i].buffer[S] < DN_SAT_12BITS)
5189  {
5190  CONVERT_TEMP_POLY(temps->ins_temp[j][XS],
5191  temp[i].buffer[S],
5192  C_INS,
5193  DN_SAT_12BITS,
5194  Celsius_To_Kelvin_Offset + tables->T_ins_offset[j]);
5195  if (temps->ins[XS] <= 0 && tables->T_ins_function_flag[j] == ON)
5196  temps->ins[XS] = temps->ins_temp[j][XS];
5197  }
5198  }
5199  if (temps->ins[XS] <= 0)
5200  temps->ins[XS] = tables->T_ins_default;
5201 
5202  /* Compute the RC temperatures and single voltage */
5203 
5204  for (j = 0, i = RC1; j < NUM_T_RC_VALUES && i <= RC5; j++, i++)
5205  {
5206  CONVERT_TEMP_POLY(temps->rc_temp[j][XS], temp[i].buffer[S],
5207  Eng_Coeffs.C_RC[j], DN_SAT_12BITS, 0.);
5208  }
5209  CONVERT_TEMP_POLY(temps->vr_lwir[XS],
5210  temp[VR_RC_LW_FPA].buffer[S],
5211  Eng_Coeffs.C_RC_VR_FPA,
5212  DN_SAT_10BITS,
5213  0.);
5214 
5215 
5216  }/*Loop over scan*/
5217 
5218 
5219  return (returnStatus);
5220 }
5221 
5222 
5224  int32 start_scan,
5225  int32 num_scans,
5226  uint16 *CP_index,
5227  uint16 **raw_BB_temp,
5228  int32 satellite_ID,
5229  Temperatures_t *temps)
5230 /*
5231 !C**************************************************************************
5232 !Description: Calculate temperatures for each BB thermistor and the
5233  thermistor averaged temperature with outlier rejection.
5234 
5235 !Input Parameters:
5236  emiss_tables_t * tables Contains BB_Weight, used in here
5237  int32 start_scan Start scan index fo filling arrays in temps
5238  int32 num_scans Number of scans to fill in arrays in temps
5239  uint16 CP_index CP A or B on (0 = "A", 1 = "B")
5240  uint16 ** raw_BB_temp 2D Array of BB temperature DNs
5241  [thermistor][scan]
5242  int32 satellite_ID TERRA = 0, AQUA = 1,
5243  INVALID_SATELLITE_ID = -1
5244 
5245 !Output Parameters:
5246  Temperatures_t *temps
5247 
5248 !Revision History:
5249  Revision 02.01 March 2003, Razor Issue #173
5250  Changed the type of variable "thermistor" from "int8" to "int16" for ANSI-C
5251  compliance.
5252  Liqin Tan, SAIC GSO (ltan@saicmodis.com)
5253 
5254  Revision 02.00 January 4, 2002 Razor Issue #154
5255  Added Engineering Temperature structure to accommodate Terra/Aqua
5256  temperature coefficient differences and changed code to use the structure
5257  variables.
5258  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
5259 
5260  Revision 01.05, January 29, 2001
5261  Improved efficiency of calculation of TBB.
5262  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
5263 
5264  Revision 01.04 November 22, 1999
5265  Added calls to L1BErrorMsg. Changed logic of immediately error-out
5266  to instead simply write error message and return to parent (so that
5267  parent can identify LUN of file).
5268  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
5269 
5270  Revision 01.03 September 30, 1999
5271  Added counting the number of BB thermistor outliers on each scan.
5272  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
5273 
5274  Revision 01.02 August 1999
5275  Used Get_Electronics_index() to determine CPA or CPB and added a check for denom > 1
5276  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
5277  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
5278 
5279  Revision 01.01 May 1999
5280  Added checks on BB DN.
5281  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
5282 
5283  Revision 01.00 Aug 1997
5284  (This function is part of the function Read_Convert_Temperature,developed
5285  by Zhiong Hao, modified by Shi-Yue Qiu and David Catozzi)
5286  Initial development
5287  Zhenying Gu (hao@barebackride.gsfc.nasa.gov)
5288 
5289 !Team-unique Header:
5290  This software is developed by the MODIS Science Data Support
5291  Team for the National Aeronautics and Space Administration,
5292  Goddard Space Flight Center, under contract NAS5-32373.
5293 
5294 !References and Credits:
5295  HDF portions developed at the National Center for Supercomputing
5296  Applications at the University of Illinois at Urbana-Champaign.
5297 
5298 !Design Notes:
5299  The calculations for standard deviation are accomplished in double
5300  precision due to the particular formula being used.
5301 
5302  If an error occurs in this function, write the error message and then
5303  return to the parent (so that the parent can identify the LUN of
5304  the file).
5305 
5306 !END********************************************************************
5307 */
5308 
5309 {
5310  PGSt_SMF_status returnStatus = MODIS_S_OK;
5311  int16 thermistor = 0;
5312  int16 S = 0;
5313  int16 XS = 0;
5314  uint16 DN = 0;
5315  float32 V0 = 0;
5316  float32 I = 0;
5317  double denom = 0;
5318  double sum1 = 0;
5319  double sum2 = 0;
5320  float32 Rc = 0;
5321  float32 R = 0;
5322  float32 lnR = 0;
5323  float32 TBB = 0;
5324  float32 temp1 = 0;
5325  float32 mean = 0;
5326  float32 sdev = 0;
5327  float32 Tmin = 0;
5328  float32 Tmax = 0;
5329  Engineering_Coefficients_t Eng_Coeffs;
5330  char *location = "Compute_BB_Temperature";
5331 
5332  /* Use different sets of engineering coefficients for
5333  * Terra (PFM) and Aqua (FM1)
5334  */
5335 
5336  if (satellite_ID == TERRA) /* Satellite is Terra */
5337  Eng_Coeffs = Engineering_Coefficients_PFM;
5338  else /* Satellite is Aqua */
5339  Eng_Coeffs = Engineering_Coefficients_FM1;
5340 
5341 
5342  for (S = 0; S < num_scans; S++)
5343  {
5344  XS = S + start_scan;
5345  if (CP_index[S] == ELECTRONICS_PRIMARY)
5346  {
5347  V0 = Eng_Coeffs.V0_CPA;
5348  I = Eng_Coeffs.I_CPA;
5349  }
5350  else
5351  {
5352  V0 = Eng_Coeffs.V0_CPB;
5353  I = Eng_Coeffs.I_CPB;
5354  }
5355 
5356  denom = 0;
5357  sum1 = 0;
5358  sum2 = 0;
5359  for (thermistor = 0; thermistor < NUM_BB_THERMISTORS; thermistor++)
5360  {
5361  if (raw_BB_temp[thermistor][S] > 0 &&
5362  raw_BB_temp[thermistor][S] < DN_SAT_12BITS)
5363  {
5364  DN = raw_BB_temp[thermistor][S];
5365  Rc = (5.0*DN/4096.0-(V0+2.5))/I;
5366  if(Eng_Coeffs.Rp - Rc == 0)
5367  {
5368  returnStatus = MODIS_F_NOK;
5369  L1BErrorMsg(location, returnStatus,
5370  "Algorithm failure computing BB temperature.\n"
5371  "Will get a divide by zero because of Rp-Rc.",
5372  NULL, 0, NULL, False);
5373  return returnStatus;
5374  }
5375  R = Rc*(Eng_Coeffs.Rp)/(Eng_Coeffs.Rp - Rc);
5376 
5377  lnR=log((double) R);
5378  if(lnR == 0)
5379  {
5380  returnStatus = MODIS_F_NOK;
5381  L1BErrorMsg(location, returnStatus,
5382  "Algorithm failure computing BB temperature. Will get a log(0).",
5383  NULL, 0, NULL, False);
5384  return returnStatus;
5385  }
5386 
5387  TBB = Eng_Coeffs.BB_a[thermistor][0]
5388  + lnR * (Eng_Coeffs.BB_a[thermistor][1]
5389  + lnR * (Eng_Coeffs.BB_a[thermistor][2]
5390  + lnR * Eng_Coeffs.BB_a[thermistor][3]));
5391  temps->bb[thermistor][XS] = 1.0/TBB;
5392 
5393  temp1 = tables->BB_Weight[thermistor] * temps->bb[thermistor][XS];
5394  sum1 += (double) temp1;
5395  sum2 += (double) temp1 * (double) temp1;
5396  denom += (double) tables->BB_Weight[thermistor];
5397  }
5398  else
5399  {
5400  temps->bb[thermistor][XS] = 0;
5401  }
5402  }
5403  if (denom > 1) /* multiple values contribute */
5404  {
5405  mean = (float32) (sum1 / denom);
5406  sdev = (float32) sqrt(fabs(sum2 - sum1*sum1/denom) / (denom - 1.0));
5407 
5408  if ( sdev < 1.0E-6 )
5409  {
5410  temps->bb_avg[XS] = mean;
5411  temps->num_thermistor_outliers[XS] = 0;
5412  }
5413  else
5414  {
5415  Tmin = mean - 3.0*sdev; /* lower bound on BB temperature to include */
5416  Tmax = mean + 3.0*sdev; /* upper bound on BB temperature to include */
5417 
5418  temps->bb_avg[XS] = 0;
5419  temps->num_thermistor_outliers[XS] = 0;
5420  denom = 0;
5421  for (thermistor = 0; thermistor < NUM_BB_THERMISTORS; thermistor++)
5422  {
5423  if ( temps->bb[thermistor][XS] < Tmin ||
5424  temps->bb[thermistor][XS] > Tmax )
5425  {
5426  if (tables->BB_Weight[thermistor] > TOLERANCE)
5427  temps->num_thermistor_outliers[XS] =
5428  temps->num_thermistor_outliers[XS] + 1;
5429  continue;
5430  }
5431 
5432  temps->bb_avg[XS] +=
5433  tables->BB_Weight[thermistor] * temps->bb[thermistor][XS];
5434  denom += tables->BB_Weight[thermistor];
5435  }
5436  if ( denom < TOLERANCE )
5437  {
5438  temps->bb_avg[XS] = mean;
5439  temps->num_thermistor_outliers[XS] = 0;
5440  }
5441  else
5442  temps->bb_avg[XS] /= denom;
5443  }
5444  }
5445  else if (denom > TOLERANCE) /* only one value contributes */
5446  {
5447  mean = (float32) (sum1 / denom);
5448  temps->bb_avg[XS] = mean;
5449  temps->num_thermistor_outliers[XS] = 0;
5450  }
5451  else /* no values */
5452  {
5453  temps->bb_avg[XS] = 0.;
5454  temps->num_thermistor_outliers[XS] = 0;
5455  }
5456  } /* end loop for scan */
5457  return (returnStatus);
5458 
5459 }
5460 
5461 PGSt_SMF_status Write_Geo_OBC_SDS(int32 obc_sd_id, int32 num_scans)
5462 /*
5463 !C************************************************************************
5464 !Description: Write SD Sun Azimuth and SD Sun Zenigh into L1B_OBC file.
5465 
5466 !Input Parameters:
5467  int32 obc_sd_id file id of obc file
5468  int32 num_scans number of scans in L1A file
5469 !Output Parameters:
5470 
5471  Output file: L1B OBC/Eng file
5472 
5473 !Revision History:
5474  Revision 01.01 November 22, 1999
5475  Added use of L1BErrorMsg
5476  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
5477 
5478  Revision 01.00 May 4 1999
5479  initial development
5480  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
5481 
5482 !Team-unique Header:
5483  This software is developed by the MODIS Characterization Support
5484  Team (MCST)for the National Aeronautics and Space Administration,
5485  Goddard Space Flight Center, under contract NAS5-32373.
5486 
5487 !References and Credits:
5488  HDF portions developed at the National Center for Supercomputing
5489  Applications at the University of Illinois at Urbana-Champaign.
5490 
5491 !Design Notes:
5492 
5493  This function writes to the OBC file, so that the LUN used for write
5494  error messages is assumed to be L1B_OBC_FILE.
5495 
5496 !END********************************************************************
5497 */
5498 {
5499  PGSt_SMF_status returnStatus = MODIS_S_OK;
5500  int32 num_scans_geo;
5501  char fname_geo[512];
5502  int32 geo_sd_id;
5503  PGSt_integer Version = 1;
5504  float32 sun_buffer[MAX_NUM_SCANS];
5505  intn hdf_return;
5506  char *location = "Write_Geo_OBC_SDS";
5507 
5508  if (PGS_PC_GetReference(GEOLOCATION_FILE, &Version, fname_geo) !=
5509  PGS_S_SUCCESS)
5510  {
5511  returnStatus = MODIS_F_FILE_NOT_FOUND;
5512  L1BErrorMsg(location, returnStatus,
5513  "Could not retrieve file name from PCF.",
5514  "PGS_PC_GetReference", GEOLOCATION_FILE, NULL, True);
5515  return returnStatus;
5516  }
5517 
5518  geo_sd_id = SDstart(fname_geo, DFACC_RDONLY);
5519  if (geo_sd_id == FAIL)
5520  {
5521  returnStatus = MODIS_F_FILE_NOT_OPENED;
5522  L1BErrorMsg(location, returnStatus,
5523  "Could not open file for SD read access.",
5524  "SDstart", GEOLOCATION_FILE,
5525  "The file may be missing, corrupted or not an HDF-4 file.",
5526  True);
5527  return returnStatus;
5528  }
5529 
5530  returnStatus = read_attribute(geo_sd_id, GEO_NUM_SCANS_NAME, DFNT_INT32,
5531  &num_scans_geo);
5532  if (returnStatus != MODIS_S_OK)
5533  {
5534  L1BErrorMsg(location, returnStatus, NULL,
5535  "read_attribute", GEOLOCATION_FILE, NULL, True);
5536  return returnStatus;
5537  }
5538 
5539  if (num_scans_geo != num_scans)
5540  {
5541  returnStatus = MODIS_F_OUT_OF_RANGE;
5542  L1BErrorMsg(location, returnStatus,
5543  "Number of scans in GEO file does not match the current L1A file.",
5544  NULL, GEOLOCATION_FILE, "The PCF may have the wrong names.", True);
5545  return returnStatus;
5546  }
5547 
5548  returnStatus = read_sds_rank1(geo_sd_id,
5550  num_scans_geo,
5551  sun_buffer);
5552  if (returnStatus != MODIS_S_OK)
5553  {
5554  L1BErrorMsg(location, returnStatus, NULL,
5555  "read_sds_rank1", GEOLOCATION_FILE, NULL, True);
5556  return returnStatus;
5557  }
5558 
5559  returnStatus = write_sds_rank1(obc_sd_id,
5562  num_scans,
5563  "float32",
5564  sun_buffer);
5565  if (returnStatus != MODIS_S_OK)
5566  {
5567  L1BErrorMsg(location, returnStatus, NULL,
5568  "write_sds_rank1", L1B_OBC_FILE, NULL, True);
5569  return returnStatus;
5570  }
5571 
5572  returnStatus = read_sds_rank1(geo_sd_id,
5574  num_scans_geo,
5575  sun_buffer);
5576  if (returnStatus != MODIS_S_OK)
5577  {
5578  L1BErrorMsg(location, returnStatus, NULL,
5579  "read_sds_rank1", GEOLOCATION_FILE, NULL, True);
5580  return returnStatus;
5581  }
5582 
5583  returnStatus = write_sds_rank1(obc_sd_id,
5586  num_scans,
5587  "float32",
5588  sun_buffer);
5589  if (returnStatus != MODIS_S_OK)
5590  {
5591  L1BErrorMsg(location, returnStatus, NULL,
5592  "write_sds_rank1", L1B_OBC_FILE, NULL, True);
5593  return returnStatus;
5594  }
5595 
5596  hdf_return = SDend(geo_sd_id);
5597  if (hdf_return == FAIL)
5598  {
5599  returnStatus = MODIS_F_HDF_ERROR;
5600  L1BErrorMsg(location, returnStatus, NULL, "SDend", GEOLOCATION_FILE,
5601  "Memory or the disk file must have become corrupted.", True);
5602  return returnStatus;
5603  }
5604 
5605  return (returnStatus);
5606 }
5607 
5608 PGSt_SMF_status Write_L1B_OBCEng (L1A_granule_t *L1A_Gran,
5610  Moon_arrays_t *moon_arrays,
5611  DN_OBC_Avg_t *DN_OBC_Avg)
5612 /*
5613 !C************************************************************************
5614 !Description: Write OBC target sdss and preprocess_data sdss, and
5615  copy scan_level_metadata sdss, pixel_quality sdss,
5616  engineering_memory sdss, engineering vdata, SD Sun
5617  Azimuth, SD Sun Zenith, and DN OBC averages into
5618  L1B_OBC file.
5619 
5620 !Input Parameters:
5621  L1A_granule_t *L1A_Gran
5622  lookup_tables_t *tables
5623  Moon_arrays_t *moon_arrays
5624  DN_OBC_Avg_t *DN_OBC_Avg
5625 !Output Parameters:
5626 
5627  Output file: L1B OBC/Eng file
5628 
5629 !Revision History:
5630  Revision 02.16 May 4 1999
5631  Deleted function call to Write_Preprocess_Data() because SV_avg
5632  and SV_uncert are deleted. Added writing the moon vector and moon
5633  in KOB arrays. Added writing DN OBC averages. Added function
5634  Write_Geo_OBC_SDS()
5635  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
5636  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
5637 
5638  Revision 02.10 July 1 1998
5639  Added function call to Write_Preprocess_Data() back
5640  (had been removed since V2.0)
5641  David Catozzi (cato@ltpmail.gsfc.nasa.gov)
5642 
5643  Revision 02.10 June 1998
5644  added calculation of DN to DN_star for SD
5645  Zhenying Gu (zgu@ltpmail.gsfc.nasa.gov)
5646 
5647  Revision 01.00 Feb. 1997
5648  Initial development
5649  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
5650 
5651 !Team-unique Header:
5652  This software is developed by the MODIS Characterization Support
5653  Team (MCST)for the National Aeronautics and Space Administration,
5654  Goddard Space Flight Center, under contract NAS5-32373.
5655 
5656 !References and Credits:
5657  HDF portions developed at the National Center for Supercomputing
5658  Applications at the University of Illinois at Urbana-Champaign.
5659 
5660 !Design Notes:
5661 
5662 !END********************************************************************
5663 */
5664 {
5665  char *location = "Write_L1B_OBCEng";
5666  PGSt_SMF_status returnStatus = MODIS_S_OK;
5667  intn hdf_return = 0;
5668  PGSt_integer Version = 1;
5669  char file_name[PGSd_PC_FILE_PATH_MAX];
5670  int32 file_id = 0; /* sd_id */
5671  int32 v_id = 0;
5672  int16 T = 0;/*Target index*/
5673  int16 R = 0;/*Resolution index*/
5674  int32 band_dim = 0;
5675  int32 track_dim = 0;
5676  int32 frame_dim = 0;
5677  int32 subsamp_dim = 0;
5678  int16 num_scans = 0;
5679 
5680  int16 *L1B_OBC;
5681  L1B_OBC = (int16*) malloc(NUM_250M_BANDS * MAX_250M_TRACK_DIM * MAX_250M_OBC_FRAME_DIM * sizeof(int16));
5682 
5683  char *avg_names[NUM_L1A_RESOLUTIONS] =
5684  {"DN_obc_avg_250m",
5685  "DN_obc_avg_500m",
5686  "DN_obc_avg_1km_day",
5687  "DN_obc_avg_1km_night"};
5688  char *var_names[NUM_L1A_RESOLUTIONS] =
5689  {"DN_obc_var_250m",
5690  "DN_obc_var_500m",
5691  "DN_obc_var_1km_day",
5692  "DN_obc_var_1km_night"};
5693  char *omask_names[NUM_L1A_RESOLUTIONS] =
5694  {"DN_obc_outlier_mask_250m",
5695  "DN_obc_outlier_mask_500m",
5696  "DN_obc_outlier_mask_1km_day",
5697  "DN_obc_outlier_mask_1km_night"};
5698 
5699  char *subsamp_dim_names[NUM_L1A_RESOLUTIONS] =
5700  {"250m_subsamples",
5701  "500m_subsamples",
5702  "1km_subsamples",
5703  "1km_subsamples"};
5704 
5705 #define WRITE_DN_BG_AT_RES(r, avg, var, omask) \
5706  band_dim = L1A_BANDS_AT_RES[r]; \
5707  track_dim = num_scans * DETECT_PER_BAND_AT_RES[r]; \
5708  subsamp_dim = BAND_RATIO_AT_RES[r]; \
5709  returnStatus = write_sds_rank3(file_id, avg_names[r], \
5710  L1A_TRACK_DIM_NAME[r], \
5711  L1A_BAND_DIM_NAME[r], \
5712  subsamp_dim_names[r], \
5713  track_dim, band_dim, subsamp_dim, \
5714  "float32", avg); \
5715  if (returnStatus != MODIS_S_OK) \
5716  { \
5717  L1BErrorMsg(location, returnStatus, NULL, \
5718  "write_sds_rank3", L1B_OBC_FILE, NULL, True); \
5719  return returnStatus; \
5720  } \
5721  returnStatus = write_sds_rank3(file_id, var_names[r], \
5722  L1A_TRACK_DIM_NAME[r], \
5723  L1A_BAND_DIM_NAME[r], \
5724  subsamp_dim_names[r], \
5725  track_dim, band_dim, subsamp_dim, \
5726  "float32", var); \
5727  if (returnStatus != MODIS_S_OK) \
5728  { \
5729  L1BErrorMsg(location, returnStatus, NULL, \
5730  "write_sds_rank3", L1B_OBC_FILE, NULL, True); \
5731  return returnStatus; \
5732  } \
5733  returnStatus = write_sds_rank4(file_id, omask_names[r], \
5734  L1A_TRACK_DIM_NAME[r], \
5735  L1A_BAND_DIM_NAME[r], \
5736  subsamp_dim_names[r], "2", \
5737  track_dim, band_dim, subsamp_dim, \
5738  2, "uint32", omask); \
5739  if (returnStatus != MODIS_S_OK) \
5740  { \
5741  L1BErrorMsg(location, returnStatus, NULL, \
5742  "write_sds_rank4", L1B_OBC_FILE, NULL, True); \
5743  return returnStatus; \
5744  }
5745 
5746  /*
5747  * Prepare for opening file: convert logical ID to physical name
5748  */
5749 
5750  returnStatus = PGS_PC_GetReference (L1B_OBC_FILE, &Version, file_name);
5751  if (returnStatus != PGS_S_SUCCESS)
5752  {
5753  returnStatus = MODIS_F_FILE_NOT_FOUND;
5754  L1BErrorMsg(location, returnStatus,
5755  "Could not retrieve file name from PCF.",
5756  "PGS_PC_GetReference", L1B_OBC_FILE, NULL, True);
5757  return returnStatus;
5758  }
5759 
5760  /*
5761  * Create/open file for HDF science data (SD) access.
5762  */
5763 
5764  file_id = SDstart (file_name, DFACC_CREATE);
5765  if (file_id == FAIL)
5766  {
5767  returnStatus = MODIS_F_FILE_NOT_CREATED;
5768  L1BErrorMsg(location, returnStatus,
5769  "Could not create file for SD write access.",
5770  "SDstart", L1B_OBC_FILE, NULL, True);
5771  return returnStatus;
5772  }
5773 
5774  /*
5775  * Open file for HDF Vdata access and initialize Vdata interface.
5776  * Call Hopen() and Vstart() in the same place.
5777  */
5778 
5779  v_id = Hopen(file_name, DFACC_RDWR, 0);
5780  if (v_id == FAIL)
5781  {
5782  returnStatus = MODIS_F_FILE_NOT_OPENED;
5783  L1BErrorMsg(location, returnStatus,
5784  "Could not open file for Vdata read/write access.",
5785  "Hopen", L1B_OBC_FILE,
5786  "The file may be corrupted or not an HDF-4 file.", True);
5787  return returnStatus;
5788  }
5789 
5790  hdf_return = Vstart (v_id);
5791  if (hdf_return == FAIL)
5792  {
5793  returnStatus = MODIS_F_HDF_ERROR;
5794  L1BErrorMsg(location, returnStatus,
5795  "Could not initialize Vdata interface.",
5796  "Vstart", L1B_OBC_FILE,
5797  "The file may be corrupted or not an HDF-4 file.", True);
5798  return returnStatus;
5799  }
5800 
5801  /*
5802  * Write OBC sector DN SDSs. Loop through targets and resolutions and
5803  * read data from the L1A file and then write data to the OBC file.
5804  */
5805 
5806  num_scans = L1A_Gran->num_scans;
5807 
5808  for (T = 0; T < NUM_TARGETS - 1; T++) /*Excluding EV target*/
5809  for (R = 0; R < NUM_L1A_RESOLUTIONS; R++)
5810  {
5811  if ((RFLAG & (1 << R)) != 0) continue;
5812 
5813  band_dim = L1A_BANDS_AT_RES[R];
5814  track_dim = L1A_Gran->num_scans * DETECT_PER_BAND_AT_RES[R];
5815  frame_dim = TARGET_1km_FRAMES[T] * BAND_RATIO_AT_RES[R];
5816 
5817  returnStatus = read_sds_rank3(L1A_Gran->sd_id, L1A_TARGET_SDS_NAME[T][R],
5818  track_dim, band_dim, frame_dim, L1B_OBC);
5819  if (returnStatus != MODIS_S_OK)
5820  {
5821  L1BErrorMsg(location, returnStatus, NULL,
5822  "read_sds_rank3", FIRST_L1A_GRANULE, NULL, True);
5823  return returnStatus;
5824  }
5825 
5826  returnStatus = write_sds_rank3(file_id, L1A_TARGET_SDS_NAME[T][R],
5829  L1A_FRAME_DIM_NAME[T][R],
5830  track_dim, band_dim, frame_dim,
5831  "int16", L1B_OBC);
5832  if (returnStatus != MODIS_S_OK)
5833  {
5834  L1BErrorMsg(location, returnStatus, NULL,
5835  "write_sds_rank3", L1B_OBC_FILE, NULL, True);
5836  return returnStatus;
5837  }
5838 
5839  }
5840 
5841  /* Write attribute first SV or BB frame to use */
5842 
5843  hdf_return = SDsetattr(file_id, DN_BG_FIRST_FRAME_SDS_NAME, DFNT_INT16, 1,
5844  &tables->refl.DN_obc_avg_first_frame_to_use);
5845  if (hdf_return == FAIL)
5846  {
5847  returnStatus = MODIS_F_WRITE_ERROR;
5848  L1BErrorMsg(location, returnStatus,
5849  "Failed to write DN_obc_avg_first_frame_to_use.",
5850  "SDsetattr", L1B_OBC_FILE, NULL, True);
5851  return returnStatus;
5852  }
5853 
5854  /* Write attribute number of SV or BB frames to use */
5855 
5856  hdf_return = SDsetattr(file_id, DN_BG_NUM_FRAMES_SDS_NAME, DFNT_INT16, 1,
5857  &tables->refl.DN_obc_avg_number_of_frames_to_use);
5858  if (hdf_return == FAIL)
5859  {
5860  returnStatus = MODIS_F_WRITE_ERROR;
5861  L1BErrorMsg(location, returnStatus,
5862  "Failed to write DN_obc_avg_number_of_frames_to_use.",
5863  "SDsetattr", L1B_OBC_FILE, NULL, True);
5864  return returnStatus;
5865  }
5866 
5867  /* Write moon vector */
5868 
5869  returnStatus = write_sds_rank2(file_id,
5872  VEC_DIM_NAME,
5873  L1A_Gran->num_scans,
5874  VEC_DIM,
5875  "float32",
5876  moon_arrays->moon_vector);
5877  if (returnStatus != MODIS_S_OK)
5878  {
5879  L1BErrorMsg(location, returnStatus, NULL,
5880  "write_sds_rank2", L1B_OBC_FILE, NULL, True);
5881  return returnStatus;
5882  }
5883 
5884  /* Write moon in KOB */
5885 
5886  returnStatus = write_sds_rank2(file_id,
5890  L1A_Gran->num_scans,
5891  NUM_BANDS,
5892  "int8",
5893  moon_arrays->moon_in_SV_KOB);
5894  if (returnStatus != MODIS_S_OK)
5895  {
5896  L1BErrorMsg(location, returnStatus, NULL,
5897  "write_sds_rank2", L1B_OBC_FILE, NULL, True);
5898  return returnStatus;
5899  }
5900 
5901  /* Write SD sun azimuth and SD sun zenith */
5902 
5903  returnStatus = Write_Geo_OBC_SDS(file_id, L1A_Gran->num_scans);
5904  if (returnStatus != MODIS_S_OK)
5905  {
5906  L1BErrorMsg(location, returnStatus, NULL,
5907  "Write_Geo_OBC_SDS", L1B_OBC_FILE, NULL, True);
5908  return returnStatus;
5909  }
5910 
5912  DN_OBC_Avg->DN_obc_250m_avg,
5913  DN_OBC_Avg->DN_obc_250m_var,
5914  DN_OBC_Avg->DN_obc_250m_outlier_mask);
5915 
5917  DN_OBC_Avg->DN_obc_500m_avg,
5918  DN_OBC_Avg->DN_obc_500m_var,
5919  DN_OBC_Avg->DN_obc_500m_outlier_mask);
5920 
5922  DN_OBC_Avg->DN_obc_1km_day_avg,
5923  DN_OBC_Avg->DN_obc_1km_day_var,
5924  DN_OBC_Avg->DN_obc_1km_day_outlier_mask);
5925 
5927  DN_OBC_Avg->DN_obc_1km_night_avg,
5928  DN_OBC_Avg->DN_obc_1km_night_var,
5929  DN_OBC_Avg->DN_obc_1km_night_outlier_mask);
5930 
5931 
5932  /* Copy other L1A data......*/
5933  returnStatus = Copy_EngMemData (L1A_Gran->sd_id, file_id,
5934  L1A_Gran->num_scans);
5935  if (returnStatus != MODIS_S_OK)
5936  {
5937  L1BErrorMsg(location, returnStatus, NULL,
5938  "Copy_EngMemData", L1B_OBC_FILE, NULL, True);
5939  return returnStatus;
5940  }
5941 
5942  returnStatus = Copy_ScanMetadata (L1A_Gran->sd_id, file_id,
5943  L1A_Gran->num_scans);
5944  if (returnStatus != MODIS_S_OK)
5945  {
5946  L1BErrorMsg(location, returnStatus, NULL,
5947  "Copy_ScanMetadata", L1B_OBC_FILE, NULL, True);
5948  return returnStatus;
5949  }
5950 
5951  returnStatus = Copy_PixelQualityData (L1A_Gran->sd_id, file_id,
5952  L1A_Gran->num_scans);
5953  if (returnStatus != MODIS_S_OK)
5954  {
5955  L1BErrorMsg(location, returnStatus, NULL,
5956  "Copy_PixelQualityData", L1B_OBC_FILE, NULL, True);
5957  return returnStatus;
5958  }
5959 
5960  returnStatus = Copy_EngVdata (L1A_Gran->v_id, v_id);
5961  if (returnStatus != MODIS_S_OK)
5962  {
5963  L1BErrorMsg(location, returnStatus, NULL,
5964  "Copy_EngVdata", L1B_OBC_FILE, NULL, True);
5965  return returnStatus;
5966  }
5967 
5968  /*
5969  * Close file and all accesses.
5970  */
5971 
5972  if (v_id != FAIL)
5973  {
5974  hdf_return = Vend(v_id);
5975  if (hdf_return == FAIL)
5976  {
5977  L1BErrorMsg(location, MODIS_F_HDF_ERROR, NULL, "Vend",
5978  L1B_OBC_FILE,
5979  "Memory or the disk file must have become corrupted.",
5980  True);
5981  }
5982  hdf_return = Hclose(v_id);
5983  if (hdf_return == FAIL)
5984  {
5985  L1BErrorMsg(location, MODIS_F_HDF_ERROR, NULL, "Hclose",
5986  L1B_OBC_FILE,
5987  "Memory or the disk file must have become corrupted.",
5988  True);
5989  }
5990  }
5991  if (file_id != FAIL)
5992  {
5993  if (SDend(file_id) == FAIL)
5994  {
5995  L1BErrorMsg(location, MODIS_F_HDF_ERROR, NULL, "SDend",
5996  L1B_OBC_FILE,
5997  "Memory or the disk file must have become corrupted.",
5998  True);
5999  }
6000  }
6001 
6002  free(L1B_OBC);
6003  return (returnStatus);
6004 }
6005 
6006 PGSt_SMF_status Copy_EngMemData (int32 in_sd_id,
6007  int32 out_sd_id,
6008  int32 num_scans)
6009 /*
6010 !C************************************************************************
6011 !Description: Copy all Engineering/Memory Data from L1A to L1B_OBC and
6012  calculate the QA "Moon within defined limits of SVP".
6013 
6014 !Input Parameters:
6015  int32 in_sd_id L1A file sd_id
6016  int32 out_sd_id L1B file sd_id
6017  int32 num_scans
6018 
6019 !Output Parameters:
6020 
6021 !Revision History:
6022  Revision 01.01 March 2003, Razor Issue #173
6023  Deleted the value "NUM_ENG_MEM_SDS" from the enum "i", replaced it with a
6024  new defined macro "NUM_ENG_MEM_SDS", and modified the corresponding "for"
6025  loop for ANSI-C compliance.
6026  Liqin Tan, SAIC GSO (ltan@saicmodis.com)
6027 
6028  Revision 01.00 June 1997
6029  Initial development
6030  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
6031 
6032 !Team-unique Header:
6033  This software is developed by the MODIS Characterization Support
6034  Team (MCST)for the National Aeronautics and Space Administration,
6035  Goddard Space Flight Center, under contract NAS5-32373.
6036 
6037 !References and Credits:
6038  HDF portions developed at the National Center for Supercomputing
6039  Applications at the University of Illinois at Urbana-Champaign.
6040 
6041 !Design Notes:
6042 
6043  For writing error messages, it is assumed that this function reads from
6044  the current L1A granule and writes to the L1B OBC file (for setting the
6045  LUN).
6046 
6047 !END********************************************************************
6048 */
6049 {
6050 #define NUM_ENG_MEM_SDS 12
6051  char *location = "Copy_EngMemData";
6052  PGSt_SMF_status returnStatus = MODIS_S_OK;
6053  char *sds_name = NULL;
6054  char *dim_name[2];
6055  int32 rank = 2; /*max rank is 2*/
6056  int32 data_type = 0;
6057  int32 start[2] = {0, 0};
6058  int32 edge[2] = {0, 0};
6059  char buffer[MAX_NUM_SCANS * MAX_ENG_MEM_DATA_DIM];
6060  enum {
6061  FPA_AEM_CONFIG,
6062  SCIENCE_STATE,
6063  SCIENCE_ABNORMAL,
6064  FPA_DCR_OFFSET,
6065  RAW_MIR_ENC,
6066  RAW_VS_DEF,
6067  RAW_VS_ACT,
6068  RAW_SCI_ENG,
6069  RAW_HK_TELEM,
6070  RAW_SC_ANCIL,
6071  RAW_PARAM,
6072  RAW_PV_GAINS
6073  } i;
6074 
6075  edge[0] = num_scans;
6076  dim_name[0] = "nscans";
6077 
6078  for (i = FPA_AEM_CONFIG; i < NUM_ENG_MEM_SDS; i++)
6079  {
6080  switch(i)
6081  {
6082  case FPA_AEM_CONFIG:
6083  sds_name = "fpa_aem_config";
6084  data_type = DFNT_INT8;
6085  rank = 2;
6086  edge[1] = 10;
6087  dim_name[1] = "10";
6088  break;
6089  case SCIENCE_STATE:
6090  sds_name = "science_state";
6091  data_type = DFNT_INT8;
6092  rank = 1;
6093  break;
6094  case SCIENCE_ABNORMAL:
6095  sds_name = "science_abnormal";
6096  data_type = DFNT_INT8;
6097  rank = 1;
6098  break;
6099  case FPA_DCR_OFFSET:
6100  sds_name = "fpa_dcr_offset";
6101  data_type = DFNT_INT8;
6102  rank = 2;
6103  edge[1] = 550;
6104  dim_name[1] = "550";
6105  break;
6106  case RAW_MIR_ENC:
6107  sds_name = "raw_mir_enc";
6108  data_type = DFNT_INT16;
6109  rank = 2;
6110  edge[1] = 78;
6111  dim_name[1] = "78";
6112  break;
6113  case RAW_VS_DEF:
6114  sds_name = "raw_vs_def";
6115  data_type = DFNT_INT16;
6116  rank = 2;
6117  edge[1] = 40;
6118  dim_name[1] = "40";
6119  break;
6120  case RAW_VS_ACT:
6121  sds_name = "raw_vs_act";
6122  data_type = DFNT_INT16;
6123  rank = 2;
6124  edge[1] = 24;
6125  dim_name[1] = "24";
6126  break;
6127  case RAW_SCI_ENG:
6128  sds_name = "raw_sci_eng";
6129  data_type = DFNT_INT8;
6130  rank = 2;
6131  edge[1] = 212;
6132  dim_name[1] = "212";
6133  break;
6134  case RAW_HK_TELEM:
6135  sds_name = "raw_hk_telem";
6136  data_type = DFNT_INT8;
6137  rank = 2;
6138  edge[1] = 128;
6139  dim_name[1] = "128";
6140  break;
6141  case RAW_SC_ANCIL:
6142  sds_name = "raw_sc_ancil";
6143  data_type = DFNT_INT16;
6144  rank = 2;
6145  edge[1] = 64;
6146  dim_name[1] = "64";
6147  break;
6148  case RAW_PARAM:
6149  sds_name = "raw_param";
6150  data_type = DFNT_INT8;
6151  rank = 2;
6152  edge[1] = 40;
6153  dim_name[1] = "40";
6154  break;
6155  case RAW_PV_GAINS:
6156  sds_name = "raw_pv_gains";
6157  data_type = DFNT_INT8;
6158  rank = 2;
6159  edge[1] = 550;
6160  dim_name[1] = "550";
6161  break;
6162  }
6163 
6164  /*
6165  * Read the SDS data from the L1A file.
6166  */
6167 
6168  returnStatus = read_sds_rankn(in_sd_id, sds_name, data_type, rank,
6169  start, edge, buffer);
6170  if (returnStatus != MODIS_S_OK)
6171  {
6172  L1BErrorMsg(location, returnStatus, NULL, "read_sds_rankn",
6174  return returnStatus;
6175  }
6176 
6177  /*
6178  * Write the data to the OBC file.
6179  */
6180 
6181  returnStatus = write_sds_rankn(out_sd_id, sds_name, data_type, rank,
6182  edge, dim_name, buffer);
6183  if (returnStatus != MODIS_S_OK)
6184  {
6185  L1BErrorMsg(location, returnStatus, NULL, "write_sds_rankn",
6186  L1B_OBC_FILE, NULL, True);
6187  return returnStatus;
6188  }
6189 
6190  }
6191 
6192  return returnStatus;
6193 }
6194 
6195 PGSt_SMF_status Copy_PixelQualityData (int32 in_sd_id,
6196  int32 out_sd_id,
6197  int32 num_scans)
6198 /*
6199 !C************************************************************************
6200 !Description: Copy L1A Pixel Quality Data into L1B_OBCEng file.
6201 
6202 !Input Parameters:
6203  int32 in_sd_id L1A file sd_id
6204  int32 out_sd_id L1B_OBC file sd_id
6205  int32 num_scans number of scans in current granule
6206 
6207 !Output Parameters:
6208 
6209 !Revision History:
6210  Revision 01.01 March 2003, Razor Issue #173
6211  Deleted the value "NUM_PIXEL_QUALITY_SDS" from the enum "i", replaced it
6212  with a new defined macro "NUM_PIXEL_QUALITY_SDS", and modified the
6213  corresponding "for" loops for ANSI-C compliance.
6214  Liqin Tan, SAIC GSO (ltan@saicmodis.com)
6215 
6216  Revision 01.00 June 1997
6217  Initial development
6218  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
6219 
6220 !Team-unique Header:
6221  This software is developed by the MODIS Characterization Support
6222  Team (MCST)for the National Aeronautics and Space Administration,
6223  Goddard Space Flight Center, under contract NAS5-32373.
6224 
6225 !References and Credits:
6226  HDF portions developed at the National Center for Supercomputing
6227  Applications at the University of Illinois at Urbana-Champaign.
6228 
6229 !Design Notes:
6230 
6231 !END********************************************************************
6232 */
6233 {
6234 #define NUM_PIXEL_QUALITY_SDS 5
6235  PGSt_SMF_status returnStatus = MODIS_S_OK;
6236  char *location = "Copy_PixelQualityData";
6237  char *sds_name = NULL;
6238  char *dim_name[3];
6239  int32 j;
6240  int32 rank = 3; /*max rank is 3*/
6241  int32 data_type = 0;
6242  int32 start[3] = {0, 0, 0};
6243  int32 edge[3] = {0, 0, 0};
6244  int16 *buffer;
6245  buffer = (int16*) malloc(MAX_NUM_SCANS * 1400 * 2 * sizeof(int16));
6246  enum {
6247  SD,
6248  SRCA,
6249  BB,
6250  SV,
6251  EARTH
6252 } i;
6253 
6254  data_type = DFNT_INT16;
6255 
6256  edge[0] = num_scans;
6257  edge[2] = 2;
6258  dim_name[0] = "nscans";
6259  dim_name[2] = "2";
6260 
6261  for (i = SD; i < NUM_PIXEL_QUALITY_SDS; i++)
6262  {
6263  switch(i)
6264  {
6265  case SD:
6266  sds_name = "SD sector Pixel quality";
6267  edge[1] = 64;
6268  dim_name[1] = "64";
6269  break;
6270  case SRCA:
6271  sds_name = "SRCA sector Pixel quality";
6272  edge[1] = 64;
6273  dim_name[1] = "64";
6274  break;
6275  case BB:
6276  sds_name = "BB sector Pixel quality";
6277  edge[1] = 64;
6278  dim_name[1] = "64";
6279  break;
6280  case SV:
6281  sds_name = "SV sector Pixel quality";
6282  edge[1] = 64;
6283  dim_name[1] = "64";
6284  break;
6285  case EARTH:
6286  sds_name = "Earth sector Pixel quality";
6287  edge[1] = 1400;
6288  dim_name[1] = "1400";
6289  if (extract_pixel_count > 0) edge[1] = extract_pixel_count;
6290  break;
6291  }
6292 
6293  /*
6294  * Read the SDS data from the L1A file.
6295  */
6296 
6297  returnStatus = read_sds_rankn(in_sd_id, sds_name, data_type, rank,
6298  start, edge, buffer);
6299  if (returnStatus != MODIS_S_OK)
6300  {
6301  L1BErrorMsg(location, returnStatus, NULL, "read_sds_rankn",
6303  return returnStatus;
6304  }
6305 
6306  if ((extract_pixel_offset > 0 ||
6307  extract_pixel_count > 0) &&
6308  i == EARTH) {
6309  edge[1] = 1400; // reset to full width for output
6310  for (j=edge[0]-1; j>=0; j--) {
6311  memmove(&buffer[(j*edge[1]+extract_pixel_offset)*edge[2]],
6312  &buffer[j*extract_pixel_count*edge[2]],
6313  extract_pixel_count*edge[2]*sizeof(int16));
6314  }
6315  for (j=edge[0]-1; j>=0; j--) {
6316  memset(&buffer[j*edge[1]*edge[2]],
6317  0,
6318  extract_pixel_offset*edge[2]*sizeof(int16));
6319  memset(&buffer[(j*edge[1]+extract_pixel_offset+extract_pixel_count)*edge[2]],
6320  0,
6321  (edge[1]-extract_pixel_offset-extract_pixel_count)*edge[2]*sizeof(int16));
6322  }
6323  }
6324 
6325  /*
6326  * Write the data to the OBC file.
6327  */
6328 
6329  returnStatus = write_sds_rankn(out_sd_id, sds_name, data_type, rank,
6330  edge, dim_name, buffer);
6331  if (returnStatus != MODIS_S_OK)
6332  {
6333  L1BErrorMsg(location, returnStatus, NULL, "write_sds_rankn",
6334  L1B_OBC_FILE, NULL, True);
6335  return returnStatus;
6336  }
6337 
6338  }
6339 
6340  free(buffer);
6341 
6342  return returnStatus;
6343 }
6344 
6345 PGSt_SMF_status Copy_ScanMetadata (int32 in_sd_id,
6346  int32 out_sd_id,
6347  int32 num_scans)
6348 /*
6349 !C************************************************************************
6350 !Description: Copy L1A scan level metadata (SDSs) into L1B_OBCEng file.
6351 
6352 !Input Parameters:
6353  int32 in_sd_id L1A file sd_id
6354  int32 out_sd_id L1B_OBC file sd_id
6355  int32 num_scans number of scans in current granule
6356 
6357 !Output Parameters:
6358 
6359 !Revision History:
6360  Revision 01.01 March 2003, Razor Issue #173
6361  Deleted the value "NUM_SCANMETA_SDS" from the enum "i", replaced it
6362  with a new defined macro "NUM_SCANMETA_SDS", and modified the
6363  corresponding "for" loops for ANSI-C compliance.
6364  Liqin Tan, SAIC GSO (ltan@saicmodis.com)
6365 
6366  Revision 01.00 June 1997
6367  Initial development
6368  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
6369 
6370 !Team-unique Header:
6371  This software is developed by the MODIS Characterization Support
6372  Team (MCST)for the National Aeronautics and Space Administration,
6373  Goddard Space Flight Center, under contract NAS5-32373.
6374 
6375 !References and Credits:
6376  HDF portions developed at the National Center for Supercomputing
6377  Applications at the University of Illinois at Urbana-Champaign.
6378 
6379 !Design Notes:
6380 
6381 !END********************************************************************
6382 */
6383 {
6384 #define NUM_SCANMETA_SDS 14
6385  char *location = "Copy_ScanMetadata";
6386  PGSt_SMF_status returnStatus = MODIS_S_OK;
6387  char *sds_name = NULL;
6388  char *dim_name[2];
6389  int32 rank = 2; /*max rank is 2*/
6390  int32 data_type = 0;
6391  int32 start[2] = {0, 0};
6392  int32 edge[2] = {0, 0};
6393  int32 buffer[MAX_NUM_SCANS * 4];
6394  enum {
6395  SCAN_NUMBER,
6396  FRAME_COUNT_ARRAY,
6397  SCAN_TYPE,
6398  SD_START_TIME,
6399  SRCA_START_TIME,
6400  BB_START_TIME,
6401  SV_START_TIME,
6402  EV_START_TIME,
6403  SRCA_CALIBRATION_MODE,
6404  PACKET_SCAN_COUNT,
6405  CCSDS_APPLICATION_IDENTIFIERS,
6406  PACKET_EXPEDITED_DATA_FLAG,
6407  MIRROR_SIDE,
6409 } i;
6410 
6411  edge[0] = num_scans;
6412  dim_name[0] = "nscans";
6413 
6414  for (i = SCAN_NUMBER; i < NUM_SCANMETA_SDS; i++)
6415  {
6416  switch(i)
6417  {
6418  case SCAN_NUMBER:
6419  sds_name = "Scan number";
6420  data_type = DFNT_INT16;
6421  rank = 1;
6422  break;
6423  case FRAME_COUNT_ARRAY:
6424  sds_name = "Frame count array";
6425  data_type = DFNT_INT16;
6426  rank = 2;
6427  edge[1] = 6;
6428  dim_name[1] = "6";
6429  break;
6430  case SCAN_TYPE:
6431  sds_name = "Scan Type";
6432  data_type = DFNT_CHAR8;
6433  rank = 2;
6434  edge[1] = 10;
6435  dim_name[1] = "10";
6436  break;
6437  case SD_START_TIME:
6438  sds_name = "SD start time";
6439  data_type = DFNT_FLOAT64;
6440  rank = 1;
6441  break;
6442  case SRCA_START_TIME:
6443  sds_name = "SRCA start time";
6444  data_type = DFNT_FLOAT64;
6445  rank = 1;
6446  break;
6447  case BB_START_TIME:
6448  sds_name = "BB start time";
6449  data_type = DFNT_FLOAT64;
6450  rank = 1;
6451  break;
6452  case SV_START_TIME:
6453  sds_name = "SV start time";
6454  data_type = DFNT_FLOAT64;
6455  rank = 1;
6456  break;
6457  case EV_START_TIME:
6458  sds_name = "EV start time";
6459  data_type = DFNT_FLOAT64;
6460  rank = 1;
6461  break;
6462  case SRCA_CALIBRATION_MODE:
6463  sds_name = "SRCA calibration mode";
6464  data_type = DFNT_INT16;
6465  rank = 1;
6466  break;
6467  case PACKET_SCAN_COUNT:
6468  sds_name = "Packet scan count";
6469  data_type = DFNT_INT16;
6470  rank = 1;
6471  break;
6472  case CCSDS_APPLICATION_IDENTIFIERS:
6473  sds_name = "CCSDS Application Identifiers";
6474  data_type = DFNT_INT16;
6475  rank = 2;
6476  edge[1] = 3;
6477  dim_name[1] = "3";
6478  break;
6479  case PACKET_EXPEDITED_DATA_FLAG:
6480  sds_name = "Packet expedited data flag";
6481  data_type = DFNT_INT16;
6482  rank = 1;
6483  break;
6484  case MIRROR_SIDE:
6485  sds_name = "Mirror side";
6486  data_type = DFNT_INT16;
6487  rank = 1;
6488  break;
6489  case SCAN_QUALITY_ARRAY:
6490  sds_name = "Scan quality array";
6491  data_type = DFNT_INT32;
6492  rank = 2;
6493  edge[1] = 4;
6494  dim_name[1] = "4";
6495  break;
6496  }
6497 
6498  /*
6499  * Read the SDS data from the L1A file.
6500  */
6501 
6502  returnStatus = read_sds_rankn(in_sd_id, sds_name, data_type, rank,
6503  start, edge, buffer);
6504  if (returnStatus != MODIS_S_OK)
6505  {
6506  L1BErrorMsg(location, returnStatus, NULL, "read_sds_rankn",
6508  return returnStatus;
6509  }
6510 
6511  /*
6512  * Write the data to the OBC file.
6513  */
6514 
6515  returnStatus = write_sds_rankn(out_sd_id, sds_name, data_type, rank,
6516  edge, dim_name, buffer);
6517  if (returnStatus != MODIS_S_OK)
6518  {
6519  L1BErrorMsg(location, returnStatus, NULL, "write_sds_rankn",
6520  L1B_OBC_FILE, NULL, True);
6521  return returnStatus;
6522  }
6523 
6524  }
6525 
6526  return returnStatus;
6527 }
6528 
6529 PGSt_SMF_status Copy_EngVdata (int32 in_v_id,
6530  int32 out_v_id)
6531 /*
6532 !C************************************************************************
6533 !Description: Copy L1A Engineering Vdata into L1B_OBCEng file.
6534 
6535 !Input Parameters:
6536  int32 in_v_id L1A file v_id
6537  int32 out_v_id L1B_OBCEng file v_id
6538 
6539 !Output Parameters:
6540  N/A
6541 
6542 !Revision History:
6543  Revision 01.00 June 1997
6544  Initial development
6545  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
6546 
6547 !Team-unique Header:
6548  This software is developed by the MODIS Characterization Support
6549  Team (MCST)for the National Aeronautics and Space Administration,
6550  Goddard Space Flight Center, under contract NAS5-32373.
6551 
6552 !References and Credits:
6553  HDF portions developed at the National Center for Supercomputing
6554  Applications at the University of Illinois at Urbana-Champaign.
6555 
6556 !Design Notes:
6557 
6558 !END********************************************************************
6559 */
6560 {
6561  PGSt_SMF_status returnStatus = MODIS_S_OK;
6562  char *location = "Copy_EngVdata";
6563  intn hdf_return = FAIL;
6564  int32 in_vdata_id = 0;
6565  int32 out_vdata_id= 0;
6566  int32 vdata = 0; /*vdata index*/
6567  int32 field = 0; /*field index*/
6568  int32 nfields = 0;
6569  int32 nvdata = 0;
6570  int32 nrecords = 0;
6571  int32 interlace = 0;
6572  int32 vd_size = 0;
6573  int32 vdata_ref[MAX_NUM_VDATA];
6574  int32 f_type = 0;
6575  int32 f_order = 0;
6576  char *f_name = NULL; /* str pointer */
6577  char fields[2048], vd_name[80]; /*max fields string less than 1024 bytes*/
6578  char buffer[MAX_NUM_SCANS * MAX_VDATA_SIZE];
6579 
6580  /*Get nvdata in L1A file and the reference numbers*/
6581  nvdata = VSlone (in_v_id, NULL, 0);
6582  if (nvdata == FAIL)
6583  {
6584  returnStatus = MODIS_F_HDF_ERROR;
6585  L1BErrorMsg(location, returnStatus, NULL, "VSlone(1st)",
6587  return returnStatus;
6588  }
6589 
6590  hdf_return = VSlone (in_v_id, vdata_ref, nvdata);
6591  if (hdf_return == FAIL)
6592  {
6593  returnStatus = MODIS_F_HDF_ERROR;
6594  L1BErrorMsg(location, returnStatus, NULL, "VSlone(2nd)",
6596  return returnStatus;
6597  }
6598 
6599  /*Loop over all vdata*/
6600  for (vdata = 0; vdata < nvdata; vdata++)
6601  {
6602  /*attach a vdata to read*/
6603  in_vdata_id = VSattach (in_v_id, vdata_ref[vdata], "r");
6604  if (in_vdata_id == FAIL)
6605  {
6606  returnStatus = MODIS_F_HDF_ERROR;
6607  L1BErrorMsg(location, returnStatus, NULL, "VSattach",
6609  return returnStatus;
6610  }
6611 
6612  /*inquire info*/
6613  hdf_return = VSinquire (in_vdata_id, &nrecords, &interlace,
6614  fields, &vd_size, vd_name);
6615  if (hdf_return == FAIL)
6616  {
6617  returnStatus = MODIS_F_HDF_ERROR;
6618  L1BErrorMsg(location, returnStatus, NULL, "VSinquire",
6620  return returnStatus;
6621  }
6622  if (vd_size > MAX_VDATA_SIZE)
6623  {
6624  returnStatus = MODIS_F_NOK;
6625  L1BErrorMsg(location, returnStatus,
6626  "macro MAX_VDATA_SIZE is too small", NULL,
6628  "Either there is something wrong with the file or there is a code bug.",
6629  True);
6630  return returnStatus;
6631  }
6632 
6633  if (strcmp(vd_name, "Discarded Packets") == 0) /* skip "Discarded Packets" */
6634  {
6635  hdf_return = VSdetach (in_vdata_id);
6636  if (hdf_return == FAIL)
6637  {
6638  returnStatus = MODIS_F_HDF_ERROR;
6639  L1BErrorMsg(location, returnStatus, NULL,
6640  "VSdetach(\"Discarded Packets\")",
6642  return returnStatus;
6643  }
6644 
6645  continue;
6646  }
6647 
6648  if (nrecords == 0) /*empty vdata: skip it*/
6649  {
6650  hdf_return = VSdetach (in_vdata_id);
6651  if (hdf_return == FAIL)
6652  {
6653  returnStatus = MODIS_F_HDF_ERROR;
6654  L1BErrorMsg(location, returnStatus, NULL, "VSdetach(empty vdata)",
6656  return returnStatus;
6657  }
6658 
6659  continue;
6660  }
6661 
6662  /*continue processing non_empty vdata*/
6663  nfields = VFnfields (in_vdata_id);
6664  if (nfields == FAIL)
6665  {
6666  returnStatus = MODIS_F_HDF_ERROR;
6667  L1BErrorMsg(location, returnStatus, NULL, "VFnfields",
6669  return returnStatus;
6670  }
6671 
6672  /*attach a vdata to write*/
6673  out_vdata_id = VSattach (out_v_id, -1, "w");
6674  if (out_vdata_id == FAIL)
6675  {
6676  returnStatus = MODIS_F_HDF_ERROR;
6677  L1BErrorMsg(location, returnStatus, NULL, "VSattach",
6678  L1B_OBC_FILE, NULL, True);
6679  return returnStatus;
6680  }
6681 
6682  /*define fields*/
6683  for (field = 0; field < nfields; field++)
6684  {
6685  /*get info*/
6686  f_name = VFfieldname (in_vdata_id, field);
6687  if (f_name == NULL)
6688  {
6689  returnStatus = MODIS_F_HDF_ERROR;
6690  L1BErrorMsg(location, returnStatus, NULL, "VFfieldname",
6692  return returnStatus;
6693  }
6694 
6695  f_type = VFfieldtype (in_vdata_id, field);
6696  if (f_type == FAIL)
6697  {
6698  returnStatus = MODIS_F_HDF_ERROR;
6699  L1BErrorMsg(location, returnStatus, NULL, "VFfieldtype",
6701  return returnStatus;
6702  }
6703 
6704  f_order = VFfieldorder (in_vdata_id, field);
6705  if (f_order == FAIL)
6706  {
6707  returnStatus = MODIS_F_HDF_ERROR;
6708  L1BErrorMsg(location, returnStatus, NULL, "VFfieldorder",
6710  return returnStatus;
6711  }
6712 
6713  /*define field*/
6714  hdf_return = VSfdefine (out_vdata_id, f_name, f_type, f_order);
6715  if (hdf_return == FAIL)
6716  {
6717  returnStatus = MODIS_F_HDF_ERROR;
6718  L1BErrorMsg(location, returnStatus, NULL, "VSfdefine",
6719  L1B_OBC_FILE, NULL, True);
6720  return returnStatus;
6721  }
6722  }
6723 
6724  /*read*/
6725  hdf_return = VSsetfields (in_vdata_id, fields);
6726  if (hdf_return == FAIL)
6727  {
6728  returnStatus = MODIS_F_HDF_ERROR;
6729  L1BErrorMsg(location, returnStatus, NULL, "VSsetfields",
6731  return returnStatus;
6732  }
6733 
6734  hdf_return = VSread (in_vdata_id, (void *)buffer, nrecords, interlace);
6735  if (hdf_return == FAIL)
6736  {
6737  returnStatus = MODIS_F_READ_ERROR;
6738  L1BErrorMsg(location, returnStatus, NULL, "VSread",
6740  return returnStatus;
6741  }
6742 
6743  /*write*/
6744  hdf_return = VSsetname (out_vdata_id, vd_name);
6745  if (hdf_return == FAIL)
6746  {
6747  returnStatus = MODIS_F_HDF_ERROR;
6748  L1BErrorMsg(location, returnStatus, NULL, "VSsetname",
6749  L1B_OBC_FILE, NULL, True);
6750  return returnStatus;
6751  }
6752 
6753  hdf_return = VSsetfields (out_vdata_id, fields);
6754  if (hdf_return == FAIL)
6755  {
6756  returnStatus = MODIS_F_HDF_ERROR;
6757  L1BErrorMsg(location, returnStatus, NULL, "VSsetfields",
6758  L1B_OBC_FILE, NULL, True);
6759  return returnStatus;
6760  }
6761 
6762  hdf_return = VSwrite (out_vdata_id, (void *)buffer, nrecords, interlace);
6763  if (hdf_return == FAIL)
6764  {
6765  returnStatus = MODIS_F_WRITE_ERROR;
6766  L1BErrorMsg(location, returnStatus, NULL, "VSwrite",
6767  L1B_OBC_FILE, NULL, True);
6768  return returnStatus;
6769  }
6770 
6771  /*done with this vdata*/
6772  hdf_return = VSdetach (in_vdata_id);
6773  if (hdf_return == FAIL)
6774  {
6775  returnStatus = MODIS_F_READ_ERROR;
6776  L1BErrorMsg(location, returnStatus, NULL, "VSdetach",
6778  return returnStatus;
6779  }
6780 
6781  hdf_return = VSdetach (out_vdata_id);
6782  if (hdf_return == FAIL)
6783  {
6784  returnStatus = MODIS_F_READ_ERROR;
6785  L1BErrorMsg(location, returnStatus, NULL, "VSdetach",
6786  L1B_OBC_FILE, NULL, True);
6787  return returnStatus;
6788  }
6789 
6790  } /*End of loop over all vdata*/
6791 
6792  return returnStatus;
6793 }
6794 
6795 PGSt_SMF_status Check_For_Moon_in_SV_KOB
6796  (int32 num_scans,
6797  common_QA_tables_t *common_QA_tables,
6798  QA_Data_t *QA,
6799  Moon_arrays_t *moon_arrays)
6800 /*
6801 !C**********************************************************************
6802 !Description:
6803  For each scan of the middle granule, determine if the center of the
6804  moon lies within the space-view (SV) keep-out box (KOB). This sets
6805  values to be used later in determining the DN offset and for writing
6806  one of the "bit QA flags" in the scan metadata.
6807 
6808 !Input Parameters:
6809  int32 num_scans Number of scans in the middle L1A
6810  granule.
6811  common_QA_tables_t *common_QA_tables
6812  Contains: float32 moon_offset_limits
6813  Defines the offsets from the SV
6814  port center in 1km units.
6815  Dimensions: [NUM_BANDS][4]
6816 !Output Parameters:
6817  QA_Data_t *QA Used to set the appropriate
6818  "Bit QA Flags" value in L1B_Setup.
6819  Moon_arrays_t *moon_arrays keep the moon vector values and
6820  flags denoting if center of
6821  moon is within the keep-out
6822  box for every scan and band.
6823 !Revision History:
6824  Revision 01.00 April 1999
6825  Initial development
6826  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
6827  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
6828 
6829 !Team-unique Header:
6830  This software is developed by the MODIS Characterization Support
6831  Team (MCST)for the National Aeronautics and Space Administration,
6832  Goddard Space Flight Center, under contract NAS5-32373.
6833 
6834 !References and Credits:
6835  HDF portions developed at the National Center for Supercomputing
6836  Applications at the University of Illinois at Urbana-Champaign.
6837 
6838 !Design Notes:
6839  According to James Kuyper (email, Jun 3, 1999) the magnitude of the
6840  moon vector should be 1 if successfully computed or 0 if not. There also
6841  could be "FloatInf" values (fill values) in some simulated data sets.
6842  The logic of this function is that a value of UNDETERMINED is assigned
6843  for either a zero magnitude moon vector or values of the components
6844  out of the range -1 through 1, inclusive.
6845 
6846 !END********************************************************************
6847 */
6848 {
6849  PGSt_SMF_status returnStatus = MODIS_S_OK;
6850  PGSt_integer Version = 1;
6851  int32 geo_sd_id;
6852  char fname[512];
6853  int32 B;
6854  int32 S;
6855  int32 num_scans_geo;
6856  float32 distance_square;
6857  float32 moon_scan_offset;
6858  float32 moon_track_offset;
6859  intn hdf_return;
6860  int16 band_is_RSB[NUM_BANDS] = {1, 1, 1, 1, 1, 1,
6861  1, 1, 1, 1, 1, 1,
6862  1, 1, 1, 1, 1, 1,
6863  1, 1, 1, 0, 0, 0,
6864  0, 0, 0, 1, 0, 0,
6865  0, 0,0, 0, 0, 0, 0, 0};
6866 
6867  float32 x, y, z;
6868  char *location = "Check_For_Moon_in_SV_KOB";
6869 
6870  if (PGS_PC_GetReference(GEOLOCATION_FILE, &Version, fname) != PGS_S_SUCCESS)
6871  {
6872  returnStatus = MODIS_F_FILE_NOT_FOUND;
6873  L1BErrorMsg(location, returnStatus,
6874  "Could not retrieve file name from PCF.",
6875  "PGS_PC_GetReference", GEOLOCATION_FILE, NULL, True);
6876  return returnStatus;
6877  }
6878 
6879  geo_sd_id = SDstart(fname, DFACC_RDONLY);
6880  if (geo_sd_id == FAIL)
6881  {
6882  returnStatus = MODIS_F_FILE_NOT_OPENED;
6883  L1BErrorMsg(location, returnStatus,
6884  "Could not open file for SD read access.",
6885  "SDstart", GEOLOCATION_FILE,
6886  "The file may be missing, corrupted or not an HDF-4 file.",
6887  True);
6888  return returnStatus;
6889  }
6890 
6891  returnStatus = read_attribute(geo_sd_id,
6893  DFNT_INT32,
6894  &num_scans_geo);
6895  if (returnStatus != MODIS_S_OK)
6896  {
6897  L1BErrorMsg(location, returnStatus, NULL,
6898  "read_attribute", GEOLOCATION_FILE, NULL, True);
6899  return returnStatus;
6900  }
6901 
6902  if (num_scans_geo != num_scans)
6903  {
6904  returnStatus = MODIS_F_OUT_OF_RANGE;
6905  L1BErrorMsg(location, returnStatus,
6906  "Number of scans in GEO file does not match the current L1A file.",
6907  NULL, GEOLOCATION_FILE, "The PCF may have the wrong names.", True);
6908  return returnStatus;
6909  }
6910 
6911  returnStatus = read_sds_rank2(geo_sd_id,
6913  num_scans,
6914  VEC_DIM,
6915  moon_arrays->moon_vector);
6916  if (returnStatus != MODIS_S_OK)
6917  {
6918  L1BErrorMsg(location, returnStatus, NULL,
6919  "read_sds_rank2", GEOLOCATION_FILE, NULL, True);
6920  return returnStatus;
6921  }
6922 
6923  hdf_return = SDend(geo_sd_id);
6924  if (hdf_return == FAIL)
6925  {
6926  returnStatus = MODIS_F_HDF_ERROR;
6927  L1BErrorMsg(location, returnStatus, NULL, "SDend", GEOLOCATION_FILE,
6928  "Memory or the disk file must have become corrupted.", True);
6929  return returnStatus;
6930  }
6931 
6932  for (S = 0; S < num_scans; S++)
6933  {
6936 
6937  x = moon_arrays->moon_vector[S][0];
6938  y = moon_arrays->moon_vector[S][1];
6939  z = moon_arrays->moon_vector[S][2];
6940 
6941  /*
6942  * Check that vector components are within range.
6943  * If so, then cannot compute.
6944  */
6945 
6946  if (x > 1.01 || x < -1.01 || y > 1.01 ||
6947  y < -1.01 || z > 1.01 || z < -1.01)
6948  {
6949  for (B = 0; B < NUM_BANDS; B++)
6950  moon_arrays->moon_in_SV_KOB[S][B] = UNDETERMINED_MOON_IN_SV_KOB;
6951  continue;
6952  }
6953 
6954  distance_square = x * x + y * y + z * z;
6955 
6956  /* Check that magnitude is not zero. IF so, then cannot compute */
6957 
6958  if (distance_square < TOLERANCE)
6959  {
6960  for (B = 0; B < NUM_BANDS; B++)
6961  moon_arrays->moon_in_SV_KOB[S][B] = UNDETERMINED_MOON_IN_SV_KOB;
6962  continue;
6963  }
6964  moon_track_offset = - asin((double)x / sqrt((double)distance_square)) /
6966  moon_scan_offset = (atan2((double)z, (double)y) - SV_CNTR_ANG_FROM_Y) /
6968  for (B = 0; B < NUM_BANDS; B++)
6969  {
6970  if (moon_track_offset <=
6971  common_QA_tables->moon_offset_limits[B][TRK_UPPER] &&
6972  moon_track_offset >=
6973  common_QA_tables->moon_offset_limits[B][TRK_LOWER] &&
6974  moon_scan_offset <=
6975  common_QA_tables->moon_offset_limits[B][SCN_UPPER] &&
6976  moon_scan_offset >=
6977  common_QA_tables->moon_offset_limits[B][SCN_LOWER])
6978  {
6979  moon_arrays->moon_in_SV_KOB[S][B] = MOON_INSIDE_SV_KOB;
6980  if (band_is_RSB[B] == 1)
6982  else
6984  }
6985  else
6986  moon_arrays->moon_in_SV_KOB[S][B] = MOON_OUTSIDE_SV_KOB;
6987  }/* end loop through bands */
6988  }/* end loop throught scans */
6989 
6990  return (returnStatus);
6991 }
6992 
6993 PGSt_SMF_status Fill_250m_DN_OBC_Avg(int32 sd_id,
6994  int32 num_scans,
6995  int16 *MirrorSide,
6996  refl_tables_t *refl_tables,
6997  Moon_arrays_t *moon_arrays,
6998  boolean Ecal_On[][NUM_BANDS],
6999  DN_OBC_Avg_t *DN_OBC_Avg,
7000  QA_Refl_t *QA_refl)
7001 /*
7002 !C**********************************************************************
7003 !Description:
7004  Compute the DN OBC averages for the 250m resolution bands. Store in
7005  DN_OBC_Avg for writing to the OBC file and for use in the reflective
7006  algorithm.
7007 
7008 !Input Parameters:
7009  int32 sd_id SD file access ID for the L1A middle
7010  granule.
7011  int32 num_scans Number of scans in the middle granule.
7012  int16 *MirrorSide Mirror side indexes per scan
7013  refl_tables_t *refl_tables Structure which contains all reflective
7014  LUTs
7015  Moon_arrays_t *moon_arrays Structure containing the moon_in_SV_KOB
7016  array.
7017  boolean Ecal_On[][NUM_BANDS] Ecal on information for each band for
7018  each scan.
7019  Preprocess_Refl_t *PP_Refl Structure containing DN saturation value.
7020 
7021 !Output Parameters:
7022  DN_OBC_Avg_t DN_OBC_Avg Structure containing arrays that will
7023  ultimately be written to the OBC file.
7024  QA_Refl_t QA_refl Depending on processing values, some
7025  elements of these may be tripped.
7026 
7027 !Revision History:
7028 
7029 
7030  Revision 01.10 March 25, 2002 Razor Issue #178
7031  Strip out ADC Correction
7032  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
7033 
7034  Revision 01.05, March 26, 2001, Razor Issue #159
7035  Changed DN_upper_valid_limit to SATURATED_DN - 1.
7036  Alice Isaacman (Alice.R.Isaacman.1@gsfc.nasa.gov)
7037 
7038  Revision 01.04, Dec 7, 2000, Razor issue 146
7039  Removed DN_sat_prime.
7040  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
7041 
7042  Revision 01.03 Oct. 22, 1999
7043  Added checking Ecal on
7044  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
7045 
7046  Revision 01.02 August 28, 1999
7047  Added checking if the data read from L1A are valid.
7048  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
7049 
7050  Revision 01.01 August, 1999
7051  Implement changes to meet the requirements of the new ADC algorithm. See SDF.
7052  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
7053  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
7054 
7055  Revision 01.00 April, 1999
7056  Initial development
7057  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
7058  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
7059 
7060 !Team-unique Header:
7061  This software is developed by the MODIS Characterization Support
7062  Team (MCST)for the National Aeronautics and Space Administration,
7063  Goddard Space Flight Center, under contract NAS5-32373.
7064 
7065 !References and Credits:
7066  HDF portions developed at the National Center for Supercomputing
7067  Applications at the University of Illinois at Urbana-Champaign.
7068 
7069 !Design Notes:
7070 
7071 !END********************************************************************
7072 */
7073 {
7074  PGSt_SMF_status returnStatus = MODIS_S_OK;
7075 
7076  typedef int16 SV_250m_t[NUM_250M_BANDS][MAX_250M_OBC_FRAME_DIM];
7077  SV_250m_t *SV_250m;
7078  SV_250m = (SV_250m_t*) malloc(MAX_250M_TRACK_DIM * sizeof(SV_250m_t));
7079  typedef int16 BB_250m_t[NUM_250M_BANDS][MAX_250M_OBC_FRAME_DIM];
7080  BB_250m_t *BB_250m;
7081  BB_250m = (BB_250m_t*) malloc(MAX_250M_TRACK_DIM * sizeof(BB_250m_t));
7082 
7083  int32 S;
7084  int32 D;
7085  int32 T;
7086  int32 B;
7087  int32 subsamp;
7088  int32 increment;
7089  int16 rejects[MAX_1KM_OBC_FRAME_DIM];
7090  int16 DN_upper_valid_limit;
7091  int16 MS;
7092  float32 mean;
7093  float32 sdev;
7094  int32 track_dim;
7095  int32 band_dim;
7096  int32 frame_dim;
7097  int32 F;
7098  char *location = "Fill_250m_DN_OBC_Avg";
7099 
7100  track_dim = num_scans * DETECT_PER_BAND_AT_RES[INDEX_250M];
7101  band_dim = NUM_250M_BANDS;
7103  increment = BAND_RATIO_AT_RES[INDEX_250M];
7104 
7105  /*
7106  * Initialize arrays (in case we skip scans due to Mirror Side).
7107  */
7108 
7109  for (T = 0; T < MAX_250M_TRACK_DIM; T++) {
7110  for (B = 0; B < NUM_250M_BANDS; B++) {
7111  for (subsamp = 0; subsamp < NUM_250M_SUBSAMP; subsamp++) {
7112  DN_OBC_Avg->DN_obc_250m_avg[T][B][subsamp] = -1;
7113  DN_OBC_Avg->DN_obc_250m_var[T][B][subsamp] = 0;
7114  DN_OBC_Avg->DN_obc_250m_outlier_mask[T][B][subsamp][0] = 0;
7115  DN_OBC_Avg->DN_obc_250m_outlier_mask[T][B][subsamp][1] = 0;
7116  }
7117  }
7118  }
7119 
7120  /*
7121  * Read SV DNs from L1A middle granule and check for valid range.
7122  */
7123 
7124  returnStatus = read_sds_rank3(sd_id,
7126  track_dim,
7127  band_dim,
7128  frame_dim,
7129  SV_250m);
7130  if (returnStatus != MODIS_S_OK)
7131  {
7132  L1BErrorMsg(location, returnStatus, NULL, "read_sds_rank3",
7134  return returnStatus;
7135  }
7136 
7137  returnStatus = Check_Valid_Range("SV_250m",
7138  DFNT_INT16,
7139  L1A_DN_SDS_LB,
7140  L1A_DN_SDS_UB,
7141  L1A_DN_SDS_FV,
7142  (track_dim*band_dim*frame_dim),
7143  (void *) SV_250m);
7144  if (returnStatus != MODIS_S_OK)
7145  {
7146  L1BErrorMsg(location, returnStatus, NULL, "Check_Valid_Range",
7148  return returnStatus;
7149  }
7150 
7151  /*
7152  * Read BB DNs from L1A middle granule and check for valid range.
7153  */
7154 
7155  returnStatus = read_sds_rank3(sd_id,
7157  track_dim,
7158  band_dim,
7159  frame_dim,
7160  BB_250m);
7161  if (returnStatus != MODIS_S_OK)
7162  {
7163  L1BErrorMsg(location, returnStatus, NULL, "read_sds_rank3",
7165  return returnStatus;
7166  }
7167 
7168  returnStatus = Check_Valid_Range("BB_250m", DFNT_INT16,
7169  L1A_DN_SDS_LB,
7170  L1A_DN_SDS_UB,
7171  L1A_DN_SDS_FV,
7172  (track_dim*band_dim*frame_dim),
7173  (void *) BB_250m);
7174  if (returnStatus != MODIS_S_OK)
7175  {
7176  L1BErrorMsg(location, returnStatus, NULL, "Check_Valid_Range",
7178  return returnStatus;
7179  }
7180 
7181  for (S = 0; S < num_scans; S++)
7182  {
7183  MS = MirrorSide[S];
7184  if (MS != 0 && MS != 1) continue; /* Skip this scan */
7185 
7186  for (D = 0; D < DETECTORS_PER_250M_BAND; D++)
7187  {
7188  T = S * DETECTORS_PER_250M_BAND + D;
7189  for (B = 0; B < NUM_250M_BANDS; B++)
7190  {
7191  for (subsamp = 0; subsamp < BAND_RATIO_AT_RES[INDEX_250M]; subsamp++)
7192  {
7193  for (F = 0; F < MAX_1KM_OBC_FRAME_DIM; F++)
7194  rejects[F] = 0;
7195  DN_upper_valid_limit = SATURATED_DN - 1;
7196 
7197  if (Ecal_On[S][B] == True)
7198  {
7199  mean = -1;
7200  sdev = 0;
7201  }
7202  else if (moon_arrays->moon_in_SV_KOB[S][B] == MOON_INSIDE_SV_KOB)
7203  {
7204  returnStatus =
7206  refl_tables->RSB_SV_DN_moon_include_frames,
7207  subsamp,
7208  SV_1km_FRAMES,
7209  increment,
7210  SV_250m[T][B],
7211  DN_upper_valid_limit,
7212  0,
7213  &mean,
7214  &sdev,
7215  &rejects[0]);
7216  if (returnStatus != MODIS_S_OK)
7217  SMF_ERROR(returnStatus,
7218  "Get_DN_Avg_SDev_Rejects_LowN() in Fill_250m_DN_OBC_Avg()");
7219  }
7220  else
7221  {
7222  returnStatus =
7224  refl_tables->DN_obc_avg_first_frame_to_use
7225  * BAND_RATIO_AT_RES[INDEX_250M] + subsamp,
7227  increment,
7228  SV_250m[T][B],
7229  DN_upper_valid_limit,
7230  0,
7231  &mean,
7232  &sdev,
7233  &rejects[refl_tables->DN_obc_avg_first_frame_to_use]);
7234  if (returnStatus != MODIS_S_OK)
7235  SMF_ERROR(returnStatus,
7236  "Get_DN_Avg_SDev_Rejects() in Fill_250m_DN_OBC_Avg()");
7237  }
7238  if (mean < 0)
7239  {
7240  QA_refl->all_SV_DN_bad[S] = 1;
7241  returnStatus =
7243  refl_tables->DN_obc_avg_first_frame_to_use
7244  * BAND_RATIO_AT_RES[INDEX_250M] + subsamp,
7246  increment,
7247  BB_250m[T][B],
7248  DN_upper_valid_limit,
7249  0,
7250  &mean,
7251  &sdev,
7252  &rejects[refl_tables->DN_obc_avg_first_frame_to_use]);
7253  if (returnStatus != MODIS_S_OK)
7254  SMF_ERROR(returnStatus,
7255  "Get_DN_Avg_SDev_Rejects() in Fill_250m_DN_OBC_Avg()");
7256  }
7257 
7258  if (mean < 0)
7259  QA_refl->all_BB_DN_bad[S] = 1;
7260 
7261  DN_OBC_Avg->DN_obc_250m_avg[T][B][subsamp] = mean;
7262  DN_OBC_Avg->DN_obc_250m_var[T][B][subsamp] = sdev * sdev;
7263  DN_OBC_Avg->DN_obc_250m_outlier_mask[T][B][subsamp][0] = 0;
7264  DN_OBC_Avg->DN_obc_250m_outlier_mask[T][B][subsamp][1] = 0;
7265  returnStatus =
7267  DN_OBC_Avg->DN_obc_250m_outlier_mask[T][B][subsamp]);
7268  }/* end loop through subsamples */
7269  }/* end loop through bands */
7270  }/* end loop through detector */
7271  }/* end loop through scans */
7272 
7273  free(SV_250m);
7274  free(BB_250m);
7275 
7276  return (returnStatus);
7277 }
7278 
7279 PGSt_SMF_status Fill_500m_DN_OBC_Avg(int32 sd_id,
7280  int32 num_scans,
7281  int16 *MirrorSide,
7282  refl_tables_t *refl_tables,
7283  Moon_arrays_t *moon_arrays,
7284  boolean Ecal_On[][NUM_BANDS],
7285  DN_OBC_Avg_t *DN_OBC_Avg,
7286  QA_Refl_t *QA_refl)
7287 /*
7288 !C**********************************************************************
7289 !Description:
7290  Compute the DN OBC averages for the 500m resolution bands. Store in
7291  DN_OBC_Avg for writing to the OBC file and use in the reflective algorithm.
7292 
7293 !Input Parameters:
7294  int32 sd_id SD file access ID for the L1A middle
7295  granule.
7296  int32 num_scans Number of scans in the middle granule.
7297  int16 *MirrorSide Mirror side indexes per scan
7298  refl_tables_t *refl_tables Structure which contains all reflective
7299  LUTs
7300  Moon_arrays_t *moon_arrays Structure containing the moon_in_SV_KOB
7301  array.
7302  boolean Ecal_On[][NUM_BANDS] Ecal on information for each band for
7303  each scan.
7304  Preprocess_Refl_t *PP_Refl Structure containing DN saturation value.
7305 
7306 !Output Parameters:
7307  DN_OBC_Avg_t DN_OBC_Avg Structure containing arrays that will
7308  ultimately be written to the OBC file.
7309  QA_Refl_t QA_refl Depending on processing values, some
7310  elements of these may be tripped.
7311 
7312 !Revision History:
7313 
7314  Revision 01.10 March 25, 2002 Razor Issue #178
7315  Strip out ADC Correction
7316  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
7317 
7318  Revision 01.06, March 26, 2001, Razor Issue 159
7319  Changed DN_upper_valid_limit to SATURATED_DN - 1.
7320  Alice Isaacman (Alice.R.Isaacman.1@gsfc.nasa.gov)
7321 
7322  Revision 01.05, Dec 7, 2000, Razor issue 146
7323  Removed DN_sat_prime.
7324  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
7325 
7326  Revision 01.04 Oct. 22, 1999
7327  Added checking for ecal on
7328  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
7329  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
7330 
7331  Revision 01.03 Sept. 2, 1999
7332  Implemented changes to meet the requirements of the new SWIR algorithm.
7333  See SDF.
7334  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
7335  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
7336 
7337  Revision 01.02 August 28, 1999
7338  Added checking if the data read from L1A are valid.
7339  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
7340 
7341  Revision 01.01 August, 1999
7342  Implement changes to meet the requirements of the new ADC algorithm. See SDF.
7343  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
7344  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
7345 
7346  Revision 01.00 April 1999
7347  Initial development
7348  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
7349  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
7350 
7351 !Team-unique Header:
7352  This software is developed by the MODIS Characterization Support
7353  Team (MCST)for the National Aeronautics and Space Administration,
7354  Goddard Space Flight Center, under contract NAS5-32373.
7355 
7356 !References and Credits:
7357  HDF portions developed at the National Center for Supercomputing
7358  Applications at the University of Illinois at Urbana-Champaign.
7359 
7360 !Design Notes:
7361 
7362 !END********************************************************************
7363 */
7364 {
7365  PGSt_SMF_status returnStatus = MODIS_S_OK;
7366 
7367  typedef int16 SV_500m_t[NUM_500M_BANDS][MAX_500M_OBC_FRAME_DIM];
7368  SV_500m_t *SV_500m;
7369  SV_500m = (SV_500m_t*) malloc(MAX_500M_TRACK_DIM * sizeof(SV_500m_t));
7370  typedef int16 BB_500m_t[NUM_500M_BANDS][MAX_500M_OBC_FRAME_DIM];
7371  BB_500m_t *BB_500m;
7372  BB_500m = (BB_500m_t*) malloc(MAX_500M_TRACK_DIM * sizeof(BB_500m_t));
7373 
7374  int32 S;
7375  int32 D;
7376  int32 T;
7377  int32 B;
7378  int32 B_38;
7379  int32 subsamp;
7380  int32 increment;
7381  int16 rejects[MAX_1KM_OBC_FRAME_DIM];
7382  int16 DN_upper_valid_limit;
7383  int16 MS;
7384  float32 mean;
7385  float32 sdev;
7386  int32 track_dim;
7387  int32 band_dim;
7388  int32 frame_dim;
7389  int32 F;
7390  char *location = "Fill_500m_DN_OBC_Avg";
7391 
7392  track_dim = num_scans * DETECT_PER_BAND_AT_RES[INDEX_500M];
7393  band_dim = NUM_500M_BANDS;
7395  increment = BAND_RATIO_AT_RES[INDEX_500M];
7396 
7397  /*
7398  * Initialize arrays (in case we skip scans to due Mirror Side).
7399  */
7400 
7401  for (T = 0; T < MAX_500M_TRACK_DIM; T++) {
7402  for (B = 0; B < NUM_500M_BANDS; B++) {
7403  for (subsamp = 0; subsamp < NUM_500M_SUBSAMP; subsamp++) {
7404  DN_OBC_Avg->DN_obc_500m_avg[T][B][subsamp] = -1;
7405  DN_OBC_Avg->DN_obc_500m_var[T][B][subsamp] = 0;
7406  DN_OBC_Avg->DN_obc_500m_outlier_mask[T][B][subsamp][0] = 0;
7407  DN_OBC_Avg->DN_obc_500m_outlier_mask[T][B][subsamp][1] = 0;
7408  }
7409  }
7410  }
7411 
7412  /*
7413  * Read SV DNs from L1A middle granule and check for valid range.
7414  */
7415 
7416  returnStatus = read_sds_rank3(sd_id,
7418  track_dim,
7419  band_dim,
7420  frame_dim,
7421  SV_500m);
7422  if (returnStatus != MODIS_S_OK)
7423  {
7424  L1BErrorMsg(location, returnStatus, NULL, "read_sds_rank3",
7426  return returnStatus;
7427  }
7428 
7429  returnStatus = Check_Valid_Range("SV_500m",
7430  DFNT_INT16,
7431  L1A_DN_SDS_LB,
7432  L1A_DN_SDS_UB,
7433  L1A_DN_SDS_FV,
7434  (track_dim*band_dim*frame_dim),
7435  (void *) SV_500m);
7436  if (returnStatus != MODIS_S_OK)
7437  {
7438  L1BErrorMsg(location, returnStatus, NULL, "Check_Valid_Range",
7440  return returnStatus;
7441  }
7442 
7443  /*
7444  * Read BB DNs from L1A middle granule and check for valid range.
7445  */
7446 
7447  returnStatus = read_sds_rank3(sd_id,
7449  track_dim,
7450  band_dim,
7451  frame_dim,
7452  BB_500m);
7453  if (returnStatus != MODIS_S_OK)
7454  {
7455  L1BErrorMsg(location, returnStatus, NULL, "read_sds_rank3",
7457  return returnStatus;
7458  }
7459 
7460  returnStatus = Check_Valid_Range("BB_500m",
7461  DFNT_INT16,
7462  L1A_DN_SDS_LB,
7463  L1A_DN_SDS_UB,
7464  L1A_DN_SDS_FV,
7465  (track_dim*band_dim*frame_dim),
7466  (void *) BB_500m);
7467  if (returnStatus != MODIS_S_OK)
7468  {
7469  L1BErrorMsg(location, returnStatus, NULL, "Check_Valid_Range",
7471  return returnStatus;
7472  }
7473 
7474  for (S = 0; S < num_scans; S++)
7475  {
7476  MS = MirrorSide[S];
7477  if (MS != 0 && MS != 1) continue; /* Skip this scan */
7478 
7479  for (D = 0; D < DETECTORS_PER_500M_BAND; D++)
7480  {
7481  T = S * DETECTORS_PER_500M_BAND + D;
7482  for (B = 0; B < NUM_500M_BANDS; B++)
7483  {
7484  B_38 = B + NUM_250M_BANDS;
7485  for (subsamp = 0;
7486  subsamp < BAND_RATIO_AT_RES[INDEX_500M]; subsamp++)
7487  {
7488  for (F = 0; F < MAX_1KM_OBC_FRAME_DIM; F++)
7489  rejects[F] = 0;
7490  DN_upper_valid_limit = SATURATED_DN - 1;
7491 
7492  if (Ecal_On[S][B_38] == True)
7493  {
7494  mean = -1;
7495  sdev = 0;
7496  }
7497  else if (moon_arrays->moon_in_SV_KOB[S][B_38] ==
7499  {
7500  returnStatus = Get_DN_Avg_SDev_Rejects_LowN(
7501  refl_tables->RSB_SV_DN_moon_include_frames,
7502  subsamp,
7503  SV_1km_FRAMES,
7504  increment,
7505  SV_500m[T][B],
7506  DN_upper_valid_limit,
7507  0,
7508  &mean,
7509  &sdev,
7510  &rejects[0]);
7511  if (returnStatus != MODIS_S_OK)
7512  SMF_ERROR(returnStatus,
7513  "Get_DN_Avg_SDev_Rejects_LowN() in Fill_500m_DN_OBC_Avg()");
7514  }
7515  else
7516  {
7517  returnStatus =
7519  refl_tables->DN_obc_avg_first_frame_to_use
7520  * BAND_RATIO_AT_RES[INDEX_500M] + subsamp,
7522  increment,
7523  SV_500m[T][B],
7524  DN_upper_valid_limit,
7525  0,
7526  &mean,
7527  &sdev,
7528  &rejects[refl_tables->DN_obc_avg_first_frame_to_use]);
7529  if (returnStatus != MODIS_S_OK)
7530  SMF_ERROR(returnStatus,
7531  "Get_DN_Avg_SDev_Rejects() in Fill_500m_DN_OBC_Avg()");
7532  }
7533  if (mean < 0)
7534  QA_refl->all_SV_DN_bad[S] = 1;
7535  if (mean < 0 && B < 2) /* only use BB DNs for bands 3 and 4 */
7536  {
7537  returnStatus =
7539  refl_tables->DN_obc_avg_first_frame_to_use
7540  * BAND_RATIO_AT_RES[INDEX_500M] + subsamp,
7542  increment,
7543  BB_500m[T][B],
7544  DN_upper_valid_limit,
7545  0,
7546  &mean,
7547  &sdev,
7548  &rejects[refl_tables->DN_obc_avg_first_frame_to_use]);
7549  if (returnStatus != MODIS_S_OK)
7550  SMF_ERROR(returnStatus,
7551  "Get_DN_Avg_SDev_Rejects() in Fill_500m_DN_OBC_Avg()");
7552  if (mean < 0)
7553  QA_refl->all_BB_DN_bad[S] = 1;
7554  }
7555 
7556  DN_OBC_Avg->DN_obc_500m_avg[T][B][subsamp] = mean;
7557  DN_OBC_Avg->DN_obc_500m_var[T][B][subsamp] = sdev * sdev;
7558  DN_OBC_Avg->DN_obc_500m_outlier_mask[T][B][subsamp][0] = 0;
7559  DN_OBC_Avg->DN_obc_500m_outlier_mask[T][B][subsamp][1] = 0;
7560  returnStatus =
7562  rejects,
7563  DN_OBC_Avg->DN_obc_500m_outlier_mask[T][B][subsamp]);
7564  }/* end loop through subsamples */
7565  }/* end loop through bands */
7566  }/* end loop through detector */
7567  }/* end loop through scans */
7568 
7569  free(SV_500m);
7570  free(BB_500m);
7571 
7572  return (returnStatus);
7573 }
7574 
7575 PGSt_SMF_status Fill_1km_day_DN_OBC_Avg
7576  (int32 sd_id,
7577  int32 num_scans,
7578  int16 *MirrorSide,
7579  refl_tables_t *refl_tables,
7580  Moon_arrays_t *moon_arrays,
7581  boolean Ecal_On[][NUM_BANDS],
7582  DN_OBC_Avg_t *DN_OBC_Avg,
7583  QA_Refl_t *QA_refl)
7584 /*
7585 !C**********************************************************************
7586 !Description:
7587  Compute the DN OBC averages for the 1km day resolution bands. Store in
7588  DN_OBC_Avg for writing to the OBC file for use in the reflective algorithm.
7589 
7590 !Input Parameters:
7591  int32 sd_id SD file access ID for the L1A middle
7592  granule.
7593  int32 num_scans Number of scans in the middle granule.
7594  int16 *MirrorSide Mirror side indexes per scan
7595  refl_tables_t *refl_tables Structure which contains all reflective
7596  LUTs
7597  Moon_arrays_t *moon_arrays Structure containing the moon_in_SV_KOB
7598  array.
7599  boolean Ecal_On[][NUM_BANDS] Ecal on information for each band for
7600  each scan.
7601  Preprocess_Refl_t *PP_Refl Structure containing DN saturation value.
7602 
7603 !Output Parameters:
7604  DN_OBC_Avg_t DN_OBC_Avg Structure containing arrays that will
7605  ultimately be written to the OBC file.
7606  QA_Refl_t QA_refl Depending on processing values, some
7607  elements of these may be tripped.
7608 
7609 !Revision History:
7610 
7611  Revision 01.10 March 25, 2002 Razor Issue #178
7612  Strip out ADC Correction
7613  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
7614 
7615  Revision 01.05, March 26, 2001, Razor Issue #159
7616  Changed DN_upper_valid_limit to SATURATED_DN - 1.
7617  Alice Isaacman (Alice.R.Isaacman.1@gsfc.nasa.gov)
7618 
7619  Revision 01.04, Dec 7, 2000, Razor issue 146
7620  Removed DN_sat_prime.
7621  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
7622 
7623  Revision 01.03 Oct. 22, 1999
7624  Added checking for Ecal on
7625  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
7626 
7627  Revision 01.02 August 28, 1999
7628  Added checking if the data read from L1A are valid.
7629  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
7630 
7631  Revision 01.01 August, 1999
7632  Implement changes to meet the requirements of the new ADC algorithm. See SDF.
7633  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
7634  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
7635 
7636  Revision 01.00 April 1999
7637  Initial development
7638  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
7639  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
7640 
7641 !Team-unique Header:
7642  This software is developed by the MODIS Characterization Support
7643  Team (MCST)for the National Aeronautics and Space Administration,
7644  Goddard Space Flight Center, under contract NAS5-32373.
7645 
7646 !References and Credits:
7647  HDF portions developed at the National Center for Supercomputing
7648  Applications at the University of Illinois at Urbana-Champaign.
7649 
7650 !Design Notes:
7651 
7652 !END********************************************************************
7653 */
7654 {
7655  PGSt_SMF_status returnStatus = MODIS_S_OK;
7656 
7657  typedef int16 SV_1km_day_t[NUM_1000M_DAY_BANDS][MAX_1KM_OBC_FRAME_DIM];
7658  SV_1km_day_t *SV_1km_day;
7659  SV_1km_day = (SV_1km_day_t*) malloc(MAX_1KM_TRACK_DIM * sizeof(SV_1km_day_t));
7660  typedef int16 BB_1km_day_t[NUM_1000M_DAY_BANDS][MAX_1KM_OBC_FRAME_DIM];
7661  BB_1km_day_t *BB_1km_day;
7662  BB_1km_day = (BB_1km_day_t*) malloc(MAX_1KM_TRACK_DIM * sizeof(BB_1km_day_t));
7663 
7664  int32 S;
7665  int32 D;
7666  int32 T;
7667  int32 B;
7668  int32 B_38;
7669  int32 subsamp;
7670  int32 increment;
7671  int16 rejects[MAX_1KM_OBC_FRAME_DIM];
7672  int16 DN_upper_valid_limit;
7673  int16 MS;
7674  float32 mean;
7675  float32 sdev;
7676  int32 track_dim;
7677  int32 band_dim;
7678  int32 frame_dim;
7679  int32 F;
7680  char *location = "Fill_1km_day_DN_OBC_Avg";
7681 
7682  track_dim = num_scans * DETECTORS_PER_1KM_BAND;
7683  band_dim = NUM_1000M_DAY_BANDS;
7685  increment = BAND_RATIO_AT_RES[INDEX_1000M_DAY];
7686 
7687  /*
7688  * Initialize arrays (in case we skip scans to due Mirror Side).
7689  */
7690 
7691  for (T = 0; T < MAX_1KM_TRACK_DIM; T++) {
7692  for (B = 0; B < NUM_1000M_DAY_BANDS; B++) {
7693  for (subsamp = 0; subsamp < NUM_1KM_SUBSAMP; subsamp++) {
7694  DN_OBC_Avg->DN_obc_1km_day_avg[T][B][subsamp] = -1;
7695  DN_OBC_Avg->DN_obc_1km_day_var[T][B][subsamp] = 0;
7696  DN_OBC_Avg->DN_obc_1km_day_outlier_mask[T][B][subsamp][0] = 0;
7697  DN_OBC_Avg->DN_obc_1km_day_outlier_mask[T][B][subsamp][1] = 0;
7698  }
7699  }
7700  }
7701 
7702  /*
7703  * Read SV DNs from L1A middle granule and check for valid range.
7704  */
7705 
7706  returnStatus = read_sds_rank3(sd_id,
7708  track_dim,
7709  band_dim,
7710  frame_dim,
7711  SV_1km_day);
7712  if (returnStatus != MODIS_S_OK)
7713  {
7714  L1BErrorMsg(location, returnStatus, NULL, "read_sds_rank3",
7716  return returnStatus;
7717  }
7718 
7719  returnStatus = Check_Valid_Range("SV_1km_day", DFNT_INT16,
7720  L1A_DN_SDS_LB,
7721  L1A_DN_SDS_UB,
7722  L1A_DN_SDS_FV,
7723  (track_dim*band_dim*frame_dim),
7724  (void *) SV_1km_day);
7725  if (returnStatus != MODIS_S_OK)
7726  {
7727  L1BErrorMsg(location, returnStatus, NULL, "Check_Valid_Range",
7729  return returnStatus;
7730  }
7731 
7732  /*
7733  * Read BB DNs from L1A middle granule and check for valid range.
7734  */
7735 
7736  returnStatus = read_sds_rank3(sd_id,
7738  band_dim,
7739  frame_dim,
7740  BB_1km_day);
7741  if (returnStatus != MODIS_S_OK)
7742  {
7743  L1BErrorMsg(location, returnStatus, NULL, "read_sds_rank3",
7745  return returnStatus;
7746  }
7747 
7748  returnStatus = Check_Valid_Range("BB_1km_day",
7749  DFNT_INT16,
7750  L1A_DN_SDS_LB,
7751  L1A_DN_SDS_UB,
7752  L1A_DN_SDS_FV,
7753  (track_dim*band_dim*frame_dim),
7754  (void *) BB_1km_day);
7755  if (returnStatus != MODIS_S_OK)
7756  {
7757  L1BErrorMsg(location, returnStatus, NULL, "Check_Valid_Range",
7759  return returnStatus;
7760  }
7761 
7762  for (S = 0; S < num_scans; S++)
7763  {
7764  MS = MirrorSide[S];
7765  if (MS != 0 && MS != 1) continue; /* Skip this scan */
7766 
7767  for (D = 0; D < DETECTORS_PER_1KM_BAND; D++)
7768  {
7769  T = S * DETECTORS_PER_1KM_BAND + D;
7770  for (B = 0; B < NUM_1000M_DAY_BANDS; B++)
7771  {
7772  B_38 = B + NUM_250M_BANDS + NUM_500M_BANDS;
7773 
7774  for (subsamp = 0;
7775  subsamp < BAND_RATIO_AT_RES[INDEX_1000M_DAY]; subsamp++)
7776  {
7777  for (F = 0; F < MAX_1KM_OBC_FRAME_DIM; F++)
7778  rejects[F] = 0;
7779  DN_upper_valid_limit = SATURATED_DN - 1;
7780 
7781  if (Ecal_On[S][B_38] == True)
7782  {
7783  mean = -1;
7784  sdev = 0;
7785  }
7786  else if (moon_arrays->moon_in_SV_KOB[S][B_38] ==
7788  {
7789  returnStatus = Get_DN_Avg_SDev_Rejects_LowN(
7790  refl_tables->RSB_SV_DN_moon_include_frames,
7791  subsamp,
7792  SV_1km_FRAMES,
7793  increment,
7794  SV_1km_day[T][B],
7795  DN_upper_valid_limit,
7796  0,
7797  &mean,
7798  &sdev,
7799  &rejects[0]);
7800  if (returnStatus != MODIS_S_OK)
7801  SMF_ERROR(returnStatus,
7802  "Get_DN_Avg_SDev_Rejects_LowN() in Fill_1km_day_DN_OBC_Avg()");
7803  }
7804  else
7805  {
7806  returnStatus =
7808  refl_tables->DN_obc_avg_first_frame_to_use
7809  + subsamp,
7811  increment,
7812  SV_1km_day[T][B],
7813  DN_upper_valid_limit,
7814  0,
7815  &mean,
7816  &sdev,
7817  &rejects[refl_tables->DN_obc_avg_first_frame_to_use]);
7818  if (returnStatus != MODIS_S_OK)
7819  SMF_ERROR(returnStatus,
7820  "Get_DN_Avg_SDev_Rejects() in Fill_1km_day_DN_OBC_Avg()");
7821  }
7822  if (mean < 0)
7823  {
7824  QA_refl->all_SV_DN_bad[S] = 1;
7825  returnStatus =
7827  refl_tables->DN_obc_avg_first_frame_to_use + subsamp,
7829  increment,
7830  BB_1km_day[T][B],
7831  DN_upper_valid_limit,
7832  0,
7833  &mean,
7834  &sdev,
7835  &rejects[refl_tables->DN_obc_avg_first_frame_to_use]);
7836  if (returnStatus != MODIS_S_OK)
7837  SMF_ERROR(returnStatus,
7838  "Get_DN_Avg_SDev_Rejects() in Fill_1km_day_DN_OBC_Avg()");
7839  }
7840 
7841  if (mean < 0)
7842  QA_refl->all_BB_DN_bad[S] = 1;
7843 
7844  DN_OBC_Avg->DN_obc_1km_day_avg[T][B][subsamp] = mean;
7845  DN_OBC_Avg->DN_obc_1km_day_var[T][B][subsamp] = sdev * sdev;
7846  DN_OBC_Avg->DN_obc_1km_day_outlier_mask[T][B][subsamp][0] = 0;
7847  DN_OBC_Avg->DN_obc_1km_day_outlier_mask[T][B][subsamp][1] = 0;
7848  returnStatus =
7850  rejects,
7851  DN_OBC_Avg->DN_obc_1km_day_outlier_mask[T][B][subsamp]);
7852  }/* end loop through subsamples */
7853  }/* end loop through bands */
7854  }/* end loop through detector */
7855  }/* end loop through scans */
7856 
7857  free(SV_1km_day);
7858  free(BB_1km_day);
7859 
7860  return (returnStatus);
7861 }
7862 
7863 PGSt_SMF_status Fill_Band_26_DN_OBC_Avg
7864  (int32 sd_id,
7865  int32 num_scans,
7866  int16 *MirrorSide,
7867  refl_tables_t *refl_tables,
7868  Moon_arrays_t *moon_arrays,
7869  boolean Ecal_On[][NUM_BANDS],
7870  DN_OBC_Avg_t *DN_OBC_Avg,
7871  QA_Refl_t *QA_refl)
7872 /*
7873 !C**********************************************************************
7874 !Description:
7875  Compute the DN OBC averages for band 26. Store in DN_OBC_Avg structure
7876  for writing to the OBC file and for use in the reflective algorithm.
7877 
7878 !Input Parameters:
7879  int32 sd_id SD file access ID for the L1A middle
7880  granule.
7881  int32 num_scans Number of scans in the middle granule.
7882  int16 *MirrorSide Mirror side indexes per scan
7883  refl_tables_t *refl_tables Structure which contains all reflective
7884  LUTs
7885  Moon_arrays_t *moon_arrays Structure containing the moon_in_SV_KOB
7886  array.
7887  boolean Ecal_On[][NUM_BANDS] Ecal on information for each band for
7888  each scan.
7889  Preprocess_Refl_t *PP_Refl Structure containing DN saturation value.
7890 
7891 !Output Parameters:
7892  DN_OBC_Avg_t DN_OBC_Avg Structure containing arrays that will
7893  ultimately be written to the OBC file.
7894  QA_Refl_t QA_refl Depending on processing values, some
7895  elements of these may be tripped.
7896 
7897 !Revision History:
7898 
7899  Revision 01.10 March 25, 2002 Razor Issue #178
7900  Strip out ADC Correction
7901  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
7902 
7903  Revision 01.06, March 26, 2001, Razor Issue #159
7904  Changed DN_upper_valid_limit to SATURATED_DN - 1.
7905  Alice Isaacman (Alice.R.Isaacman.1@gsfc.nasa.gov)
7906 
7907  Revision 01.05, Dec 7, 2000, Razor issue 146
7908  Removed DN_sat_prime.
7909  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
7910 
7911  Revision 01.04 Oct. 22, 1999
7912  Added checking for Ecal on
7913  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
7914  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
7915 
7916  Revision 01.03 Sept. 2, 1999
7917  Implemented changes to meet the requirements of the new SWIR algorithm. See SDF.
7918  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
7919  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
7920 
7921  Revision 01.02 August 28, 1999
7922  Added checking if the data read from L1A are valid.
7923  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
7924 
7925  Revision 01.01 August, 1999
7926  Implement changes to meet the requirements of the new ADC algorithm. See SDF.
7927  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
7928  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
7929 
7930  Revision 01.00 April 1999
7931  Initial development
7932  Jim Rogers(rogers@mcst.gsfc.nasa.gov)
7933  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
7934 
7935 !Team-unique Header:
7936  This software is developed by the MODIS Characterization Support
7937  Team (MCST)for the National Aeronautics and Space Administration,
7938  Goddard Space Flight Center, under contract NAS5-32373.
7939 
7940 !References and Credits:
7941  HDF portions developed at the National Center for Supercomputing
7942  Applications at the University of Illinois at Urbana-Champaign.
7943 
7944 !Design Notes:
7945 
7946 !END********************************************************************
7947 */
7948 {
7949  PGSt_SMF_status returnStatus = MODIS_S_OK;
7950 
7951  typedef int16 SV_1km_night_t[NUM_1000M_NIGHT_BANDS][MAX_1KM_OBC_FRAME_DIM];
7952  SV_1km_night_t *SV_1km_night;
7953  SV_1km_night = (SV_1km_night_t*) malloc(MAX_1KM_TRACK_DIM * sizeof(SV_1km_night_t));
7954 
7955  int32 S;
7956  int32 D;
7957  int32 T;
7958  int32 B;
7959  int32 B_38;
7960  int32 subsamp;
7961  int32 increment;
7962  int16 rejects[MAX_1KM_OBC_FRAME_DIM];
7963  int16 DN_upper_valid_limit;
7964  int16 MS;
7965  float32 mean;
7966  float32 sdev;
7967  int32 track_dim;
7968  int32 band_dim;
7969  int32 frame_dim;
7970  int32 F;
7971  char *location = "Fill_Band_26_DN_OBC_Avg";
7972 
7973  track_dim = num_scans * DETECTORS_PER_1KM_BAND;
7974  band_dim = NUM_1000M_NIGHT_BANDS;
7976  increment = BAND_RATIO_AT_RES[INDEX_1000M_NIGHT];
7977 
7978  /*
7979  * Initialize arrays (in case we skip scans to due Mirror Side).
7980  */
7981 
7982  B = BAND26; /* Index in the 1km night band group */
7983 
7984  for (T = 0; T < MAX_1KM_TRACK_DIM; T++) {
7985  for (subsamp = 0; subsamp < NUM_1KM_SUBSAMP; subsamp++) {
7986  DN_OBC_Avg->DN_obc_1km_night_avg[T][B][subsamp] = -1;
7987  DN_OBC_Avg->DN_obc_1km_night_var[T][B][subsamp] = 0;
7988  DN_OBC_Avg->DN_obc_1km_night_outlier_mask[T][B][subsamp][0] = 0;
7989  DN_OBC_Avg->DN_obc_1km_night_outlier_mask[T][B][subsamp][1] = 0;
7990  }
7991  }
7992 
7993  /*
7994  * Read SV DNs from L1A middle granule and check for valid range.
7995  */
7996 
7997  returnStatus = read_sds_rank3(sd_id,
7999  track_dim,
8000  band_dim,
8001  frame_dim,
8002  SV_1km_night);
8003  if (returnStatus != MODIS_S_OK)
8004  {
8005  L1BErrorMsg(location, returnStatus, NULL, "read_sds_rank3",
8007  return returnStatus;
8008  }
8009 
8010  returnStatus = Check_Valid_Range("SV_1km_night",
8011  DFNT_INT16,
8012  L1A_DN_SDS_LB,
8013  L1A_DN_SDS_UB,
8014  L1A_DN_SDS_FV,
8015  (track_dim*band_dim*frame_dim),
8016  (void *) SV_1km_night);
8017  if (returnStatus != MODIS_S_OK)
8018  {
8019  L1BErrorMsg(location, returnStatus, NULL, "Check_Valid_Range",
8021  return returnStatus;
8022  }
8023 
8024  B = BAND26;
8025  B_38 = MODIS_BAND26_INDEX;
8026 
8027  for (S = 0; S < num_scans; S++)
8028  {
8029  MS = MirrorSide[S];
8030  if (MS != 0 && MS != 1) continue; /* Skip this scan */
8031 
8032  for (D = 0; D < DETECTORS_PER_1KM_BAND; D++)
8033  {
8034  T = S * DETECTORS_PER_1KM_BAND + D;
8035 
8036  for (subsamp = 0;
8037  subsamp < BAND_RATIO_AT_RES[INDEX_1000M_NIGHT]; subsamp++)
8038  {
8039  for (F = 0; F < MAX_1KM_OBC_FRAME_DIM; F++)
8040  rejects[F] = 0;
8041  DN_upper_valid_limit = SATURATED_DN - 1;
8042 
8043  if (Ecal_On[S][B_38] == True)
8044  {
8045  mean = -1;
8046  sdev = 0;
8047  }
8048  else if (moon_arrays->moon_in_SV_KOB[S][B_38] == MOON_INSIDE_SV_KOB)
8049  {
8050  returnStatus = Get_DN_Avg_SDev_Rejects_LowN(
8051  refl_tables->RSB_SV_DN_moon_include_frames,
8052  subsamp,
8053  SV_1km_FRAMES,
8054  increment,
8055  SV_1km_night[T][B],
8056  DN_upper_valid_limit,
8057  0,
8058  &mean,
8059  &sdev,
8060  &rejects[0]);
8061  if (returnStatus != MODIS_S_OK)
8062  SMF_ERROR(returnStatus,
8063  "Get_DN_Avg_SDev_Rejects_LowN() in Fill_1km_day_DN_OBC_Avg()");
8064  }
8065  else
8066  {
8067  returnStatus =
8069  refl_tables->DN_obc_avg_first_frame_to_use + subsamp,
8071  increment,
8072  SV_1km_night[T][B],
8073  DN_upper_valid_limit,
8074  0,
8075  &mean,
8076  &sdev,
8077  &rejects[refl_tables->DN_obc_avg_first_frame_to_use]);
8078  if (returnStatus != MODIS_S_OK)
8079  SMF_ERROR(returnStatus,
8080  "Get_DN_Avg_SDev_Rejects() in Fill_Band_26_DN_OBC_Avg()");
8081  }
8082  if (mean < 0)
8083  QA_refl->all_SV_DN_bad[S] = 1;
8084 
8085  DN_OBC_Avg->DN_obc_1km_night_avg[T][B][subsamp] = mean;
8086  DN_OBC_Avg->DN_obc_1km_night_var[T][B][subsamp] = sdev * sdev;
8087  DN_OBC_Avg->DN_obc_1km_night_outlier_mask[T][B][subsamp][0] = 0;
8088  DN_OBC_Avg->DN_obc_1km_night_outlier_mask[T][B][subsamp][1] = 0;
8089  returnStatus =
8091  rejects,
8092  DN_OBC_Avg->DN_obc_1km_night_outlier_mask[T][B][subsamp]);
8093  }/* end loop through subsamples */
8094  }/* end loop through detector */
8095  }/* end loop through scans */
8096 
8097  free(SV_1km_night);
8098 
8099  return (returnStatus);
8100 }
8101 
8102 PGSt_SMF_status Adjust_dn_star_Min(float32 *dn_star_Min,
8103  int32 L1A_v_id,
8104  int32 num_scans)
8105 /*
8106 !C**************************************************************************
8107 !Description: This routine check if the NAD door is closed. If the door is
8108  closed during any scan within the granule, set the dn_star_Min
8109  value to be -40 for those bands where dn_star_Min was set to 0.
8110  The reason is that if NAD door is closed, DN values should be
8111  very small and dn_star values for EV could be small negative
8112  values due to noise. So, set the minimum valid dn_star value to
8113  be -40.
8114 
8115 !Input Parameters:
8116  float32 * dn_star_Min Mininum dn_star values for reflective
8117  bands
8118  int32 L1A_v_id L1A file id for vdata interface
8119  int32 num_scans number of scans in the L1A granule
8120 
8121 !Output Parameters:
8122  float32 * dn_star_Min Mininum dn_star values for reflective
8123  bands
8124 
8125 !Revision History:
8126  Revision 01.01 June 23, 2003, Razor Issue #192
8127  Changed the telemetry mnemonic which determines whether the nadir aperture
8128  door (NAD) is open from "CR_DR_NAD_OPEN" to the equivalent "CR_DR_NAD_CLSD"
8129  mnemonic and altered the L1B code logic to correctly use the new value. It
8130  was discovered that at two different times in the history of the MODIS/Terra
8131  instrument the mnemonic "CR_DR_NAD_OPEN" did not correctly reflect the state
8132  of the NAD, whereas the mnemonic "CR_DR_NAD_CLSD" has been consistently
8133  reliable.
8134  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
8135 
8136  Revision 01.00 Oct. 12, 1999
8137  Initial development
8138  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
8139  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
8140 
8141 !Team-unique Header:
8142  This software is developed by the MODIS Characterization Support
8143  Team (MCST)for the National Aeronautics and Space Administration,
8144  Goddard Space Flight Center, under contract NAS5-32373.
8145 
8146 !References and Credits:
8147  HDF portions developed at the National Center for Supercomputing
8148  Applications at the University of Illinois at Urbana-Champaign.
8149 
8150 !Design Notes:
8151 
8152 !END********************************************************************
8153 */
8154 
8155 {
8156  PGSt_SMF_status returnStatus = MODIS_S_OK;
8157  uint16 NAD_door_clsd[MAX_NUM_SCANS];
8158  int16 S;
8159  int16 B;
8160 
8161  /* Check the input parameters are valid values */
8162 
8163  if (dn_star_Min == NULL)
8165  "dn_star_Min is NULL in Adjust_dn_star_Min(), Preprocess.c");
8166 
8167  if (num_scans < 0 || num_scans > MAX_NUM_SCANS)
8169  "invalid value for num_scans in Adjust_dn_star_Min(), Preprocess.c");
8170 
8171  /* Read the telemetry field for NAD door closed */
8172 
8173  returnStatus = read_vdata (L1A_v_id,
8174  0,
8175  num_scans,
8176  "Telemetry Major Cycle 3A of 7",
8177  "CR_DR_NAD_CLSD",
8178  NAD_door_clsd);
8179  if (returnStatus != MODIS_S_OK)
8180  {
8181  L1BErrorMsg("Adjust_dn_star_Min", returnStatus, NULL, "read_vdata",
8183  return returnStatus;
8184  }
8185 
8186  for (S = 0; S < num_scans; S++)
8187  {
8188  if (NAD_door_clsd[S] == 1)
8189  {
8190  for (B = 0; B < NUM_REFLECTIVE_BANDS; B++)
8191  {
8192  /*
8193  * If the NAD door is closed in any scan within the granule,
8194  * set the minimum value for dn_star to -40.
8195  */
8196 
8197  dn_star_Min[B] = -40;
8198  }
8199 
8200  break;
8201  }
8202  }
8203 
8204  return (returnStatus);
8205 }
8206 
8207 PGSt_SMF_status Check_For_Ecal_On(int32 lun,
8208  int32 num_scans,
8209  int32 v_id,
8210  boolean Ecal_On[][NUM_BANDS])
8211 /*
8212 !C**************************************************************************
8213 !Description:
8214  This function reads telemetry fields for Ecal-on for different
8215  kinds of bands, i.e. PV VIS, PV NIR, PV SM, PV LW and PC LW bands.
8216  There are two Ecal devices for each kind of bands, i.e. A and B.
8217  If one of them is on, set Ecal_On values for the corresponding bands
8218  for current scan to be true. If Ecal is on, the corresponding SV
8219  data can not be used for calibration.
8220 
8221 !Input Parameters:
8222  int32 lun The LUN of the L1A file being read (this is input
8223  to allow identification in error messages).
8224  int32 num_scans Number of scans in the L1A granule (could be the
8225  leading, middle or trailing granule)
8226  int32 v_id Vdata interface ID for the appropriate L1A file
8227  (should be open for reading)
8228 
8229 !Output Parameters:
8230  boolean Ecal_On[][NUM_BANDS] Ecal on or off information for every band
8231  for each scan
8232 !Revision History:
8233  Revision 01.03 October 16, 2004 Razor Issue #200
8234  Casted Int32 variables in sprintf calls to "long" with the
8235  format specifier "%ld" for better code portability.
8236  Liqin Tan, SAIC GSO (ltan@saicmodis.com)
8237 
8238  Revision 01.02 March 2003, Razor Issue #173
8239  In the initializers of array-of-struct "temp", enclosed its rows with braces
8240  for ANSI-C compliance.
8241  Liqin Tan, SAIC GSO (ltan@saicmodis.com)
8242 
8243  Revision 01.01 Sep. 5, 2000
8244  Added "lun" to argument list to allow identification of L1A granule.
8245  Corrected the upper bound on Ecal telemetries (should be 1).
8246  Added error messages identifying telemetry point where failed.
8247  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
8248 
8249  Revision 01.00 Oct. 21, 1999
8250  Initial development
8251  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
8252 
8253 !Team-unique Header:
8254  This software is developed by the MODIS Science Data Support
8255  Team for the National Aeronautics and Space Administration,
8256  Goddard Space Flight Center, under contract NAS5-32373.
8257 
8258 !References and Credits:
8259  HDF portions developed at the National Center for Supercomputing
8260  Applications at the University of Illinois at Urbana-Champaign.
8261 
8262 !Design Notes:
8263  When Ecal is ON, the SV DNs are invalid (these are use to telemeter Ecal
8264  results down). However, the DNs from other sectors should be valid.
8265 
8266  a. For RSBs, the calculation of DN_OBC_avg should fail-over to use the
8267  BB DNs.
8268  b. For TEBs, a valid DN_OBC_avg (SV avg) cannot be calculated. This should
8269  result in -1 in the DN_OBC_avg arrays for those affected bands and then
8270  the bad data pixel value will be set appropriately in Emissive_Cal.
8271 
8272 !END********************************************************************
8273 */
8274 {
8275  PGSt_SMF_status returnStatus = MODIS_S_OK;
8276  int32 S;
8277  int32 B_38;
8278  int32 i;
8279 
8280  int32 number_bands[NUM_BAND_TYPES] = {NUM_PV_VIS_BANDS,
8282  NUM_SM_BANDS,
8284  NUM_PC_LW_BANDS};
8285 
8286  enum {
8287  PV_VIS,
8288  PV_NIR,
8289  PV_SM,
8290  PV_LW,
8291  PC_LW
8292  } band_type;
8293 
8295  /* VIS bands */
8296  {2, 3, 7, 8, 9, 10, 11},
8297  /* NIR bands */
8298  {0, 1, 12, 13, 14, 15, 16, 17, 18, 19, 20},
8299  /* SM bands */
8300  {4, 5, 6, 21, 22, 23, 24, 25, 26, 27},
8301  /* PV LW bands */
8302  {28, 29, 30, 31},
8303  /* PC LW bands */
8304  {32, 33, 34, 35, 36, 37}
8305  };
8306 
8307  /*
8308  * The number of the fields below, which equals the value of NUM_FIELDS
8309  * should be exactly twice as many as NUM_BAND_TYPES. Every two consecutive
8310  * fields with the same name except the last character, i.e. A or B, is
8311  * used for one kind of bands.
8312  * If this is changed, the logic below is not right.
8313  */
8314 
8315  enum {
8316  VIS_ECAL_A,
8317  VIS_ECAL_B,
8318  NIR_ECAL_A,
8319  NIR_ECAL_B,
8320  SM_ECAL_A,
8321  SM_ECAL_B,
8322  PV_LW_ECAL_A,
8323  PV_LW_ECAL_B,
8324  PC_LW_ECAL_A,
8325  PC_LW_ECAL_B,
8326  NUM_FIELDS
8327  } field;
8328 
8329  struct {
8330  char *vname;
8331  char *fname;
8332  uint16 buffer[MAX_NUM_SCANS];
8333  }temp[NUM_FIELDS] = {
8334  {"Telemetry Major Cycle 4B of 7", "CR_PVVISA_ECALON", {0}},
8335  {"Telemetry Major Cycle 4B of 7", "CR_PVVISB_ECALON", {0}},
8336  {"Telemetry Major Cycle 4B of 7", "CR_PVNIRA_ECALON", {0}},
8337  {"Telemetry Major Cycle 4B of 7", "CR_PVNIRB_ECALON", {0}},
8338  {"Telemetry Major Cycle 4B of 7", "CR_PVSMA_ECAL_ON", {0}},
8339  {"Telemetry Major Cycle 4B of 7", "CR_PVSMB_ECAL_ON", {0}},
8340  {"Telemetry Major Cycle 4A of 7", "CR_PVLWA_ECAL_ON", {0}},
8341  {"Telemetry Major Cycle 4A of 7", "CR_PVLWB_ECAL_ON", {0}},
8342  {"Telemetry Major Cycle 4A of 7", "CR_PCLWA_ECAL_ON", {0}},
8343  {"Telemetry Major Cycle 4A of 7", "CR_PCLWB_ECAL_ON", {0}}
8344  };
8345  char *location = "Check_For_Ecal_On";
8346 
8347  /* Check if the value of num_scans is valid */
8348 
8349  if (num_scans < 0 || num_scans > MAX_NUM_SCANS)
8350  {
8351  char errmsg[256];
8352  sprintf (errmsg, "The input value of \"num_scans\" (%ld) is invalid.",
8353  (long)num_scans);
8354  returnStatus = MODIS_F_INVALID_ARGUMENT;
8355  L1BErrorMsg(location, returnStatus, errmsg, NULL, lun, NULL, True);
8356  return returnStatus;
8357  }
8358 
8359  /* Read the vdata and check the value */
8360 
8361  for (field = VIS_ECAL_A; field < NUM_FIELDS; field++)
8362  {
8363  returnStatus = read_vdata (v_id, 0, num_scans, temp[field].vname,
8364  temp[field].fname,
8365  (VOIDP)temp[field].buffer);
8366  if (returnStatus != MODIS_S_OK)
8367  {
8368  char errmsg[256];
8369  sprintf (errmsg, "Failed to read field \"%s\" from telemetry \"%s\".",
8370  temp[field].fname, temp[field].vname);
8371  L1BErrorMsg(location, returnStatus, errmsg, "read_vdata",
8372  lun, NULL, True);
8373  return returnStatus;
8374  }
8375  returnStatus = Check_Valid_Range(temp[field].fname, DFNT_UINT16,
8376  NULL, "1", NULL,
8377  num_scans, (void *) temp[field].buffer);
8378  if (returnStatus != MODIS_S_OK)
8379  {
8380  L1BErrorMsg(location, returnStatus, NULL, "Check_Valid_Range",
8381  lun, NULL, True);
8382  return returnStatus;
8383  }
8384  }
8385 
8386  for (S = 0; S < num_scans; S++)
8387  {
8388  for (band_type = PV_VIS, field = VIS_ECAL_A; band_type < NUM_BAND_TYPES;
8389  band_type++, field += 2)
8390  {
8391  /*
8392  * If Ecal A on or/and Ecal B on, it is considered to be Ecal on.
8393  * Set Ecal_On to be True for the corresponding bands for this scan.
8394  * Otherwise, set that to be False.
8395  */
8396 
8397  if (temp[field].buffer[S] == 1 || temp[field+1].buffer[S] == 1)
8398  for (i = 0; i < number_bands[band_type]; i++)
8399  {
8400  B_38 = bands[band_type][i];
8401  Ecal_On[S][B_38] = True;
8402  }
8403 
8404  else
8405  for (i = 0; i < number_bands[band_type]; i++)
8406  {
8407  B_38 = bands[band_type][i];
8408  Ecal_On[S][B_38] = False;
8409  }
8410  }
8411  }
8412 
8413  return (returnStatus);
8414 }
8415 
8416 PGSt_SMF_status Check_If_Sector_Rotated(int32 lun,
8417  int32 num_scans,
8418  int32 v_id,
8419  boolean Sector_Rotated[])
8420 /*
8421 !C****************************************************************************
8422 !Description:
8423  This function determines if the MODIS data collection sectors were
8424  rotated from their normal angular positions on any scan. A sector rotation
8425  event, commanded from the ground, is used occasionally for calibration
8426  studies.
8427 
8428 !Input Parameters:
8429  int32 lun The LUN of the L1A file being read (this is input
8430  to allow identification in error messages).
8431  int32 num_scans Number of scans in the L1A granule (could be the
8432  leading, middle or trailing granule)
8433  int32 v_id Vdata interface ID for the appropriate L1A file
8434  (should be open for reading)
8435 
8436 !Output Parameters:
8437  boolean Sector_Rotated[] Array describing if there is any degree
8438  of sector rotation for each scan.
8439  Values of each element are "True" or "False".
8440  (Array assumed allocated to MAX_NUM_SCANS).
8441 
8442 !Revision History:
8443  Revision 01.01 October 16, 2004 Razor Issue #200
8444  Casted Int32 variables in sprintf calls to "long" with the
8445  format specifier "%ld" for better code portability.
8446  Liqin Tan, SAIC GSO (ltan@saicmodis.com)
8447 
8448  Revision 01.00 Sep. 5, 2000
8449  Initial development
8450  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
8451 
8452 !Team-unique Header:
8453  This software is developed by the MODIS Science Data Support
8454  Team for the National Aeronautics and Space Administration,
8455  Goddard Space Flight Center, under contract NAS5-32373.
8456 
8457 !References and Credits:
8458  HDF portions developed at the National Center for Supercomputing
8459  Applications at the University of Illinois at Urbana-Champaign.
8460 
8461 !Design Notes:
8462  The telemetry name is "Telemetry Major Cycle 6 of 7" and the field
8463  name is "CS_FR_ENC_DELTA". If the value is non-zero on any scan, then
8464  it is assumed that the sector is rotated for that scan.
8465 
8466 !END**************************************************************************
8467 */
8468 {
8469  PGSt_SMF_status returnStatus = MODIS_S_OK;
8470  int32 S; /* scan index */
8471  uint16 sect_rot_telem[MAX_NUM_SCANS]; /* holds telemetry data */
8472  char *location = "Check_If_Sector_Rotated";
8473 
8474  /* Check if the value of num_scans is valid */
8475 
8476  if (num_scans < 0 || num_scans > MAX_NUM_SCANS)
8477  {
8478  char errmsg[256];
8479  sprintf (errmsg, "The input value of \"num_scans\" (%ld) is invalid.",
8480  (long)num_scans);
8481  returnStatus = MODIS_F_INVALID_ARGUMENT;
8482  L1BErrorMsg(location, returnStatus, errmsg, NULL, lun, NULL, True);
8483  return returnStatus;
8484  }
8485 
8486 
8487  /*---------------------------------------------------------------------
8488  * 03/01/2015 Xg
8489  * The telemetry data CS_FR_ENC_DELTA may not represent correctly
8490  * the sector rotation status. Our observations indicate that the
8491  * SET_FR_ENC_DELTA in the Command Parameters field correlates well
8492  * with the sector rotation encoder position.
8493  *
8494  returnStatus = read_vdata (v_id,
8495  0,
8496  num_scans,
8497  "Telemetry Major Cycle 6 of 7",
8498  "CS_FR_ENC_DELTA",
8499  (VOIDP) sect_rot_telem);
8500  if (returnStatus != MODIS_S_OK)
8501  {
8502  L1BErrorMsg(location, returnStatus,
8503  "Failed to read telemetry field \"CS_FR_ENC_DELTA\".",
8504  "read_vdata", lun, NULL, True);
8505  return returnStatus;
8506  }
8507  */
8508 
8509  /* Check the upper bound. If it is exceeded, then the L1A file
8510  * must be corrupted.
8511  */
8512 
8513  /*
8514  returnStatus = Check_Valid_Range("CS_FR_ENC_DELTA", DFNT_UINT16,
8515  NULL, "16383", NULL,
8516  num_scans, (void *) sect_rot_telem);
8517  if (returnStatus != MODIS_S_OK)
8518  {
8519  L1BErrorMsg(location, returnStatus, NULL, "Check_Valid_Range",
8520  lun, NULL, True);
8521  return returnStatus;
8522  }
8523  --------------------------------------------------------------------*/
8524 
8525  /* Read the telemetry data. */
8526  returnStatus = read_vdata (v_id,
8527  0,
8528  num_scans,
8529  "Command Parameters",
8530  "SET_FR_ENC_DELTA",
8531  (VOIDP) sect_rot_telem);
8532  if (returnStatus != MODIS_S_OK)
8533  {
8534  L1BErrorMsg(location, returnStatus,
8535  "Failed to read telemetry field \"SET_FR_ENC_DELTA\".",
8536  "read_vdata", lun, NULL, True);
8537  return returnStatus;
8538  }
8539 
8540 
8541  /* Check the upper bound. If it is exceeded, then the L1A file
8542  * must be corrupted.
8543  */
8544 
8545  returnStatus = Check_Valid_Range("SET_FR_ENC_DELTA", DFNT_UINT16,
8546  NULL, "16383", NULL,
8547  num_scans, (void *) sect_rot_telem);
8548  if (returnStatus != MODIS_S_OK)
8549  {
8550  L1BErrorMsg(location, returnStatus, NULL, "Check_Valid_Range",
8551  lun, NULL, True);
8552  return returnStatus;
8553  }
8554 
8555  /* Loop through scans, check each value, assign True or False. */
8556  for (S = 0; S < num_scans; S++)
8557  {
8558  if (sect_rot_telem[S] > 0)
8559  Sector_Rotated[S] = True;
8560  else
8561  Sector_Rotated[S] = False;
8562  }
8563 
8564  returnStatus = MODIS_S_OK;
8565  return returnStatus;
8566 }
8567 
8568 
8569 PGSt_SMF_status sort_int16_array (int32 n,
8570  int16 *a,
8571  int32 *indx)
8572 
8573 /*
8574 !C****************************************************************************
8575 !Description:
8576  This function sorts an array of "int16" values from the lowest to
8577  highest. The sorted values are returned in the original array (the
8578  original is changed upon exit).
8579 
8580 !Input Parameters:
8581  int32 n number of values in the array "a".
8582  int16 *a array of n values to be sorted, from lowest to highest.
8583  int32 *indx allocated space, contents unimportant
8584 
8585 !Output Parameters:
8586  int16 *a sorted array.
8587  int32 *indx the indexes of the original array "a", after sorting
8588 
8589 !Revision History:
8590  Revision 01.00 Sep. 11, 2000
8591  Initial development
8592  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
8593 
8594 !Team-unique Header:
8595  This software is developed by the MODIS Science Data Support
8596  Team for the National Aeronautics and Space Administration,
8597  Goddard Space Flight Center, under contract NAS5-32373.
8598 
8599 !References and Credits:
8600  HDF portions developed at the National Center for Supercomputing
8601  Applications at the University of Illinois at Urbana-Champaign.
8602 
8603 !Design Notes:
8604 
8605 !END**************************************************************************
8606 */
8607 {
8608  PGSt_SMF_status returnStatus = MODIS_S_OK;
8609  int16 atemp; /* Temporary variable */
8610  int32 itemp; /* Temporary variable */
8611  int32 i, j; /* Loop indices */
8612 
8613  for (i = 0; i < n; i++)
8614  indx[i] = i;
8615  for (i = 0; i < n-1; i++) {
8616  for (j = i+1; j < n; j++) {
8617  if (a[j] < a[i]) {
8618  atemp = a[i];
8619  a[i] = a[j];
8620  a[j] = atemp;
8621  itemp = indx[i];
8622  indx[i] = indx[j];
8623  indx[j] = itemp;
8624  }
8625  }
8626  }
8627  return returnStatus;
8628 }
8629 
8630 
8631 PGSt_SMF_status Get_DN_Avg_SDev_Rejects_LowN(int32 N_include,
8632  int32 start_index,
8633  int32 N,
8634  int32 index_increment,
8635  int16 *DN_array,
8636  int16 DN_upper_valid_limit,
8637  int16 DN_lower_valid_limit,
8638  float32 *mean_DN,
8639  float32 *sdev_DN,
8640  int16 *rejects)
8641 /*
8642 !C****************************************************************************
8643 !Description:
8644  This function has the same purpose as "Get_DN_Avg_SDev_Rejects" -- to
8645  compute the average, standard deviation and the rejected values for a set
8646  of DNs. In fact, this function calls "Get_DN_Avg_SDev_Rejects". However,
8647  prior to calling that function, the DNs are sorted from lowest to highest
8648  -- and only the lowest "N_include" values are passed into
8649  Get_DN_Avg_SDev_Rejects to compute the output values.
8650 
8651  This function is intended for use in calculating the space view (SV)
8652  average DN when the moon is in the space view port. In that situation,
8653  several 1km frames will be corrupted by the moon, having abnormally high
8654  values. By sorting the DNs from lowest to highest, we can eliminate
8655  those abnormally high values.
8656 
8657 !Input Parameters:
8658  int32 N_include Number of values to use to form the set of DNs
8659  which are passed into "Get_DN_Avg_SDev_Rejects".
8660  After sorting the values from lowest to highest,
8661  the lowest N_include values will be used.
8662  int32 start_index Starting index in the array "DN_array".
8663  This value is normally the subsample index of
8664  the DNs being averaged.
8665  int32 N Number of DN values to form an array before
8666  sorting. This number should be greater than or
8667  equal to N_include. This number is normally
8668  the number of 1km frames.
8669  int32 index_increment Amount to increment when forming the array
8670  of DNs to sort. This value is normally the
8671  number of subsamples appropriate to the
8672  resolution of the data (1, 2 or 4).
8673  int16 * DN_array Array of digital numbers for all frames and
8674  subsamples. There should be
8675  N * index_increment values in this array.
8676  int16 DN_upper_valid_limit Upper limit of the valid range of
8677  DNs (typically 4094).
8678  int16 DN_lower_valid_limit Lower limit of the valid range of
8679  DNs (typically 0).
8680 
8681 !Output Parameters:
8682  float32 * mean_DN Mean value of final set of data after all
8683  invalid and outlier values are removed. A
8684  negative return value means that all values
8685  were rejected for some reason.
8686  float32 * sdev_DN standard deviation of the final set of values.
8687  A negative return value means that all values
8688  were rejected for some reason.
8689  int16 * rejects An array of dimension [N], where 1 denotes a
8690  value was removed and 0 denotes that a value
8691  was used in the final set.
8692 
8693 !Revision History:
8694  Revision 01.11 October 16, 2004 Razor Issue #200
8695  Casted Int32 variables in sprintf calls to "long" with the
8696  format specifier "%ld" for better code portability.
8697  Liqin Tan, SAIC GSO (ltan@saicmodis.com)
8698 
8699  Revision 01.10 March 25, 2002 Razor Issue #178
8700  Strip out ADC Correction (delta_DN)
8701  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
8702 
8703  Revision 01.00 Sep. 13, 2000
8704  Initial development
8705  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
8706 
8707 !Team-unique Header:
8708  This software is developed by the MODIS Science Data Support
8709  Team for the National Aeronautics and Space Administration,
8710  Goddard Space Flight Center, under contract NAS5-32373.
8711 
8712 !References and Credits:
8713  HDF portions developed at the National Center for Supercomputing
8714  Applications at the University of Illinois at Urbana-Champaign.
8715 
8716 !Design Notes:
8717 
8718 !END**************************************************************************
8719 */
8720 {
8721  PGSt_SMF_status returnStatus = MODIS_S_OK;
8722  int32 i; /* index */
8723  int16 DN_temp[MAX_1KM_OBC_FRAME_DIM]; /* Temp array for DNs */
8724  int32 DN_temp_indx[MAX_1KM_OBC_FRAME_DIM]; /* Temp array for indexes */
8725  int16 rejects_temp[MAX_1KM_OBC_FRAME_DIM]; /* Temp array for rejects */
8726  char *location = "Get_DN_Avg_SDev_Rejects_LowN";
8727 
8728  /*
8729  * Check dimensions and input values.
8730  */
8731 
8732  if (N > MAX_1KM_OBC_FRAME_DIM) {
8733  char errmsg[256];
8734  sprintf (errmsg, "Input N (%ld) exceeds MAX_1KM_OBC_FRAME_DIM (%ld)\n",
8735  (long)N, (long)MAX_1KM_OBC_FRAME_DIM);
8736  returnStatus = MODIS_F_INVALID_ARGUMENT;
8737  L1BErrorMsg(location, returnStatus, errmsg, NULL, 0, NULL, True);
8738  return returnStatus;
8739  }
8740  if (N_include > N) {
8741  char errmsg[256];
8742  sprintf (errmsg, "Input N_include (%ld) exceeds N (%ld)\n",
8743  (long)N_include, (long)N);
8744  returnStatus = MODIS_F_INVALID_ARGUMENT;
8745  L1BErrorMsg(location, returnStatus, errmsg, NULL, 0, NULL, True);
8746  return returnStatus;
8747  }
8748  if (N_include < 1) {
8749  char errmsg[256];
8750  sprintf (errmsg, "Input N_include (%ld) is invalid (should be > 0)\n",
8751  (long)N_include);
8752  returnStatus = MODIS_F_INVALID_ARGUMENT;
8753  L1BErrorMsg(location, returnStatus, errmsg, NULL, 0, NULL, True);
8754  return returnStatus;
8755  }
8756 
8757  /*
8758  * Form the set of DNs and sort from lowest to highest.
8759  */
8760 
8761  for (i = 0; i < N; i++)
8762  DN_temp[i] = DN_array[start_index + i * index_increment];
8763 
8764  returnStatus = sort_int16_array (N, DN_temp, DN_temp_indx);
8765  if (returnStatus != MODIS_S_OK) {
8766  returnStatus = MODIS_F_NOK;
8767  L1BErrorMsg(location, returnStatus, NULL, "sort_int16_array",
8768  0, NULL, True);
8769  return returnStatus;
8770  }
8771 
8772  /*
8773  * Calculate <DN>, sdev and rejects. Put rejects into temp array.
8774  */
8775 
8776  returnStatus = Get_DN_Avg_SDev_Rejects(0,
8777  N_include,
8778  1,
8779  DN_temp,
8780  DN_upper_valid_limit,
8781  DN_lower_valid_limit,
8782  mean_DN,
8783  sdev_DN,
8784  rejects_temp);
8785  if (returnStatus != MODIS_S_OK) {
8786  L1BErrorMsg(location, returnStatus, NULL, "Get_DN_Avg_SDev_Rejects",
8787  0, NULL, True);
8788  return returnStatus;
8789  }
8790 
8791  /*
8792  * Fill the rejects return variable.
8793  */
8794 
8795  for (i = 0; i < N_include; i++)
8796  rejects[DN_temp_indx[i]] = rejects_temp[i];
8797  for ( ; i < N; i++)
8798  rejects[DN_temp_indx[i]] = 1;
8799 
8800  return returnStatus;
8801 }
8802 
8803 
8805  L1B_granule_t *L1B_Gran)
8806 /*
8807 !C****************************************************************************
8808 !Description:
8809  This function calculates the frame-by-frame RVS correction terms for
8810  the reflective solar bands and thermal emissive bands. The calculated
8811  values are stored in the RSB_Cal_Coeff structure for use in
8812  Reflective_Cal and in the Emiss_Cal_Coeff structure for use
8813  in Emissive_Cal respectively. The RVS correction values for the SV and
8814  BB are also used in Preprocess.c.
8815  The frame dependent uncertainty terms are also calculated in this function.
8816 
8817 !Input Parameters:
8818  lookup_tables_t * tables Contains structure members for m1 and R*
8819  time-dependent LUTs and dead detector list.
8820  L1B_granule_t *L1B_Gran Will contain L1B data and also L1B Calibration
8821  information. Of interest are the RVS
8822  correction terms which need to be calculated
8823  so that they can be used in preprocessing.
8824 
8825 !Output Parameters:
8826  L1B_granule_t *L1B_Gran with the RVS correction inserted.
8827 
8828 !Revision History:
8829  Revision 02.13 March 2003, Razor Issue #173
8830  Initialized variable "rvs_corr" to 0.0 for ANSI-C compliance.
8831  Liqin Tan, SAIC GSO (ltan@saicmodis.com)
8832 
8833  Revision 1.01 May 14, 2002
8834  Replaced incorrect comparison of RVS coefficients for TEBs to RSB
8835  coefficents with a comparison to TEB coefficients. This error never
8836  resulted in an incorrect answer but did lead to recalculating the
8837  coefficients for each detector in a thermal band even if the coefficients
8838  were the same for all 10 detectors.
8839  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
8840 
8841  Initial development March 10, 2002 Razor Issue #174
8842  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
8843 
8844 !Team-unique Header:
8845  This software is developed by the MODIS Characterization Support
8846  Team (MCST)for the National Aeronautics and Space Administration,
8847  Goddard Space Flight Center, under contract NAS5-32373.
8848 
8849 !References and Credits:
8850  HDF portions developed at the National Center for Supercomputing
8851  Applications at the University of Illinois at Urbana-Champaign.
8852 
8853 !Design Notes:
8854 
8855 !END**************************************************************************
8856 */
8857 
8858 {
8859  PGSt_SMF_status returnStatus = MODIS_S_OK;
8860  int16 band = 0; /* Band index */
8861  int16 ref_band = 0; /* Reference band index */
8862  int16 det = 0; /* Detector */
8863  int16 det_160 = 0; /* Emissive detector index */
8864  int16 sample = 0; /* Sample number */
8865  int16 mirr_side = 0; /* Mirror side */
8866  int16 frame = 0; /* Frame number */
8867  int16 ref_frame = 0; /* Reference frame number */
8868  int16 BB_frame_no = 0; /* Frame number to use for BB RVS Correction */
8869  int16 SV_frame_no = 0; /* Frame number to use for SV RVS Correction */
8870  int16 i = 0; /* temporal variable */
8871  boolean coeffs_same = FALSE;
8872  boolean det_0_or_coeffs_diff = FALSE;
8873  float32 *rvs_coeffs; /* Temporary pointer to current RVS coefficients */
8874  float32 *sigma_rvs_coeffs; /* Temporary pointer to RVS uncertainty coefficients */
8875  float32 rvs_corr = 0.0; /* Calculated RVS correction */
8876  float32 sigma_rvs = 0.0; /* Calculated Sigma RVS */
8877  float32 *u2_samples; /* Temporary pointer to RSB u2 uncertainty */
8878  int16 *u2_frames; /* Temporary pointer to the specified frames loaded with RSB u2 uncertainty */
8879  float32 y1,y2; /* temporary variables for u2 interpolation */
8880  int16 f1, f2, f_end; /* temporary variables for frame index */
8881  char *location = "Calculate_RVS_Correction";
8882 
8883  int32 frame_no_squared[EV_1km_FRAMES];
8884  /* Array of squares of frames */
8885 
8886  /* Initialize the array of squares of frames */
8887  for ( frame = 0; frame < EV_1km_FRAMES; frame++ )
8888  frame_no_squared[frame] = frame*frame;
8889 
8890  /* Frame numbers to use for BB and SV calculations */
8891 
8892  BB_frame_no = tables->emiss.RVS_BB_SV_Frame_No[0];
8893  SV_frame_no = tables->emiss.RVS_BB_SV_Frame_No[1];
8894 
8895  /* Calculate the frame-by-frame RVS Correction Terms for 250M Bands. */
8896 
8897  /* Loop through bands, detectors, and mirror sides: */
8898 
8899  for (band = 0; band < NUM_250M_BANDS; band++ )
8900  {
8901  for ( det = 0; det < DETECTORS_PER_250M_BAND; det++)
8902  {
8903  for ( mirr_side = 0; mirr_side < NUM_MIRROR_SIDES; mirr_side++ )
8904  {
8905 
8906  /* Read the set of three rvs coefficients. */
8907 
8908  rvs_coeffs = tables->refl.RVS_RefSB[band][det][mirr_side];
8909 
8910  /*
8911  * If this is not the first detector, check to see whether these
8912  * coefficients are the same as those for the detector before it.
8913  */
8914 
8915  if (det > 0)
8916  {
8917  i = 0;
8918  coeffs_same = TRUE;
8919  while (coeffs_same && i < NUM_RSB_RVS_COEFFS)
8920  {
8921  coeffs_same = (tables->refl.RVS_RefSB[band][det - 1][mirr_side][i] == rvs_coeffs[i]);
8922  i++;
8923  }
8924  }
8925  else
8926  coeffs_same = FALSE;
8927 
8928  det_0_or_coeffs_diff = (det == 0 || (coeffs_same == FALSE));
8929 
8930  /* Run through each EV frame and calculate the correction. */
8931 
8932  for ( ref_frame = 0; ref_frame < EV_1km_FRAMES; ref_frame++ )
8933  {
8934 
8935  /*
8936  * If this is the first detector or these coefficients are not the
8937  * same as those for the previous detector, calculate the new correction.
8938  */
8939 
8940  if (det_0_or_coeffs_diff)
8941  {
8942  /* calculate RVS correction */
8943  rvs_corr = 0.;
8944  for (i = NUM_RSB_RVS_COEFFS-1; i >= 0; i -- )
8945  {
8946  rvs_corr = rvs_corr*ref_frame + rvs_coeffs[i];
8947  }
8948 
8949  if (rvs_corr < RVS_CORRECTION_LOWER_LIMIT ||
8950  rvs_corr > RVS_CORRECTION_UPPER_LIMIT)
8951 
8952  {
8953  returnStatus = MODIS_F_OUT_OF_RANGE;
8954  L1BErrorMsg(location, returnStatus, NULL, NULL,
8955  0, NULL, True);
8956  return returnStatus;
8957  }
8958  } /* Coefficients not the same */
8959 
8960  /* Set the actual frame number for the 250m resolution: */
8961 
8962  frame = NUM_250M_SUBSAMP*ref_frame;
8963 
8964  /* Loop through the subframes located here: */
8965 
8966  for ( sample = 0; sample < NUM_250M_SUBSAMP; sample++ )
8967  {
8968  /* If the correction was recalculated, use it now: */
8969 
8970  if (det_0_or_coeffs_diff)
8971 
8972  L1B_Gran->RSB_Cal_Coeff.RVS_250m
8973  [band][det][frame][mirr_side] = rvs_corr;
8974 
8975  else
8976 
8977  /* Otherwise, use the previously recorded correction term. */
8978 
8979  L1B_Gran->RSB_Cal_Coeff.RVS_250m
8980  [band][det][frame][mirr_side] =
8981  L1B_Gran->RSB_Cal_Coeff.RVS_250m
8982  [band][det - 1][frame][mirr_side];
8983 
8984  frame++;
8985 
8986  } /* end loop through samples */
8987  } /* end loop through ref_frame */
8988  } /* end loop through mirr_side */
8989  } /* end loop through det */
8990  } /* end loop through bands */
8991 
8992  /* Calculate the frame-by-frame RVS Correction Terms for 500M Bands. */
8993 
8994  /* Loop through bands, detectors, and mirror sides: */
8995 
8996  for (band = 0; band < NUM_500M_BANDS; band++ )
8997  {
8998  /* Find this band's index in the set of reflective solar bands. */
8999 
9000  ref_band = band + NUM_250M_BANDS;
9001 
9002  for ( det = 0; det < DETECTORS_PER_500M_BAND; det++)
9003  {
9004  for ( mirr_side = 0; mirr_side < NUM_MIRROR_SIDES; mirr_side++ )
9005  {
9006 
9007  /* Read the set of three rvs coefficients. */
9008 
9009  rvs_coeffs = tables->refl.RVS_RefSB[ref_band][det][mirr_side];
9010 
9011  /*
9012  * If this is not the first detector, check to see whether these
9013  * coefficients are the same as those for the detector before it.
9014  */
9015 
9016  if (det > 0)
9017  {
9018  i = 0;
9019  coeffs_same = TRUE;
9020  while (coeffs_same && i < NUM_RSB_RVS_COEFFS)
9021  {
9022  coeffs_same = (tables->refl.RVS_RefSB[band][det - 1][mirr_side][i] == rvs_coeffs[i]);
9023  i++;
9024  }
9025  }
9026  else
9027  coeffs_same = FALSE;
9028 
9029  det_0_or_coeffs_diff = (det == 0 || (coeffs_same == FALSE));
9030 
9031  /* Run through each EV frame and calculate the correction. */
9032 
9033  for ( ref_frame = 0; ref_frame < EV_1km_FRAMES; ref_frame++ )
9034  {
9035 
9036  /*
9037  * If this is the first detector or these coefficients are not the
9038  * same as those for the previous detector, calculate the new correction.
9039  */
9040 
9041  if (det_0_or_coeffs_diff)
9042  {
9043  /* calculate RVS correction */
9044  rvs_corr = 0.;
9045  for (i = NUM_RSB_RVS_COEFFS-1; i >= 0; i -- )
9046  {
9047  rvs_corr = rvs_corr*ref_frame + rvs_coeffs[i];
9048  }
9049 
9050  if (rvs_corr < RVS_CORRECTION_LOWER_LIMIT ||
9051  rvs_corr > RVS_CORRECTION_UPPER_LIMIT)
9052 
9053  {
9054  returnStatus = MODIS_F_OUT_OF_RANGE;
9055  L1BErrorMsg(location, returnStatus, NULL, NULL,
9056  0, NULL, True);
9057  return returnStatus;
9058  }
9059  } /* Coefficients not same */
9060 
9061  /* Set the actual frame number for the 500m resolution: */
9062 
9063  frame = NUM_500M_SUBSAMP*ref_frame;
9064 
9065  /* Loop through the subframes located here: */
9066 
9067  for ( sample = 0; sample < NUM_500M_SUBSAMP; sample++ )
9068  {
9069  /* If the correction was recalculated, use it now: */
9070 
9071  if (det_0_or_coeffs_diff)
9072 
9073  L1B_Gran->RSB_Cal_Coeff.RVS_500m
9074  [band][det][frame][mirr_side] = rvs_corr;
9075 
9076  else
9077 
9078  /* Otherwise, use the previously recorded correction term. */
9079 
9080  L1B_Gran->RSB_Cal_Coeff.RVS_500m
9081  [band][det][frame][mirr_side] =
9082  L1B_Gran->RSB_Cal_Coeff.RVS_500m
9083  [band][det - 1][frame][mirr_side];
9084 
9085  frame++;
9086 
9087  } /* end loop through samples */
9088  } /* end loop through ref_frame */
9089  } /* end loop through mirr_side */
9090  } /* end loop through det */
9091  } /* end loop through bands */
9092 
9093 
9094  /* Calculate the frame-by-frame RVS Correction Terms for 1KM RSBs. */
9095 
9096  /* Loop through bands, detectors, and mirror sides: */
9097 
9098  for (band = 0; band < NUM_1000M_REFL_BANDS; band++ )
9099  {
9100  /* Find this band's index in the set of reflective solar bands. */
9101 
9102  ref_band = band + (NUM_250M_BANDS + NUM_500M_BANDS);
9103 
9104  for ( det = 0; det < DETECTORS_PER_1KM_BAND; det++)
9105  {
9106  for ( mirr_side = 0; mirr_side < NUM_MIRROR_SIDES; mirr_side++ )
9107  {
9108  /* Read the set of three rvs coefficients. */
9109 
9110  rvs_coeffs = tables->refl.RVS_RefSB[ref_band][det][mirr_side];
9111 
9112  /*
9113  * If this is not the first detector, check to see whether these
9114  * coefficients are the same as those for the detector before it.
9115  */
9116 
9117  if (det > 0)
9118  {
9119  i = 0;
9120  coeffs_same = TRUE;
9121  while (coeffs_same && i < NUM_RSB_RVS_COEFFS)
9122  {
9123  coeffs_same = (tables->refl.RVS_RefSB[band][det - 1][mirr_side][i] == rvs_coeffs[i]);
9124  i++;
9125  }
9126  }
9127  else
9128  coeffs_same = FALSE;
9129 
9130  det_0_or_coeffs_diff = (det == 0 || (coeffs_same == FALSE));
9131 
9132  /* Run through each EV frame and calculate the correction. */
9133 
9134  for ( frame = 0; frame < EV_1km_FRAMES; frame++ )
9135  {
9136 
9137  /*
9138  * If this is the first detector or these coefficients are not the
9139  * same as those for the previous detector, calculate the new correction.
9140  */
9141 
9142  if (det_0_or_coeffs_diff)
9143  {
9144  /* calculate RVS correction */
9145  rvs_corr = 0.;
9146  for (i = NUM_RSB_RVS_COEFFS-1; i >= 0; i -- )
9147  {
9148  rvs_corr = rvs_corr*frame + rvs_coeffs[i];
9149  }
9150 
9151  if (rvs_corr < RVS_CORRECTION_LOWER_LIMIT ||
9152  rvs_corr > RVS_CORRECTION_UPPER_LIMIT)
9153 
9154  {
9155  returnStatus = MODIS_F_OUT_OF_RANGE;
9156  L1BErrorMsg(location, returnStatus, NULL, NULL,
9157  0, NULL, True);
9158  return returnStatus;
9159  }
9160 
9161  /* Fill in the calculated correction: */
9162 
9163  L1B_Gran->RSB_Cal_Coeff.RVS_1km_RefSB
9164  [band][det][frame][mirr_side] = rvs_corr;
9165 
9166  } /* Coefficients not same */
9167 
9168  else
9169 
9170  /* Otherwise, use the previously recorded correction term. */
9171 
9172  L1B_Gran->RSB_Cal_Coeff.RVS_1km_RefSB
9173  [band][det][frame][mirr_side] =
9174  L1B_Gran->RSB_Cal_Coeff.RVS_1km_RefSB
9175  [band][det - 1][frame][mirr_side] ;
9176 
9177  } /* end loop through frame */
9178  } /* end loop through mirr_side */
9179  } /* end loop through det */
9180  } /* end loop through bands */
9181 
9182  /* calculate the frame-dependent uncertainty */
9183  u2_frames = tables->refl.u2_frames;
9184  /* interpolation to get u2 on each frame */
9185  for ( det = 0; det < NUM_REFLECTIVE_DETECTORS; det++)
9186  {
9187  for ( mirr_side = 0; mirr_side < NUM_MIRROR_SIDES; mirr_side++ )
9188  {
9189  /* Read the set of three rvs coefficients. */
9190  u2_samples = tables->refl.u2_samples[det][mirr_side];
9191  for ( frame = 0; frame < EV_1km_FRAMES; frame++ )
9192  {
9193  if (frame <= u2_frames[0]) L1B_Gran->RSB_Cal_Coeff.u2[det][frame][mirr_side] = u2_samples[0];
9194  else if (frame >= u2_frames[NUM_U2_FRAME-1])
9195  L1B_Gran->RSB_Cal_Coeff.u2[det][frame][mirr_side] = u2_samples[NUM_U2_FRAME-1];
9196  else
9197  {
9198  /*
9199  * implement interpolation
9200  */
9201  f_end = 1;
9202  while ( frame > u2_frames[f_end] && f_end < (NUM_U2_FRAME-1) )
9203  f_end++;
9204  f1 = u2_frames[f_end-1];
9205  f2 = u2_frames[f_end];
9206  y1 = u2_samples[f_end-1];
9207  y2 = u2_samples[f_end];
9208  L1B_Gran->RSB_Cal_Coeff.u2[det][frame][mirr_side] = y1*((float32)(f2-frame))/((float32)(f2-f1))
9209  + y2*((float32)(frame-f1))/((float32)(f2-f1));
9210  }
9211  } /* end loop through frame */
9212  } /* end loop through mirr_side */
9213  } /* end loop through det */
9214 
9215 
9216  /* Calculate the frame-by-frame RVS Correction Terms for Emissive Bands. */
9217 
9218  /* Set the emissive detector index to 0. */
9219 
9220  det_160 = 0;
9221 
9222  /* Loop through bands, detectors, and mirror sides: */
9223 
9224  for (band = 0; band < NUM_EMISSIVE_BANDS; band++ )
9225  {
9226  for ( det = 0; det < DETECTORS_PER_1KM_BAND; det++, det_160++ )
9227  {
9228  for ( mirr_side = 0; mirr_side < NUM_MIRROR_SIDES; mirr_side++ )
9229  {
9230  /* Read the set of three rvs coefficients. */
9231 
9232  rvs_coeffs = tables->emiss.RVS_TEB[band][det][mirr_side];
9233 
9234  /*
9235  * If this is not the first detector, check to see whether these
9236  * coefficients are the same as those for the detector before it.
9237  */
9238 
9239  if (det > 0)
9240  coeffs_same = (
9241  tables->emiss.RVS_TEB[band][det - 1][mirr_side][0]
9242  == rvs_coeffs[0] &&
9243  tables->emiss.RVS_TEB[band][det - 1][mirr_side][1]
9244  == rvs_coeffs[1] &&
9245  tables->emiss.RVS_TEB[band][det - 1][mirr_side][2]
9246  == rvs_coeffs[2]);
9247  else
9248  coeffs_same = FALSE;
9249 
9250  det_0_or_coeffs_diff = (det == 0 || (coeffs_same == FALSE));
9251 
9252  /* Run through each EV frame and calculate the correction. */
9253 
9254  for ( frame = 0; frame < EV_1km_FRAMES; frame++ )
9255  {
9256 
9257  /*
9258  * If this is the first detector or these coefficients are not the
9259  * same as those for the previous detector, calculate the new correction.
9260  */
9261 
9262  if (det_0_or_coeffs_diff)
9263  {
9264  EVAL_2ND_ORDER_POLYNOMIAL(rvs_corr, rvs_coeffs,
9265  frame, frame_no_squared[frame]);
9266 
9267  if (rvs_corr < RVS_CORRECTION_LOWER_LIMIT ||
9268  rvs_corr > RVS_CORRECTION_UPPER_LIMIT)
9269 
9270  {
9271  returnStatus = MODIS_F_OUT_OF_RANGE;
9272  L1BErrorMsg(location, returnStatus, NULL, NULL,
9273  0, NULL, True);
9274  return returnStatus;
9275  }
9276 
9277  /* Fill in the calculated correction: */
9278 
9280  [det_160][frame][mirr_side] = rvs_corr;
9281 
9282  } /* Coefficients not same */
9283 
9284  else
9285 
9286  /* Otherwise, use the previously recorded correction term. */
9287 
9289  [det_160][frame][mirr_side] =
9291  [det_160 - 1][frame][mirr_side];
9292  }
9293 
9294  /* Calculate the sigma RVS for TEB */
9295  /* Read the set of three sigma rvs coefficients. */
9296  sigma_rvs_coeffs = tables->emiss.sigma_RVS_EV[band][det][mirr_side];
9297 
9298  /*
9299  * If this is not the first detector, check to see whether these
9300  * coefficients are the same as those for the detector before it.
9301  */
9302 
9303  if (det > 0)
9304  coeffs_same = (
9305  tables->emiss.sigma_RVS_EV[band][det - 1][mirr_side][0]
9306  == sigma_rvs_coeffs[0] &&
9307  tables->emiss.sigma_RVS_EV[band][det - 1][mirr_side][1]
9308  == sigma_rvs_coeffs[1] &&
9309  tables->emiss.sigma_RVS_EV[band][det - 1][mirr_side][2]
9310  == sigma_rvs_coeffs[2]);
9311  else
9312  coeffs_same = FALSE;
9313 
9314  det_0_or_coeffs_diff = (det == 0 || (coeffs_same == FALSE));
9315 
9316  /* Run through each EV frame and calculate the correction. */
9317  for ( frame = 0; frame < EV_1km_FRAMES; frame++ )
9318  {
9319 
9320  /*
9321  * If this is the first detector or these coefficients are not the
9322  * same as those for the previous detector, calculate the new correction.
9323  */
9324 
9325  if (det_0_or_coeffs_diff)
9326  {
9327  EVAL_2ND_ORDER_POLYNOMIAL(sigma_rvs, sigma_rvs_coeffs,
9328  frame, frame_no_squared[frame]);
9329 
9330  /* Fill in the calculated correction: */
9331 
9333  [det_160][frame][mirr_side] = sigma_rvs;
9334 
9335  } /* Coefficients not same */
9336 
9337  else
9338 
9339  /* Otherwise, use the previously recorded correction term. */
9340 
9342  [det_160][frame][mirr_side] =
9344  [det_160 - 1][frame][mirr_side];
9345 
9346 
9347  } /* end loop through frame */
9348 
9349  /* Fill in the BlackBody correction for this detector and mirror side: */
9350 
9351  L1B_Gran->Emiss_Cal_Coeff.RVS_1km_Emiss_BB[det_160][mirr_side] =
9353  [det_160][BB_frame_no][mirr_side] ;
9354 
9355  /* Fill in the Space View correction for this detector and mirror side: */
9356 
9357  L1B_Gran->Emiss_Cal_Coeff.RVS_1km_Emiss_SV[det_160][mirr_side] =
9359  [det_160][SV_frame_no][mirr_side];
9360 
9361  } /* end loop through mirr_side */
9362  } /* end loop through det */
9363  } /* end loop through bands */
9364 
9365  return returnStatus;
9366 }
9367 
uint8 change_b1[NUM_EMISSIVE_DETECTORS]
Definition: Granule.h:1042
@ GRAN_AVG_TA_RC_CS
Definition: Granule.h:709
#define MODIS_S_OK
float32 b1[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:141
#define MODIS_F_FILE_NOT_FOUND
integer, parameter int16
Definition: cubeio.f90:3
@ SV_INDEX
Definition: Granule.h:637
float32 DN_obc_1km_night_avg[MAX_1KM_TRACK_DIM][NUM_1000M_NIGHT_BANDS][NUM_1KM_SUBSAMP]
Definition: Preprocess.h:121
#define QA_TABLES_FILE
Definition: FNames.h:76
const int TRK_LOWER
uint8 noise_T_cav
Definition: Granule.h:1040
#define L1A_DN_SDS_LB
Definition: Granule.h:506
float32 DN_obc_500m_avg[MAX_500M_TRACK_DIM][NUM_500M_BANDS][NUM_500M_SUBSAMP]
Definition: Preprocess.h:119
Engineering_Coefficients_t Engineering_Coefficients_PFM
Definition: PreprocessP.h:245
#define OFF
Definition: l1.h:42
an array had not been initialized Several spelling and grammar corrections were which is read from the appropriate MCF the above metadata values were hard coded A problem calculating the average background DN for SWIR bands when the moon is in the space view port was corrected The new algorithm used to calculate the average background DN for all reflective bands when the moon is in the space view port is now the same as the algorithm employed by the thermal bands For non SWIR changes in the averages are typically less than Also for non SWIR the black body DNs remain a backup in case the SV DNs are not available For SWIR the changes in computed averages were larger because the old which used the black body suffered from contamination by the micron leak As a consequence of the if SV DNs are not available for the SWIR the EV pixels will not be the granule time is used to identify the appropriate tables within the set given for one LUT the first two or last two tables respectively will be used for the interpolation If there is only one LUT in the set of tables
Definition: HISTORY.txt:695
PGSt_SMF_status Calculate_Planck(float32 *RSR, float32 *wl, int16 size, float32 T, float32 *planck)
Definition: Preprocess.c:305
boolean leading_granule_scan_gap
Definition: Granule.h:1072
PGSt_SMF_status Copy_EngMemData(int32 in_sd_id, int32 out_sd_id, int32 num_scans)
Definition: Preprocess.c:6006
uint8 noise_T_ins
Definition: Granule.h:1039
#define MODIS_F_WRITE_ERROR
float32 vr_lwir[MAX_NUM_SCANS]
Definition: PreprocessP.h:543
#define DROPPED_SCAN_UPPER_LIMIT
Definition: PreprocessP.h:196
PGSt_SMF_status Check_For_Moon_in_SV_KOB(int32 num_scans, common_QA_tables_t *common_QA_tables, QA_Data_t *QA, Moon_arrays_t *moon_arrays)
Definition: Preprocess.c:6796
int j
Definition: decode_rs.h:73
QA_Common_t QA_common
Definition: Granule.h:1097
float32 mir_avg[MAX_NUM_SCANS]
Definition: PreprocessP.h:527
#define NUM_AQUA_BB_SAT_BANDS
Definition: L1B_Tables.h:401
float32 RVS_500m[NUM_500M_BANDS][DETECTORS_PER_500M_BAND][EV_500m_FRAMES][NUM_MIRROR_SIDES]
Definition: Granule.h:830
#define L(lambda, T)
Definition: PreprocessP.h:185
PGSt_SMF_status Read_Convert_Temperatures(emiss_tables_t *tables, int32 v_id, int32 start_scan, int32 num_scans, int32 satellite_ID, Temperatures_t *temps)
Definition: Preprocess.c:4610
u5 which has been done in the LOCALGRANULEID metadata should have an extension NRT It is requested to identify the NRT production Changes from v6 which may affect scientific the sector rotation may actually occur during one of the scans earlier than the one where it is first reported As a the b1 values are about the LOCALGRANULEID metadata should have an extension NRT It is requested to identify the NRT to fill pixels affected by dead subframes with a special value Output the metadata of noisy and dead subframe Dead Subframe EV and Detector Quality Flag2 Removed the function call of Fill_Dead_Detector_SI to stop interpolating SI values for dead but also for all downstream products for science test only Changes from v5 which will affect scientific to conform to MODIS requirements Removed the Mixed option from the ScanType in the code because the L1A Scan Type is never Mixed Changed for ANSI C compliance and comments to better document the fact that when the HDF_EOS metadata is stricly the and products are off by and in the track respectively Corrected some misspelling of RCS swir_oob_sending_detector to the Reflective LUTs to enable the SWIR OOB correction detector so that if any of the sending detectors becomes noisy or non near by good detectors from the same sending band can be specified as the substitute in the new look up table Code change for adding an additional dimension of mirror side to the Band_21_b1 LUT to separate the coefficient of the two mirror sides for just like other thermal emissive so that the L1B code can calibrate Band scan to scan with mirror side dependency which leads better calibration result Changes which do not affect scientific when the EV data are not provided in this Crosstalk Correction will not be performed to the Band calibration data Changes which do not affect scientific SV_250m
Definition: HISTORY.txt:333
float32 RVS_1km_Emiss_BB[NUM_EMISSIVE_DETECTORS][NUM_MIRROR_SIDES]
Definition: Granule.h:850
float32 rc_temp[NUM_T_RC_VALUES][MAX_NUM_SCANS]
Definition: PreprocessP.h:542
boolean missing_trailing_granule
Definition: Granule.h:1071
float32 moon_offset_limits[NUM_BANDS][NUM_MOON_OFFSET_LIMITS]
Definition: L1B_Tables.h:900
#define NUM_T_INS_THERMISTORS
Definition: L1B_Tables.h:415
@ BAND36
Definition: Granule.h:644
PGSt_SMF_status write_sds_rank3(int32 file_id, char *sds_name, char *dim_name1, char *dim_name2, char *dim_name3, int32 dim1, int32 dim2, int32 dim3, char *datatype, void *data)
Definition: HDF_Lib.c:1192
PGSt_SMF_status Read_Overlap_OBCEng(L1A_granule_t *L1A_Gran, emiss_tables_t *emiss_tables, PGSt_PC_Logical lun, Overlap_OBCEng_t *Overlap_OBCEng, boolean *scan_gap)
Definition: Preprocess.c:3660
int16_t * denom[MAXNFILES]
Definition: l2bin.cpp:99
PGSt_SMF_status Cross_Granule_Sliding_Average(int32 num_overlapScans, int32 num_scans_middle, float32 *Xarray, int16 *Xmir, float32 *avg)
Definition: Preprocess.c:2867
float f1(float x)
float mean(float *xs, int sample_size)
Definition: numerical.c:81
#define L1A_DN_SDS_UB
Definition: Granule.h:507
PGSt_SMF_status Get_Electronics_index_special(int32 num_scans, uint16 *Electronics_pri, uint16 *Electronics_red, uint16 *Electronics_index)
Definition: Preprocess.c:3326
float32 a1[NUM_EMISSIVE_DETECTORS]
Definition: L1B_Tables.h:934
PGSt_SMF_status Calculate_Temp_QA(int32 num_scans, Temperatures_t *temps, QA_tables_t *tables, QA_Data_t *QA)
Definition: Preprocess.c:68
int8 all_BB_DN_bad[MAX_NUM_SCANS]
Definition: Granule.h:1064
#define MAX_1KM_TRACK_DIM
Definition: Granule.h:456
#define NUM_T_RC_VALUES
Definition: Granule.h:713
@ INDEX_1000M_DAY
Definition: Granule.h:571
emiss_QA_tables_t emiss_QA_tables
Definition: L1B_Tables.h:945
uint8 noise_T_bb[12]
Definition: Granule.h:1032
int N
Definition: Usds.c:60
#define DN_SAT_10BITS
Definition: PreprocessP.h:175
#define FAIL
Definition: ObpgReadGrid.h:18
#define VEC_DIM_NAME
Definition: PreprocessP.h:154
#define FALSE
Definition: rice.h:164
@ BAND32
Definition: Granule.h:644
Temperatures_t temps
Definition: PreprocessP.h:573
@ INDEX_500M
Definition: Granule.h:570
#define NULL
Definition: decode_rs.h:63
int16 SV_1km_night[MAX_1KM_TRACK_DIM][NUM_1000M_NIGHT_BANDS][SV_1km_FRAMES]
Definition: PreprocessP.h:554
#define CONVERT_TO_UINT8(x, y)
Definition: PreprocessP.h:168
int16 SV_1km_night[MAX_OVERLAP_TRACK_DIM][NUM_1000M_NIGHT_BANDS][SV_1km_FRAMES]
Definition: PreprocessP.h:569
#define NUM_TEMPS
PGSt_SMF_status Write_L1B_OBCEng(L1A_granule_t *L1A_Gran, lookup_tables_t *tables, Moon_arrays_t *moon_arrays, DN_OBC_Avg_t *DN_OBC_Avg)
Definition: Preprocess.c:5608
const int MOON_OUTSIDE_SV_KOB
#define TERRA
Definition: Granule.h:549
#define MODIS_BAND26_INDEX
Definition: Granule.h:446
@ GRAN_AVG_TA_RC_OS_OG
Definition: Granule.h:713
#define FIRST_L1A_GRANULE
Definition: FNames.h:79
#define DN_BG_NUM_FRAMES_SDS_NAME
Definition: PreprocessP.h:153
float32 DN_obc_500m_var[MAX_500M_TRACK_DIM][NUM_500M_BANDS][NUM_500M_SUBSAMP]
Definition: Preprocess.h:123
int16 TARGET_1km_FRAMES[NUM_TARGETS]
Definition: Preprocess.c:23
float32 RVS_250m[NUM_250M_BANDS][DETECTORS_PER_250M_BAND][EV_250m_FRAMES][NUM_MIRROR_SIDES]
Definition: Granule.h:825
#define SCAN_QUALITY_ARRAY
Definition: L1a_data.h:125
#define NUM_500M_SUBSAMP
Definition: Granule.h:442
@ GRAN_AVG_TP_MF_CALBKHD_SR
Definition: Granule.h:701
PARAM_TYPE_NONE Default value No parameter is buried in the product name name_prefix is case insensitive string compared to the product name PARAM_TYPE_VIS_WAVE The visible wavelength bands from the sensor are buried in the product name The product name is compared by appending and name_suffix ie aph_412_giop where prod_ix will be set to PARAM_TYPE_IR_WAVE same search method as PARAM_TYPE_VIS_WAVE except only wavelength above are looped through but prod_ix is still based ie aph_2_giop for the second band
#define GEO_SD_SUN_AZ_SDS_NAME
Definition: PreprocessP.h:148
#define SV_START_TIME
Definition: L1a_data.h:127
boolean Sector_Rotated[MAX_NUM_SCANS]
Definition: PreprocessP.h:572
int16 MirrorSide[MAX_NUM_SCANS]
Definition: PreprocessP.h:570
PGSt_SMF_status Get_Satellite_ID(PGSt_PC_Logical lun, int32 *satellite_ID)
Definition: Granule.c:2924
uint32 DN_obc_1km_night_outlier_mask[MAX_1KM_TRACK_DIM][NUM_1000M_NIGHT_BANDS][NUM_1KM_SUBSAMP][2]
Definition: Preprocess.h:129
PGSt_SMF_status Write_Geo_OBC_SDS(int32 obc_sd_id, int32 num_scans)
Definition: Preprocess.c:5461
uint8 noise_T_mir2
Definition: Granule.h:1037
@ GRAN_AVG_TP_SA_RCT2_MIRE
Definition: Granule.h:699
#define MAX_NUM_BANDS_PER_TYPE
Definition: PreprocessP.h:133
#define ELECTRONICS_REDUNDANT
Definition: PreprocessP.h:142
int16 BB_1km_night[MAX_1KM_TRACK_DIM][NUM_1000M_NIGHT_BANDS][BB_1km_FRAMES]
Definition: PreprocessP.h:551
PGSt_SMF_status Get_Electronics_index(int32 num_scans, uint16 *Electronics_pri, uint16 *Electronics_red, uint16 *Electronics_index)
Definition: Preprocess.c:3224
#define NUM_500M_BANDS
Definition: Granule.h:431
int16 BB_1km_night[MAX_OVERLAP_TRACK_DIM][NUM_1000M_NIGHT_BANDS][BB_1km_FRAMES]
Definition: PreprocessP.h:566
Emiss_Cal_Coeff_t Emiss_Cal_Coeff
Definition: Granule.h:864
#define NUM_ENG_MEM_SDS
#define MODIS_F_OUT_OF_RANGE
@ GRAN_AVG_TP_SA_A_MTR
Definition: Granule.h:700
int32 extract_line_count
Definition: Preprocess.c:66
float32 u2[NUM_REFLECTIVE_DETECTORS][EV_1km_FRAMES][NUM_MIRROR_SIDES]
Definition: Granule.h:839
#define SD
Definition: usrmac.h:196
int32 num_scans
Definition: Granule.h:749
PGSt_SMF_status read_sds_rank3(int32 file_id, char *sds_name, int32 dim1, int32 dim2, int32 dim3, void *data)
Definition: HDF_Lib.c:546
#define TRUE
Definition: rice.h:165
PGSt_SMF_status Check_For_Ecal_On(int32 lun, int32 num_scans, int32 v_id, boolean Ecal_On[][NUM_BANDS])
Definition: Preprocess.c:8207
#define MISSING_L1A_FLAG
Definition: Granule.h:515
@ BAND21
Definition: Granule.h:643
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_INT32
@ INDEX_250M
Definition: Granule.h:569
PGSt_SMF_status write_sds_rank2(int32 file_id, char *sds_name, char *dim_name1, char *dim_name2, int32 dim1, int32 dim2, char *datatype, void *data)
Definition: HDF_Lib.c:1062
@ GRAN_AVG_TA_RC_LWIR_CFPAE
Definition: Granule.h:697
boolean Ecal_On[MAX_NUM_SCANS][NUM_BANDS]
Definition: PreprocessP.h:556
data_t lambda[NROOTS+1]
Definition: decode_rs.h:75
int8 all_SV_DN_bad[MAX_NUM_SCANS]
Definition: Granule.h:1063
#define ON
Definition: l1.h:43
Preprocess_Emiss_t PP_Emiss
Definition: Preprocess.h:176
#define MAX_250M_TRACK_DIM
Definition: Granule.h:454
float32 DN_obc_1km_night_var[MAX_1KM_TRACK_DIM][NUM_1000M_NIGHT_BANDS][NUM_1KM_SUBSAMP]
Definition: Preprocess.h:125
const int NUM_MIRROR_SIDES
const int TRK_UPPER
#define MAX_NUM_VDATA
Definition: PreprocessP.h:160
#define DETECTORS_PER_500M_BAND
Definition: Granule.h:439
float32 NEdL[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:149
@ NUM_TARGETS
Definition: Granule.h:639
PGSt_SMF_status Adjust_dn_star_Min(float32 *dn_star_Min, int32 L1A_v_id, int32 num_scans)
Definition: Preprocess.c:8102
int16 BAND_RATIO_AT_RES[NUM_L1A_RESOLUTIONS]
Definition: Granule.c:73
int8 moon_in_SV_KOB_TEB[MAX_NUM_SCANS]
Definition: Granule.h:1048
#define DETECTORS_PER_1KM_BAND
Definition: Granule.h:438
#define MODIS_BAND20_INDEX
Definition: Granule.h:448
PGSt_SMF_status Get_DN_Avg_SDev_Rejects(int32 start_index, int32 N, int32 index_increment, int16 *DN_array, int16 DN_upper_valid_limit, int16 DN_lower_valid_limit, float32 *mean_DN, float32 *sdev_DN, int16 *rejects)
Definition: Preprocess.c:2480
#define ELECTRONICS_PRIMARY
Definition: PreprocessP.h:141
#define NUM_BAND_TYPES
Definition: PreprocessP.h:134
u5 which has been done in the LOCALGRANULEID metadata should have an extension NRT It is requested to identify the NRT production Changes from v6 which may affect scientific the sector rotation may actually occur during one of the scans earlier than the one where it is first reported As a the b1 values are about the LOCALGRANULEID metadata should have an extension NRT It is requested to identify the NRT to fill pixels affected by dead subframes with a special value Output the metadata of noisy and dead subframe Dead Subframe EV and Detector Quality Flag2 Removed the function call of Fill_Dead_Detector_SI to stop interpolating SI values for dead but also for all downstream products for science test only Changes from v5 which will affect scientific to conform to MODIS requirements Removed the Mixed option from the ScanType in the code because the L1A Scan Type is never Mixed Changed for ANSI C compliance and comments to better document the fact that when the HDF_EOS metadata is stricly the and products are off by and in the track respectively Corrected some misspelling of RCS swir_oob_sending_detector to the Reflective LUTs to enable the SWIR OOB correction detector so that if any of the sending detectors becomes noisy or non near by good detectors from the same sending band can be specified as the substitute in the new look up table Code change for adding an additional dimension of mirror side to the Band_21_b1 LUT to separate the coefficient of the two mirror sides for just like other thermal emissive so that the L1B code can calibrate Band scan to scan with mirror side dependency which leads better calibration result Changes which do not affect scientific when the EV data are not provided in this Crosstalk Correction will not be performed to the Band calibration data Changes which do not affect scientific SV_500m
Definition: HISTORY.txt:334
PGSt_SMF_status Fill_500m_DN_OBC_Avg(int32 sd_id, int32 num_scans, int16 *MirrorSide, refl_tables_t *refl_tables, Moon_arrays_t *moon_arrays, boolean Ecal_On[][NUM_BANDS], DN_OBC_Avg_t *DN_OBC_Avg, QA_Refl_t *QA_refl)
Definition: Preprocess.c:7279
PGSt_SMF_status write_sds_rank1(int32 file_id, char *sds_name, char *dim_name, int32 dim, char *datatype, void *data)
Definition: HDF_Lib.c:944
float32 RVS_1km_Emiss_SV[NUM_EMISSIVE_DETECTORS][NUM_MIRROR_SIDES]
Definition: Granule.h:848
#define DN_SAT_9BITS
Definition: PreprocessP.h:174
#define MAX_500M_OBC_FRAME_DIM
Definition: Granule.h:460
@ GRAN_AVG_VR_RC_LW_FPA_HTR
Definition: Granule.h:714
const double F
PGSt_SMF_status sort_int16_array(int32 n, int16 *a, int32 *indx)
Definition: Preprocess.c:8569
#define MODIS_F_FILE_NOT_CREATED
uint16 vis_adc_index[MAX_NUM_SCANS]
Definition: PreprocessP.h:537
float32 DN_obc_250m_avg[MAX_250M_TRACK_DIM][NUM_250M_BANDS][NUM_250M_SUBSAMP]
Definition: Preprocess.h:118
float32 sigma_a0[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:140
PGSt_SMF_status Copy_PixelQualityData(int32 in_sd_id, int32 out_sd_id, int32 num_scans)
Definition: Preprocess.c:6195
#define MAX_OVERLAP_TRACK_DIM
Definition: PreprocessP.h:145
PGSt_SMF_status read_sds_rank1(int32 file_id, char *sds_name, int32 dim, void *data)
Definition: HDF_Lib.c:359
#define INVALID_SATELLITE_ID
Definition: Granule.h:551
#define LEADING_L1A_GRANULE
Definition: FNames.h:78
QA_Refl_t QA_refl
Definition: Granule.h:1099
#define GEOLOCATION_FILE
Definition: FNames.h:82
float f2(float y)
PGSt_SMF_status Get_Temp_Avg_And_Variance(int32 N, float32 *T, float32 *avg, float32 *var)
Definition: Preprocess.c:3038
Preprocess_Refl_t PP_Refl
Definition: Preprocess.h:175
PGSt_SMF_status Process_OBCEng_Emiss(L1A_granule_t *L1A_Gran, L1A_granule_OBCEng_t *L1A_OBCEng, Emiss_Cal_Coeff_t *RVS_Coeff, emiss_tables_t *tables, QA_tables_t *QA_tables, Moon_arrays_t *moon_arrays, QA_Data_t *QA, Preprocess_Emiss_t *PP, DN_OBC_Avg_t *DN_OBC_Avg)
Definition: Preprocess.c:1094
int32 v_id
Definition: Granule.h:746
const int NUM_BANDS
const int SCN_LOWER
PGSt_SMF_status Get_Emiss_Coeff_Per_Scan(int8 moon_in_SV_KOB, int16 *BB, int16 *SV, int16 B, int16 D, int16 D_emiss, int16 MS, Emiss_Cal_Coeff_t *RVS_Coeff, emiss_tables_t *tables, float32 T_bb, float32 T_mir, float32 T_cav, float32 T_ins, float32 T_fp_lwir, float32 *Xdn_bb_31, float32 *Xb1, float32 *xdLbb, float32 *xdnbb, float32 *xLbb, float32 *xLcav, float32 *xdnsv, float32 *xdnsv_var, uint32 *sv_omask, float32 *SNR, int32 satellite_ID)
Definition: Preprocess.c:389
int16 RFLAG
Definition: Granule.c:75
uint32 DN_obc_250m_outlier_mask[MAX_250M_TRACK_DIM][NUM_250M_BANDS][NUM_250M_SUBSAMP][2]
Definition: Preprocess.h:126
PGSt_SMF_status Fill_Invalid_Temp_DNs(int32 num_scans, uint16 miss_DN, uint16 sat_DN, uint16 *DN)
Definition: Preprocess.c:3119
#define MOON_VECTOR_SDS_NAME
Definition: PreprocessP.h:158
float32 sigma_a2[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:143
float32 T_fp[NUM_FOCAL_PLANES][MAX_NUM_SCANS]
Definition: Preprocess.h:152
#define SATURATED_DN
Definition: Granule.h:511
uint8 noise_T_vis
Definition: Granule.h:1053
#define MAX_ENG_MEM_DATA_DIM
Definition: PreprocessP.h:159
uint16 mwir_adc_index[MAX_NUM_SCANS]
Definition: PreprocessP.h:535
float32 dn_bb[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:145
int16 L1A_BANDS_AT_RES[NUM_L1A_RESOLUTIONS]
Definition: Granule.c:63
@ BAND26
Definition: Granule.h:643
int16 DN_obc_avg_number_of_frames_to_use
Definition: L1B_Tables.h:650
#define NUM_SCANS_DIM_NAME
Definition: Granule.h:416
#define AQUA
Definition: Granule.h:550
float32 a2[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:142
uint8 noise_T_mwir
Definition: Granule.h:1035
int8 moon_in_SV_KOB_RSB[MAX_NUM_SCANS]
Definition: Granule.h:1062
uint8 noise_T_bb_avg
Definition: Granule.h:1033
int32 extract_pixel_offset
Definition: Preprocess.c:63
#define I
#define VOLTAGE_BAD_VALUE
Definition: Granule.h:718
PGSt_SMF_status Copy_EngVdata(int32 in_v_id, int32 out_v_id)
Definition: Preprocess.c:6529
PGSt_SMF_status Calculate_PP_Planck_Mir(int32 num_scans, emiss_tables_t *tables, Preprocess_Emiss_t *PP)
Definition: Preprocess.c:1539
#define OBC_SD_SUN_AZ_SDS_NAME
Definition: PreprocessP.h:150
#define MODIS_F_READ_ERROR
char * L1A_FRAME_DIM_NAME[NUM_TARGETS-1][NUM_L1A_RESOLUTIONS]
Definition: Preprocess.c:49
Temperatures_t temps
Definition: PreprocessP.h:558
#define NUM_PV_NIR_BANDS
Definition: PreprocessP.h:136
#define EV_1km_FRAMES
Definition: Granule.h:469
#define TRAILING_L1A_GRANULE
Definition: FNames.h:80
#define CONVERT_TEMP_POLY(tdk, tdn, c, dnsat, toffset)
const int NUM_REFLECTIVE_BANDS
#define Celsius_To_Kelvin_Offset
Definition: PreprocessP.h:173
#define VEC_DIM
Definition: PreprocessP.h:157
PGSt_SMF_status Check_Valid_Range(char *data_name, int32 data_type, char *a_lb, char *a_ub, char *a_fillvalue, int32 count, void *buffer)
Definition: HDF_Lib.c:1782
float32 DN_obc_1km_day_var[MAX_1KM_TRACK_DIM][NUM_1000M_DAY_BANDS][NUM_1KM_SUBSAMP]
Definition: Preprocess.h:124
#define GEO_NUM_SCANS_NAME
Definition: PreprocessP.h:147
int32 extract_line_offset
Definition: Preprocess.c:65
uint32 DN_obc_1km_day_outlier_mask[MAX_1KM_TRACK_DIM][NUM_1000M_DAY_BANDS][NUM_1KM_SUBSAMP][2]
Definition: Preprocess.h:128
const int SCN_UPPER
float32 DN_obc_250m_var[MAX_250M_TRACK_DIM][NUM_250M_BANDS][NUM_250M_SUBSAMP]
Definition: Preprocess.h:122
#define NUM_1KM_SUBSAMP
Definition: Granule.h:441
float32 T_mir[MAX_NUM_SCANS]
Definition: Preprocess.h:154
float32 cav[MAX_NUM_SCANS]
Definition: PreprocessP.h:529
#define INDEX_1000M_EMISS
Definition: Granule.h:576
#define SCAN_NUMBER
Definition: L1a_data.h:124
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude resolving resolving GSFcd00179 Corrected handling of fill values for[Sensor|Solar][Zenith|Azimuth] resolving MODxl01751 Changed to validate LUT version against a value retrieved from the resolving MODxl02056 Changed to calculate Solar Diffuser angles without adjustment for estimated post launch changes in the MODIS orientation relative to incidentally resolving defects MODxl01766 Also resolves MODxl01947 Changed to ignore fill values in SCI_ABNORM and SCI_STATE fields
Definition: HISTORY.txt:400
#define NUM_250M_SUBSAMP
Definition: Granule.h:443
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 T_bb[MAX_NUM_SCANS]
Definition: Preprocess.h:153
const double delta
PGSt_SMF_status Get_Middle_Gran_Emiss_Coeff(L1A_granule_OBCEng_t *L1A_OBCEng, int16 B, int16 D, int16 D_emiss, Emiss_Cal_Coeff_t *RVS_Coeff, emiss_tables_t *tables, emiss_QA_tables_t *QA_tables, Moon_arrays_t *moon_arrays, float32 Xdn_bb_31[][DETECTORS_PER_1KM_BAND], float32 *Xb1, int16 *XMS, QA_Emiss_t *QA, Preprocess_Emiss_t *PP, DN_OBC_Avg_t *DN_OBC_Avg, int32 satellite_ID)
Definition: Preprocess.c:1839
#define SCIENCE_STATE
Definition: L1a_data.h:128
float32 mir1[MAX_NUM_SCANS]
Definition: PreprocessP.h:525
a context in which it is NOT documented to do so subscript which cannot be easily calculated when extracting TONS attitude data from the Terra L0 files Corrected several defects in extraction of entrained ephemeris and and as HDF file for both the L1A and Geolocation enabling retrieval of South Polar DEM data Resolved Bug by changing to opent the geolocation file only after a successful read of the L1A and also by checking for fatal errors from not restoring C5 and to report how many of those high resolution values were water in the new WaterPresent SDS Added valid_range attribute to Land SeaMask Changed to bilinearly interpolate the geoid_height to remove artifacts at one degree lines Made corrections to const qualification of pointers allowed by new version of M API library Removed casts that are no longer for same not the geoid Corrected off by one error in calculation of high resolution offsets Corrected parsing of maneuver list configuration parameter Corrected to set Height SDS to fill values when geolocation when for elevation and land water mask
Definition: HISTORY.txt:114
PGSt_SMF_status read_part_sds_rank3(int32 sd_id, char *sds_name, int32 start0, int32 start1, int32 start2, int32 edge0, int32 edge1, int32 edge2, void *data)
Definition: HDF_Lib.c:249
#define NUM_U2_FRAME
Definition: L1B_Tables.h:427
#define GEO_SD_SUN_ZEN_SDS_NAME
Definition: PreprocessP.h:149
float32 mir2[MAX_NUM_SCANS]
Definition: PreprocessP.h:526
PGSt_SMF_status Get_Leading_Gran_Emiss_Coeff(Overlap_OBCEng_t *Leading_OBCEng, int16 B, int16 D, int16 D_emiss, Emiss_Cal_Coeff_t *RVS_Coeff, emiss_tables_t *tables, Moon_arrays_t *moon_arrays, float32 Xdn_bb_31[][DETECTORS_PER_1KM_BAND], float32 *Xb1, int16 *XMS, int32 satellite_ID)
Definition: Preprocess.c:1607
integer, parameter double
float32 DN_sv[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:144
PGSt_SMF_status Get_DN_Avg_SDev_Rejects_LowN(int32 N_include, int32 start_index, int32 N, int32 index_increment, int16 *DN_array, int16 DN_upper_valid_limit, int16 DN_lower_valid_limit, float32 *mean_DN, float32 *sdev_DN, int16 *rejects)
Definition: Preprocess.c:8631
PGSt_SMF_status Calculate_RVS_Correction(lookup_tables_t *tables, L1B_granule_t *L1B_Gran)
Definition: Preprocess.c:8804
#define NUM_SM_BANDS
Definition: PreprocessP.h:137
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_INT16
#define CALC_ONE_TEMP_QA(t, tablevar, output)
Engineering_Coefficients_t Engineering_Coefficients_FM1
Definition: PreprocessP.h:388
const int UNDETERMINED_MOON_IN_SV_KOB
PGSt_SMF_status read_attribute(int32 s_id, char *attr_name, int32 TypeID, void *buffer)
Definition: HDF_Lib.c:33
#define DN_SAT_12BITS
Definition: PreprocessP.h:176
@ FP_LWIR
Definition: Preprocess.h:114
#define SV_CNTR_ANG_FROM_Y
Definition: PreprocessP.h:165
PGSt_SMF_status Copy_ScanMetadata(int32 in_sd_id, int32 out_sd_id, int32 num_scans)
Definition: Preprocess.c:6345
#define INNER_GRANULE_TIMEDIFF_TOLERANCE
Definition: PreprocessP.h:199
#define MODIS_F_NOK
@ GRAN_AVG_TA_AO_NIR_FPAE
Definition: Granule.h:695
#define MAX_NUM_OVERLAP_SCANS
Definition: PreprocessP.h:144
#define MOON_IN_KOB_SDS_NAME
Definition: PreprocessP.h:156
uint16 nir_adc_index[MAX_NUM_SCANS]
Definition: PreprocessP.h:536
uint8 num_thermistor_outliers[MAX_NUM_SCANS]
Definition: Granule.h:1043
int16 MirrorSide[MAX_NUM_SCANS]
Definition: PreprocessP.h:555
float32 bb_avg[MAX_NUM_SCANS]
Definition: PreprocessP.h:532
PGSt_SMF_status Fill_Band_26_DN_OBC_Avg(int32 sd_id, int32 num_scans, int16 *MirrorSide, refl_tables_t *refl_tables, Moon_arrays_t *moon_arrays, boolean Ecal_On[][NUM_BANDS], DN_OBC_Avg_t *DN_OBC_Avg, QA_Refl_t *QA_refl)
Definition: Preprocess.c:7864
PGSt_SMF_status Fill_250m_DN_OBC_Avg(int32 sd_id, int32 num_scans, int16 *MirrorSide, refl_tables_t *refl_tables, Moon_arrays_t *moon_arrays, boolean Ecal_On[][NUM_BANDS], DN_OBC_Avg_t *DN_OBC_Avg, QA_Refl_t *QA_refl)
Definition: Preprocess.c:6993
PGSt_SMF_status Check_If_Sector_Rotated(int32 lun, int32 num_scans, int32 v_id, boolean Sector_Rotated[])
Definition: Preprocess.c:8416
float32 dn_bb_sdev[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:146
#define True
Definition: Granule.h:537
PGSt_SMF_status write_sds_rankn(int32 file_id, char *sds_name, int32 data_type, int32 rank, int32 *edge, char **dim_name, void *data)
Definition: HDF_Lib.c:1648
#define TOLERANCE
Definition: Granule.h:535
uint16 pclw_adc_index[MAX_NUM_SCANS]
Definition: PreprocessP.h:538
float32 L_cav[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:148
#define MAX_NUM_SCANS
Definition: Granule.h:422
uint8 num_thermistor_outliers[MAX_NUM_SCANS]
Definition: PreprocessP.h:539
PGSt_SMF_status Get_Trailing_Gran_Emiss_Coeff(int32 num_scans_middle, Overlap_OBCEng_t *Trailing_OBCEng, int16 B, int16 D, int16 D_emiss, Emiss_Cal_Coeff_t *RVS_Coeff, emiss_tables_t *tables, Moon_arrays_t *moon_arrays, float32 Xdn_bb_31[][DETECTORS_PER_1KM_BAND], float32 *Xb1, int16 *XMS, int32 satellite_ID)
Definition: Preprocess.c:2098
uint8 noise_T_nir
Definition: Granule.h:1054
uint16 lwir_adc_index[MAX_NUM_SCANS]
Definition: PreprocessP.h:534
float32 RVS_1km_Emiss_EV[NUM_EMISSIVE_DETECTORS][EV_1km_FRAMES][NUM_MIRROR_SIDES]
Definition: Granule.h:846
float32 granule_averages[MAX_NUM_GRAN_AVERAGES]
Definition: Granule.h:1092
PGSt_SMF_status Granule_Average_Temperature(int32 num_values, float32 *array, float32 *avg)
Definition: Preprocess.c:2973
float32 ins_temp[NUM_T_INS_THERMISTORS][MAX_NUM_SCANS]
Definition: PreprocessP.h:540
uint8 noise_T_lwir
Definition: Granule.h:1034
#define NUM_SCANMETA_SDS
uint32 DN_obc_500m_outlier_mask[MAX_500M_TRACK_DIM][NUM_500M_BANDS][NUM_500M_SUBSAMP][2]
Definition: Preprocess.h:127
PGSt_SMF_status read_sds_rank2(int32 file_id, char *sds_name, int32 dim1, int32 dim2, void *data)
Definition: HDF_Lib.c:449
@ INDEX_1000M_NIGHT
Definition: Granule.h:572
#define OBC_SD_SUN_ZEN_SDS_NAME
Definition: PreprocessP.h:151
boolean Sector_Rotated[MAX_NUM_SCANS]
Definition: PreprocessP.h:557
PGSt_SMF_status Pack_Rejects_In_Outlier_Mask(int32 N, int16 *rejects, uint32 *packed_rejects)
Definition: Preprocess.c:2641
int32 extract_pixel_count
Definition: Preprocess.c:64
#define BB_1km_FRAMES
Definition: Granule.h:467
uint8 noise_T_mir_avg
Definition: Granule.h:1038
float32 NEdL[NUM_EMISSIVE_DETECTORS]
Definition: L1B_Tables.h:933
#define fabs(a)
Definition: misc.h:93
boolean trailing_granule_scan_gap
Definition: Granule.h:1073
int16 DN_obc_avg_first_frame_to_use
Definition: L1B_Tables.h:648
char * L1A_TARGET_SDS_NAME[NUM_TARGETS][NUM_L1A_RESOLUTIONS]
Definition: Preprocess.c:27
#define SV_1km_FRAMES
Definition: Granule.h:468
#define DN_BG_FIRST_FRAME_SDS_NAME
Definition: PreprocessP.h:152
Extra metadata that will be written to the HDF4 file l2prod rank
#define L1A_DN_SDS_FV
Definition: Granule.h:508
#define NUM_BANDS_DIM_NAME
Definition: PreprocessP.h:155
#define NUM_1000M_NIGHT_BANDS
Definition: Granule.h:437
int8 fp_set_point_state[MAX_NUM_SCANS]
Definition: Preprocess.h:169
int8 moon_in_SV_KOB[MAX_NUM_SCANS][NUM_BANDS]
Definition: PreprocessP.h:519
QA_Emiss_t QA_emiss
Definition: Granule.h:1098
#define NUM_REFLECTIVE_DETECTORS
Definition: Granule.h:427
DN_OBC_Avg_t DN_OBC_Avg
Definition: Preprocess.h:174
RSB_Cal_Coeff_t RSB_Cal_Coeff
Definition: Granule.h:863
uint8 noise_T_mir1
Definition: Granule.h:1036
#define MAX_1KM_OBC_FRAME_DIM
Definition: Granule.h:461
#define MIRROR_SIDE
Definition: L1a_data.h:117
#define NUM_PV_VIS_BANDS
Definition: PreprocessP.h:135
int32 sd_id
Definition: Granule.h:747
#define PIXEL_WIDTH_RADIANS
Definition: PreprocessP.h:164
PGSt_SMF_status Process_OBCEng_Refl(int32 sd_id, int32 num_scans, float32 *T_ins, int16 *MirrorSide, refl_tables_t *refl_tables, Moon_arrays_t *moon_arrays, L1A_granule_OBCEng_t *L1A_OBCEng, DN_OBC_Avg_t *DN_OBC_Avg, QA_Refl_t *QA_refl, Preprocess_Refl_t *PP_Refl)
Definition: Preprocess.c:2713
PGSt_SMF_status Fill_1km_day_DN_OBC_Avg(int32 sd_id, int32 num_scans, int16 *MirrorSide, refl_tables_t *refl_tables, Moon_arrays_t *moon_arrays, boolean Ecal_On[][NUM_BANDS], DN_OBC_Avg_t *DN_OBC_Avg, QA_Refl_t *QA_refl)
Definition: Preprocess.c:7576
data_t s[NROOTS]
Definition: decode_rs.h:75
#define NUM_T_CAV_THERMISTORS
Definition: L1B_Tables.h:421
#define MAX_TOTAL_XGRAN_SCANS
Definition: PreprocessP.h:146
float32 scn_mtr[MAX_NUM_SCANS]
Definition: PreprocessP.h:528
#define NUM_250M_BANDS
Definition: Granule.h:430
const int NUM_FOCAL_PLANES
boolean missing_leading_granule
Definition: Granule.h:1070
int32 satellite_id
Definition: Granule.h:748
char * L1A_BAND_DIM_NAME[NUM_L1A_RESOLUTIONS]
Definition: Preprocess.c:41
#define NUM_PIXEL_QUALITY_SDS
int8 fp_set_point_state[MAX_NUM_SCANS]
Definition: PreprocessP.h:533
float32 cav_temp[NUM_T_CAV_THERMISTORS][MAX_NUM_SCANS]
Definition: PreprocessP.h:541
u5 which has been done in the LOCALGRANULEID metadata should have an extension NRT It is requested to identify the NRT production Changes from v6 which may affect scientific the sector rotation may actually occur during one of the scans earlier than the one where it is first reported As a the b1 values are about the LOCALGRANULEID metadata should have an extension NRT It is requested to identify the NRT to fill pixels affected by dead subframes with a special value Output the metadata of noisy and dead subframe Dead Subframe EV and Detector Quality Flag2 Removed the function call of Fill_Dead_Detector_SI to stop interpolating SI values for dead but also for all downstream products for science test only Changes from v5 which will affect scientific to conform to MODIS requirements Removed the Mixed option from the ScanType in the code because the L1A Scan Type is never Mixed Changed for ANSI C compliance and comments to better document the fact that when the HDF_EOS metadata is stricly the and products are off by and in the track respectively Corrected some misspelling of RCS swir_oob_sending_detector to the Reflective LUTs to enable the SWIR OOB correction detector so that if any of the sending detectors becomes noisy or non near by good detectors from the same sending band can be specified as the substitute in the new look up table Code change for adding an additional dimension of mirror side to the Band_21_b1 LUT to separate the coefficient of the two mirror sides for just like other thermal emissive so that the L1B code can calibrate Band scan to scan with mirror side dependency which leads better calibration result Changes which do not affect scientific when the EV data are not provided in this Crosstalk Correction will not be performed to the Band calibration data Changes which do not affect scientific BB_250m
Definition: HISTORY.txt:334
#define MODIS_F_HDF_ERROR
PGSt_SMF_status Get_All_Emiss_Coeff(L1A_granule_OBCEng_t *L1A_OBCEng, int16 B, int16 D_emiss, float32 *Xb1, int16 *Xmir, emiss_tables_t *tables, emiss_QA_tables_t *QA_tables, QA_Emiss_t *QA, Preprocess_Emiss_t *PP)
Definition: Preprocess.c:2305
for(i=0;i< NROOTS;i++) s[i]
Definition: decode_rs.h:85
#define SD_START_TIME
Definition: L1a_data.h:126
#define NUM_PC_LW_BANDS
Definition: PreprocessP.h:139
#define MAX_250M_OBC_FRAME_DIM
Definition: Granule.h:459
#define OUTER_GRANULE_TIMEDIFF_TOLERANCE
Definition: PreprocessP.h:200
#define NUM_RSB_RVS_COEFFS
Definition: L1B_Tables.h:428
#define L1B_OBC_FILE
Definition: FNames.h:72
int16 DETECT_PER_BAND_AT_RES[NUM_L1A_RESOLUTIONS]
Definition: Granule.c:68
float32 BB_a[NUM_BB_THERMISTORS][4]
Definition: PreprocessP.h:234
#define R
Definition: make_L3_v1.1.c:96
PGSt_SMF_status Preprocess_L1A_Data(lookup_tables_t *tables, L1A_granule_t *L1A_Gran, L1B_granule_t *L1B_Gran, QA_Data_t *QA, Preprocess_Data_t *PP)
Definition: Preprocess.c:899
void L1BErrorMsg(char *L1B_location, PGSt_SMF_code code, char *input_message, char *assoc_function, int32 lun, char *other_msg, boolean error_out)
Definition: Granule.c:918
char Invalid_MOD01_Msg[]
Definition: Granule.c:913
#define MODIS_F_FILE_NOT_OPENED
@ GRAN_AVG_TP_AO_LWIR_LENS
Definition: Granule.h:708
#define NUM_1000M_DAY_BANDS
Definition: Granule.h:436
@ NUM_L1A_RESOLUTIONS
Definition: Granule.h:573
#define MAX_VDATA_SIZE
Definition: PreprocessP.h:161
GNU GENERAL PUBLIC LICENSE Version
Definition: LICENSE.txt:2
float32 moon_vector[MAX_NUM_SCANS][VEC_DIM]
Definition: PreprocessP.h:518
float32 Planck_mir[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:138
#define RVS_CORRECTION_LOWER_LIMIT
Definition: PreprocessP.h:190
#define NUM_1000M_REFL_BANDS
Definition: Granule.h:432
#define NUM_PV_LW_BANDS
Definition: PreprocessP.h:138
@ GRAN_AVG_TP_AO_SMIR_OBJ
Definition: Granule.h:705
float32 ins[MAX_NUM_SCANS]
Definition: PreprocessP.h:530
@ BAND31
Definition: Granule.h:644
#define MAX_NUM_GRAN_AVERAGES
Definition: Granule.h:706
int32 SUBSAMPLES_AT_RES[NUM_L1A_RESOLUTIONS]
Definition: Preprocess.c:21
#define RVS_CORRECTION_UPPER_LIMIT
Definition: PreprocessP.h:189
const int NUM_EMISSIVE_BANDS
#define MAX_500M_TRACK_DIM
Definition: Granule.h:455
int16 num_overlap_scans_b1
Definition: L1B_Tables.h:804
#define WRITE_DN_BG_AT_RES(r, avg, var, omask)
PGSt_SMF_status read_vdata(int32 v_id, int32 start_record, int32 records, char *vname, char *fname, void *buffer)
Definition: HDF_Lib.c:748
int i
Definition: decode_rs.h:71
#define ELECTRONICS_BOTH
Definition: PreprocessP.h:143
#define MODIS_F_INVALID_ARGUMENT
float32 C_RC[NUM_T_RC_VALUES][6]
Definition: PreprocessP.h:232
int read_extract_metadata(int32 sd_id, int32 *extract_pixel_offset, int32 *extract_pixel_count, int32 *extract_line_offset, int32 *extract_line_count)
const int NUM_BB_THERMISTORS
const int MOON_INSIDE_SV_KOB
PGE01 indicating that PGE02 PGE01 V6 for and PGE01 V2 for MOD03 were used to produce the granule By convention adopted in all MODIS Terra PGE02 code versions are The fourth digit of the PGE02 version denotes the LUT version used to produce the granule The source of the metadata environment variable ProcessingCenter was changed from a QA LUT value to the Process Configuration A sign used in error in the second order term was changed to a
Definition: HISTORY.txt:424
int MS[]
Definition: Usds.c:106
int16 MirrorSide[MAX_NUM_SCANS]
Definition: Granule.h:751
#define EVAL_2ND_ORDER_POLYNOMIAL(p, a, x, y)
Definition: L1B_Tables.h:379
PGSt_SMF_status Compute_BB_Temperature(emiss_tables_t *tables, int32 start_scan, int32 num_scans, uint16 *CP_index, uint16 **raw_BB_temp, int32 satellite_ID, Temperatures_t *temps)
Definition: Preprocess.c:5223
#define SCAN_TIME_INTERVAL
Definition: PreprocessP.h:193
float32 RVS_1km_RefSB[NUM_1000M_REFL_BANDS][DETECTORS_PER_1KM_BAND][EV_1km_FRAMES][NUM_MIRROR_SIDES]
Definition: Granule.h:835
float32 L_bb[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:147
float32 fp[NUM_FOCAL_PLANES][MAX_NUM_SCANS]
Definition: PreprocessP.h:524
uint8 NEdL[NUM_EMISSIVE_DETECTORS]
Definition: Granule.h:1041
@ GRAN_AVG_TP_SA_RCT1_MIRE
Definition: Granule.h:698
char * L1A_TRACK_DIM_NAME[NUM_L1A_RESOLUTIONS]
Definition: Preprocess.c:45
PGSt_SMF_status read_sds_rankn(int32 sd_id, char *sds_name, int32 data_type, int32 rank, int32 *start, int32 *edge, void *data)
Definition: HDF_Lib.c:1478
int16 RSB_SV_DN_moon_include_frames
Definition: L1B_Tables.h:727
@ GRAN_AVG_TP_MF_CVR_OP_SR
Definition: Granule.h:704
float64 EVStartTime_TAIsecond[MAX_NUM_SCANS]
Definition: Granule.h:753
float32 T_ins[MAX_NUM_SCANS]
Definition: Preprocess.h:155
#define DETECTORS_PER_250M_BAND
Definition: Granule.h:440
@ GRAN_AVG_TA_RC_SMIR_CFPAE
Definition: Granule.h:696
float32 bb[NUM_BB_THERMISTORS][MAX_NUM_SCANS]
Definition: PreprocessP.h:531
#define False
Definition: Granule.h:538
boolean Ecal_On[MAX_NUM_SCANS][NUM_BANDS]
Definition: PreprocessP.h:571
PGSt_SMF_status Read_L1A_OBCEng(emiss_tables_t *emiss_tables, L1A_granule_t *L1A_Gran, L1A_granule_OBCEng_t *L1A_OBCEng)
Definition: Preprocess.c:3426
float32 a0[NUM_EMISSIVE_DETECTORS][MAX_NUM_SCANS]
Definition: Preprocess.h:139
@ BB_INDEX
Definition: Granule.h:636
float32 DN_obc_1km_day_avg[MAX_1KM_TRACK_DIM][NUM_1000M_DAY_BANDS][NUM_1KM_SUBSAMP]
Definition: Preprocess.h:120
@ GRAN_AVG_TA_AO_VIS_FPAE
Definition: Granule.h:694
int count
Definition: decode_rs.h:79