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