OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
L1B_Setup.c
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 File: L1B_Setup.c
4 
5 External functions:
6  L1B_Setup
7  Write_L1B_ScanMeta
8  Determine_Other_Missing_Scans
9 
10 Other functions:
11  Open_L1A_EV_SDS
12  Calculate_Earth_Sun_Distance
13  Calculate_RSB_Cal_Coeff
14  Init_L1B_ScaleOffset
15  Calculate_B26_B5_Correction
16  Open_W_L1B_Granule
17  Create_L1B_Swath
18  Write_Swath_Band_Number
19  Open_L1B_EV_SDS
20  Set_L1B_EV_SDS_Attrs
21  Set_Unit_Range_Fillvalue
22  Get_SDS_id
23  Set_SDS_Attributes
24  Create_Band_Subsetting_SDS
25  Copy_Geo_SDS
26  Scan_Meta_Cal
27  Calculate_DCR_Change
28  Init_QA_Parameters
29  Determine_Split_Scans
30  Get_Split_Scan_Indexes
31  Set_UI_ConvertToPercent_Attrs
32 
33 Note:
34  In the the various functions, there is a return statement after each
35  L1BErrorMsg function call. These are actually not necessary if the last
36  argument to L1BErrorMsg is "True". These returns make it easier to test
37  error out conditions (with SMF_ERROR used in UNIT_TEST_MODE_ONLY -- it does
38  not actually exit).
39 
40 Revision History:
41  $Log: L1B_Setup.c,v $
42  Revision 1.30 2015-03-13 10:58:28-04 xgeng
43  Fix the anomaly before and after the sector rotation due to the timing mismatch between the command performed and the status updated.
44 
45  Revision 1.29 2010-11-15 10:36:35-05 xgeng
46  Added a QA flag to identify the scan with both sides of PCLW on.
47 
48  Revision 1.28 2009/08/27 14:33:31 xgeng
49  Fixed a bug at the initialization of the num_dead_subframe_EV_data
50 
51  Revision 1.27 2008/11/18 19:40:10 xgeng
52  merge branch for V6.0.0
53 
54  Revision 1.26.2.2 2008/06/05 14:07:50 xgeng
55  Initialize dead_subframe_pixels and num_dead_subframe_EV_data
56 
57  Revision 1.26 2008/01/31 21:45:17 ltan
58  Relax the RVS correction limit range. Removed the ScanType of "Mixed" from the code.
59 
60  Revision 1.25 2006/10/30 14:54:47 ltan
61  Removed the "Mixed" option from ScanType since L1A "Scan Type" never "Mixed". Some comments regarding Night mode handling corrected.
62 
63  *****************************************************************************/
64 
65 #include <string.h>
66 #include <math.h>
67 /* Replace <malloc.h> with the standard head file <stdlib.h> for ANSI-C
68  compliance (Razor Issue 173). */
69 #include <stdlib.h>
70 #include <time.h>
71 #include "L1B_Setup.h"
72 #include "L1B_Tables.h"
73 #include "Metadata.h"
74 #include "HDF_Lib.h"
75 #include "PGS_PC.h"
76 #include "PGS_TD.h"
77 #include "PGS_Error_Codes.h"
78 #include "FNames.h"
79 #include "L1B_SetupP.h" /* local prototypes and structures */
80 
81 /*
82  * L1A_EV_SDS_NAME -- names of the earth-view SDSs in the L1A granule.
83  * Used in opening access to those SDSs.
84  */
86  "EV_250m", "EV_500m", "EV_1km_day", "EV_1km_night"
87 };
88 
89 /*-----------------------------------------
90  L1B file spec
91  (SI = Scaled Integer)
92  (UI = Uncertainty Index)
93  (SU = Samples Used)
94  L1B_EV_SDS_index_t Defines macros for the indices in the SDS name arrays.
95  L1B_EV_SDS_NAME Names of all earth-view SDSs in the L1B files.
96  L1B_EV_SDS_LONG_NAME Long names for the EV SDSs
97 -----------------------------------------*/
98 typedef enum
99 {
109 
111 {
112  "EV_250_RefSB", "EV_250_RefSB_Uncert_Indexes",
113  "EV_500_RefSB", "EV_500_RefSB_Uncert_Indexes",
114  "EV_1KM_RefSB", "EV_1KM_RefSB_Uncert_Indexes",
115  "EV_1KM_Emissive", "EV_1KM_Emissive_Uncert_Indexes",
116  "EV_250_Aggr500_RefSB", "EV_250_Aggr500_RefSB_Uncert_Indexes",
117  "EV_250_Aggr500_RefSB_Samples_Used",
118  "EV_250_Aggr1km_RefSB", "EV_250_Aggr1km_RefSB_Uncert_Indexes",
119  "EV_250_Aggr1km_RefSB_Samples_Used",
120  "EV_500_Aggr1km_RefSB", "EV_500_Aggr1km_RefSB_Uncert_Indexes",
121  "EV_500_Aggr1km_RefSB_Samples_Used"
122 };
123 
125 {
126  "Earth View 250M Reflective Solar Bands Scaled Integers",
127  "Earth View 250M Reflective Solar Bands Uncertainty Indexes",
128  "Earth View 500M Reflective Solar Bands Scaled Integers",
129  "Earth View 500M Reflective Solar Bands Uncertainty Indexes",
130  "Earth View 1KM Reflective Solar Bands Scaled Integers",
131  "Earth View 1KM Reflective Solar Bands Uncertainty Indexes",
132  "Earth View 1KM Emissive Bands Scaled Integers",
133  "Earth View 1KM Emissive Bands Uncertainty Indexes",
134  "Earth View 250M Aggregated 500M Reflective Solar Bands "
135  "Scaled Integers",
136  "Earth View 250M Aggregated 500M Reflective Solar Bands "
137  "Uncertainty Indexes",
138  "Earth View 250M Aggregated 500M Reflective Solar Bands "
139  "Number of Samples Used in Aggregation",
140  "Earth View 250M Aggregated 1km Reflective Solar Bands "
141  "Scaled Integers",
142  "Earth View 250M Aggregated 1km Reflective Solar Bands "
143  "Uncertainty Indexes",
144  "Earth View 250M Aggregated 1km Reflective Solar Bands "
145  "Number of Samples Used in Aggregation",
146  "Earth View 500M Aggregated 1km Reflective Solar Bands "
147  "Scaled Integers",
148  "Earth View 500M Aggregated 1km Reflective Solar Bands "
149  "Uncertainty Indexes",
150  "Earth View 500M Aggregated 1km Reflective Solar Bands "
151  "Number of Samples Used in Aggregation"
152 };
153 
154 /*
155  * Band_subsetting_names Names of the swath fields for bands subsetting SDSs.
156  * L1B_EV_DIM_NAME Dimension names. 1st column for band subsetting.
157  */
158 
160  "Band_250M",
161  "Band_500M",
162  "Band_1KM_RefSB",
163  "Band_1KM_Emissive"
164 };
165 
166 #define L1B_EV_SDS_RANK 3
167 
169  {"Band_250M", "40*nscans", "4*Max_EV_frames"},
170  {"Band_500M", "20*nscans", "2*Max_EV_frames"},
171  {"Band_1KM_RefSB", "10*nscans", "Max_EV_frames"},
172  {"Band_1KM_Emissive", "10*nscans", "Max_EV_frames"}
173 };
174 
175 /* Mapping offsets in scan and track directions:
176 */
178  {1, 0}, {0, 0}, {0, 0}, {0, 0}
179 };
180 
181 /* Mapping fractional offsets in scan and track directions:
182 */
184  {0.5, 0.0}, {0.5, 0.0}, {0.0, 0.0}, {0.0, 0.0}
185 };
186 
187  /*Neal's notation of geo_sds*/
188 
189  /* NOTE: only the name, src_name and type are currently being used
190  * in the code.
191  */
192 /* Enclosed the rows in the initializer of array GEO_SDS with braces for
193  ANSI-C compliance (Razor Issue 173).
194 */
196 /* name src_name type units
197  valid_range[2] FillValue line_numbers frame_numbers scale_factor */
198  {"Latitude" , "Latitude" , DFNT_FLOAT32, "degrees" ,
199  {-90.,90.} , -999. , "3,8" , "3,8,13,...", 1.f} ,
200  {"Longitude" , "Longitude" , DFNT_FLOAT32, "degrees" ,
201  {-180., 180.} , -999. , "3,8" , "3,8,13,...", 1.f} ,
202  {"Height" , "Height" , DFNT_INT16 , "meters" ,
203  {-400,10000} , -32767 , "3,8" , "3,8,13,...", 1.f} ,
204  {"SensorZenith" , "SensorZenith" , DFNT_INT16 , "degrees" ,
205  {0,18000} , -32767 , "3,8" , "3,8,13,...", 0.01f},
206  {"SensorAzimuth", "SensorAzimuth", DFNT_INT16 , "degrees" ,
207  {-18000,18000} , -32767 , "3,8" , "3,8,13,...", 0.01f},
208  {"Range" , "Range" , DFNT_UINT16 , "meters" ,
209  {27000.,65535.}, 0 , "3,8" , "3,8,13,...", 25.f} ,
210  {"SolarZenith" , "SolarZenith" , DFNT_INT16 , "degrees" ,
211  {0,18000} , -32767 , "3,8" , "3,8,13,...", 0.01f},
212  {"SolarAzimuth" , "SolarAzimuth" , DFNT_INT16 , "degrees" ,
213  {-18000,18000} , -32767 , "3,8" , "3,8,13,...", 0.01f},
214  {"gflags" , "gflags" , DFNT_UINT8 , "" ,
215  {0.,0.} , 255 , "" , "" , 1.}
216 };
217 
218 extern int16 RFLAG;
219 extern int16 RSCL_FLAG;
220 
221 /******************************** FUNCTIONS *********************************/
222 
223 PGSt_SMF_status L1B_Setup (lookup_tables_t *tables,
224  L1A_granule_t *L1A_Gran,
225  L1B_granule_t *L1B_Gran,
226  L1A_Scan_t *L1A_Scan,
227  L1B_Scan_t *L1B_Scan,
228  QA_Data_t *QA,
229  L1B_Scan_Metadata_t *L1B_Scan_Meta,
230  boolean skip_night_hi_res)
231 /*
232 !C************************************************************************
233 !Description:
234  This routine performs a variety of functions in preparation for EV
235  calibration: (1) opens SDS access to each of the four L1A EV SDSs,
236  (2) calculates radiance and reflectance coefficients, populating the
237  "momos_t" structure, (3) sets the radiance, reflectance and emissive
238  scales and offsets for the L1B data products, (4) creates HDFEOS Swaths
239  and data fields for each L1B output file, (5) creates band-subsetting
240  SDSs, (6) opens SDS access for each of the EV SDSs in the L1B EV files
241  and create attributes for all, (7) reads subsampled SDSs from geolocation
242  file and write those data and their attributes into the 1km L1B file,
243  (8) assigns nadir-frame lattitude and longitude to members of L1B_Scan_Meta
244  to be written later in Write_L1B_ScanMeta, (9) assigns members of the
245  L1B_Scan_Meta to be written to the L1B EV files later in
246  Write_L1B_ScanMeta, and (10) initializes the QA values of total number of
247  pixels, number of valid pixels, number of saturated pixels, number of
248  missing pixels and pixels representing negative values below noise.
249 
250 !Input Parameters:
251  lookup_tables_t *tables
252  L1A_granule_t *L1A_Gran
253  boolean skip_night_hi_res True if and only if all scans are
254  night mode scans and writing of 250m
255  and 500m night mode granules has been
256  turned off
257 
258 !Output Parameters:
259  L1B_granule_t *L1B_Gran
260  L1A_Scan_t *L1A_Scan
261  L1B_Scan_t *L1B_Scan
262  QA_Data_t *QA
263 
264 !Revision History:
265  (continue at top of the file)
266 
267  Revision 02.15 March 26, 2003 Razor Issue #191
268  Added assignment of SWIR OOB correction band from LUT value
269  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
270 
271  Revision 02.14 March 19, 2002 Razor Issue #182
272  Added Call to Calculate_B26_B5_Correction
273  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
274 
275  Revision 02.13 November 15, 2001 Razor Issue #169
276  Changed call to Open_W_L1B_Granule to include boolean skip_night_hi_res
277  Added boolean skip_night_hi_res to input parameters to L1B_Setup
278  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
279 
280  Revision 02.12 Feb 10, 1999
281  Moved call to function Write_L1B_ScanMeta to L1B (main).
282  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
283 
284  Revision 02.11 Feb. 1999
285  The following L1A_Gran members are now read in Read_L1A_OBCEng:
286  Number of Day mode scans, EV start time and Scan Type. This eliminates
287  the need for Get_EV_Start_Time and Read_L1A_ScanMeta.
288  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
289 
290  Revision 02.10 April 1998
291  Added scan_meta_cal().
292  Zhenying Gu(zgu@gscmail.gsfc.nasa.gov)
293 
294  Revision 02.10 April 1998
295  Added the Get_EV_Start_Time() and Calculate_MOMOs() calls.
296  David Catozzi (cato@ltpmail.gsfc.nasa.gov)
297 
298  Revision 02.00 March 1997
299  Exluded everything associated with LookupTables & PreprocessData;
300  changed processing metadata one scan a time to all scans at once.
301  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
302 
303  Revision 01.01 1996/04/05
304  Updated to match Version 1 Design Document
305  John Hannon(hannon@highwire.gsfc.nasa.gov)
306  Joan Baden (baden@highwire.gsfc.nasa.gov)
307 
308  Revision 01.00 1993
309  Initial development
310  Geir Kvaran(geir@highwire.gsfc.nasa.gov)
311 
312 !Team-unique Header:
313 
314 !References and Credits:
315  This software is developed by the MODIS Characterization Support
316  Team (MCST)for the National Aeronautics and Space Administration,
317  Goddard Space Flight Center, under contract NAS5-32373.
318 
319  HDF portions developed at the National Center for Supercomputing
320  Applications at the University of Illinois at Urbana-Champaign.
321 
322 !Design Notes:
323 
324 !END********************************************************************
325 */
326 {
327  PGSt_SMF_status returnStatus = MODIS_S_OK;
328  char *location = "L1B_Setup"; /* L1B location */
329  SWIR_correction_tables_t *swir_tables =
330  &tables->refl.SWIR_correction_tables;
331 
332  /*
333  * Assign L1B_Scan->band_X based on reflective LUT value
334  * Assignment is as night band index for use with L1A data.
335  */
336  /* MODIS_BAND20_INDEX = 21 NUM_BANDS = 38 MODIS_BAND26_INDEX = 27 */
337 
338 
339  if ((swir_tables->SWIR_corr_sending_band >= MODIS_BAND20_INDEX - 1 &&
340  swir_tables->SWIR_corr_sending_band < MODIS_BAND26_INDEX - 1) ||
341  (swir_tables->SWIR_corr_sending_band > MODIS_BAND26_INDEX - 1 &&
342  swir_tables->SWIR_corr_sending_band < NUM_BANDS - 1))
343  L1B_Scan->band_X = swir_tables->SWIR_corr_sending_band - MODIS_BAND20_INDEX + 1;
344  else
345  {
346  returnStatus = MODIS_F_OUT_OF_RANGE;
347  L1BErrorMsg(location, returnStatus,
348  "Band to use for SWIR OOB Correction is out of range.",
350  "This is most likely due to an invalid LUT file.", True);
351  return returnStatus;
352  }
353 
354  /*
355  * Assign L1B_Gran->num_scans & L1B_Gran->num_day_scans
356  */
357  L1B_Gran->num_scans = L1A_Gran->num_scans;
358  L1B_Gran->num_day_scans = L1A_Gran->num_day_scans;
359 
360 
361  returnStatus = Open_L1A_EV_SDS (L1A_Gran, L1A_Scan);
362  if (returnStatus != MODIS_S_OK)
363  SMF_ERROR(returnStatus,"Open_L1A_EV_SDS() in L1B_Setup");
364 
365  returnStatus = Calculate_Earth_Sun_Distance(L1A_Gran,
366  &L1B_Gran->Earth_Sun_Dist);
367  if (returnStatus != MODIS_S_OK)
368  L1BErrorMsg(location, returnStatus, NULL,
369  "Calculate_Earth_Sun_Distance",
370  0, NULL, True);
371 
372  returnStatus = Calculate_RSB_Cal_Coeff(tables,
373  L1B_Gran->Earth_Sun_Dist,
374  &L1B_Gran->RSB_Cal_Coeff);
375  if (returnStatus != MODIS_S_OK)
376  SMF_ERROR(returnStatus,"Calculate_RSB_Cal_Coeff() in L1B_Setup");
377 
378  returnStatus = Init_L1B_ScaleOffset(&L1B_Gran->SO,
379  &L1B_Gran->RSB_Cal_Coeff,
380  L1B_Gran->Earth_Sun_Dist, tables);
381  if (returnStatus != MODIS_S_OK)
382  SMF_ERROR(returnStatus,"Init_L1B_ScaleOffset() in L1B_Setup");
383 
384  /*
385  * Scale the Band 5 to Band 26 crosstalk correction coefficients by the
386  * ratio of the Band 5 to Band 26 scales and store the result in the
387  * L1B_Gran->RSB_Cal_Coeff structure.
388  */
389 
390  returnStatus = Calculate_B26_B5_Correction
391  (tables->refl.B26_B5_Corr,
392  L1B_Gran->b26_fr_b5_scaled_corr,
393  &L1B_Gran->SO);
394 
395  if (returnStatus != MODIS_S_OK)
396  SMF_ERROR (returnStatus,
397  "Calculate_B26_B5_Correction() in L1B_Setup");
398 
399  returnStatus = Open_W_L1B_Granule (tables, L1B_Gran, L1B_Scan,
400  skip_night_hi_res);
401  if (returnStatus != MODIS_S_OK)
402  SMF_ERROR(returnStatus, "Open_W_L1B_Granule() in L1B_Setup");
403 
404  returnStatus = Copy_Geo_SDS (L1B_Gran, skip_night_hi_res);
405  if (returnStatus != MODIS_S_OK)
406  SMF_ERROR(returnStatus, "Copy_Geo_SDS() in L1B_Setup");
407 
408  returnStatus = Scan_Meta_Cal(tables,
409  L1A_Gran, L1B_Gran, L1B_Scan_Meta, QA);
410  if (returnStatus != MODIS_S_OK)
411  SMF_ERROR(returnStatus, "Scan_Meta_Cal() in L1B_Setup");
412 
413  returnStatus = Calculate_DCR_Change(L1A_Gran, QA, L1B_Scan_Meta);
414  if(returnStatus != MODIS_S_OK)
415  SMF_ERROR(returnStatus, "Calculate_DCR_Change() in Gran_Meta_Cal()");
416 
417  returnStatus = Init_QA_Parameters (L1A_Gran, L1B_Gran, QA);
418  if (returnStatus != MODIS_S_OK)
419  SMF_ERROR(returnStatus, "Init_QA_Parameters() in L1B_Setup");
420 
421  return(MODIS_S_OK);
422 }
423 
424 PGSt_SMF_status Open_L1A_EV_SDS (L1A_granule_t *L1A_Gran,
425  L1A_Scan_t *L1A_Scan)
426 /*
427 !C****************************************************************************
428 !Description: Create SDS access to each of the four L1A EV SDSs. The sds_ids
429  are stored in L1A_Scan. These SDS accesses are not terminated
430  until after all processing has been complete.
431 
432 !Input Parameters:
433  L1A_Gran (->sd_id) SD file access ID -- already opened.
434 
435 !Output Parameters:
436  L1A_Scan (->sds_id[R]) SDS access IDs for each EV SDS in L1A file.
437 
438 !Revision History:
439  (continue at top of the file)
440 
441  Revision 02.10 March 1997
442  Modified to match the change in L1A_Scan_t.
443  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
444 
445  Revision 02.00 1996/07/02
446  Version 2, initial redesign
447  Neal Devine(neal.devine@gsfc.nasa.gov)
448 
449  Revision 01.01 1996/04/05
450  Update to match Version 1 Design Document
451  John Hannon(hannon@highwire.gsfc.nasa.gov)
452  Neal Devine(neal.devine@gsfc.nasa.gov)
453  Joan Baden (baden@highwire.gsfc.nasa.gov)
454 
455  Revision 01.00 1993
456  Initial development
457  Geir E. Kvaran(geir@highwire.gsfc.nasa.gov)
458 
459 !Team-unique Header:
460  This software is developed by the MODIS Characterization Support
461  Team (MCST)for the National Aeronautics and Space Administration,
462  Goddard Space Flight Center, under contract NAS5-32373.
463 
464 !References and Credits:
465  HDF portions developed at the National Center for Supercomputing
466  Applications at the University of Illinois at Urbana-Champaign.
467 
468 !Design Notes:
469 
470 !END**************************************************************************
471 */
472 {
473  PGSt_SMF_status returnStatus = MODIS_S_OK;
474  char *location = "Open_L1A_EV_SDS";
475  int16 R = 0;
476  int32 sds_index = 0;
477  char errmsg[256];
478 
479  for (R = 0; R < NUM_L1A_RESOLUTIONS; R++)
480  {
481  if ((RFLAG & (1 << R)) != 0) continue;
482 
483  sds_index = SDnametoindex (L1A_Gran->sd_id, L1A_EV_SDS_NAME[R]);
484  if (sds_index == FAIL)
485  {
486  sprintf(errmsg, "Could not get SDS index of \"%s\".",
487  L1A_EV_SDS_NAME[R]);
488  returnStatus = MODIS_F_READ_ERROR;
489  L1BErrorMsg(location, returnStatus, errmsg,
490  "SDnametoindex", FIRST_L1A_GRANULE, NULL, True);
491  return returnStatus;
492  }
493 
494  L1A_Scan->sds_id[R] = SDselect (L1A_Gran->sd_id, sds_index);
495  if (L1A_Scan->sds_id[R] == FAIL)
496  {
497  sprintf(errmsg, "Could not get SDS ID for \"%s\".",
498  L1A_EV_SDS_NAME[R]);
499  returnStatus = MODIS_F_HDF_ERROR;
500  L1BErrorMsg(location, returnStatus, errmsg,
501  "SDselect", FIRST_L1A_GRANULE, NULL, True);
502  return returnStatus;
503  }
504  }
505 
506  return(MODIS_S_OK);
507 }
508 
509 PGSt_SMF_status Calculate_Earth_Sun_Distance( L1A_granule_t *L1A_Gran,
510  float32 *Earth_Sun_Dist)
511 /*
512 !C****************************************************************************
513 !Description: This function calculates the Earth Sun distance based on the TAI
514  time.
515 
516 !Input Parameters:
517  L1A_granule_t *L1A_Gran contains number of scans in middle
518  L1A granule and EV start time.
519 
520 !Output Parameters:
521  float32 * Earth_Sun_Dist to store Earth Sun distance
522 
523 !Revision History:
524  (continue at top of the file)
525 
526  Revision 1.22 2005/02/16 21:29:39 ltan
527  Code changes to correct the HDFEOS dimension mapping offset for QKM data and
528  1KM geolocation from 0 to 1.
529 
530  Revision 1.21 2005/01/18 19:34:45 ltan
531  Added new file attributes prefixed with HDFEOS_FractionalOffset
532 
533 
534  Revision 1.02 June 3, 2003 Razor Issue #193
535  The calculation of the Earth-Sun distance was amended after it was
536  discovered that the memo on which it is based has a typographical
537  error; the "+" in front of the second order term should be a "-".
538  Comments were also clarified.
539  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
540 
541  Revision 01.01 November 7, 2001
542  Change use of PI to PGS_PI (Razor issue #168); clean up some spelling
543  and grammar
544  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
545 
546  Revision 01.00 Nov. 04, 1999
547  Initial development.
548  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
549 
550 !Team-unique Header:
551  This software is developed by the MODIS Characterization Support
552  Team (MCST)for the National Aeronautics and Space Administration,
553  Goddard Space Flight Center, under contract NAS5-32373.
554 
555 !References and Credits:
556  HDF portions developed at the National Center for Supercomputing
557  Applications at the University of Illinois at Urbana-Champaign.
558 
559 !Design Notes:
560 
561 !END**************************************************************************
562 */
563 {
564  PGSt_SMF_status returnStatus = MODIS_S_OK;
565  char *location = "Calculate_Earth_Sun_Distance";
566  float64 TAItime;
567  float64 EMA;
568  int32 middle_scan;
569 
570  if (L1A_Gran == NULL || Earth_Sun_Dist == NULL)
572  "Input parameter is NULL pointer.", NULL, 0, NULL, True);
573 
574  /*
575  * The formula calculating earth sun distance uses one TAI time for
576  * the granule. The memo referred to below does not specify with time
577  * to use. Logically, it would be near the middle of the granule.
578  */
579 
580 
581  middle_scan = L1A_Gran->num_scans/2;
582  TAItime = L1A_Gran->EVStartTime_TAIsecond[middle_scan];
583 
584 /*
585  * Calculate EMA using the expression for m appropriate for use with secTAI93
586  * (TAItime) input. This equation appears on the last page of the memo, "The
587  * Earth-Sun Distance Correction for the MODIS Reflective Product", M0612.
588  * The additional modulo 360 equation in this reference can be ignored as it
589  * will not affect the answer.
590  */
591 
592  EMA = -2.15802 + 0.0000114074107 * TAItime -
593  1.56645046e-23 * TAItime * TAItime;
594 
595 /*
596  * Calculate Earth-Sun distance using equation (2) with e = 0.167075 from the
597  * memo "The Earth-Sun Distance Correction for the MODIS Reflective Product",
598  * M0612.
599  */
600 
601  *Earth_Sun_Dist = 1.0001396 - 0.0167068 * cos((double)(EMA * PGS_PI/180.0))
602  - 0.0001396 * cos((double)(2 * EMA * PGS_PI/180.0));
603 
604  return returnStatus;
605 }
606 
608  float32 E_S_Dist,
609  RSB_Cal_Coeff_t *RSB_Cal_Coeff)
610 /*
611 !C****************************************************************************
612 !Description:
613  This function calculates the reflective calibration coefficient m1_des_sq,
614  which is the values of LUT m1 multiplied by the square of the Earth-Sun
615  distance for the current granule, and it's maximum values. It also calculates
616  minimum values of R*, from the time-dependent LUT quantities. The calculated
617  values are stored in the RSB_Cal_Coeff_t structure for use in Reflective_Cal
618  and Init_L1B_ScaleOffset.
619 
620 !Input Parameters:
621  lookup_tables_t * tables Contains structure members for m1 and R*
622  time-dependent LUTs and dead detector list.
623  float32 E_S_Dist earth-sun distance
624 
625 !Output Parameters:
626  RSB_Cal_Coeff_t * RSB_Cal_Coeff Contains the structure members to be filled
627  in this array: m1_des_sq, m1_des_sq_max,
628  R_star, R_star_min.
629 
630 !Revision History:
631  (continue at top of the file)
632 
633  Revision 01.01 Nov, 1999
634  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
635 
636  Revision 01.00 May, 1999
637  See SDF, Initial development.
638  Zhenying Gu (zgu@mcst.gsfc.nasa.gov) and Jim Rogers (rogers@mcst.gsfc.nasa.gov)
639 
640 !Team-unique Header:
641  This software is developed by the MODIS Characterization Support
642  Team (MCST)for the National Aeronautics and Space Administration,
643  Goddard Space Flight Center, under contract NAS5-32373.
644 
645 !References and Credits:
646  HDF portions developed at the National Center for Supercomputing
647  Applications at the University of Illinois at Urbana-Champaign.
648 
649 !Design Notes:
650 
651 !END**************************************************************************
652 */
653 
654 {
655  PGSt_SMF_status returnStatus = MODIS_S_OK;
656  int16 band, det, sample, mirr_side;
657  int16 det_490; /* index for all detectors */
658  int16 num_detectors[NUM_REFLECTIVE_BANDS] =
659  {40, 40, 20, 20, 20, 20, 20, 10,
660  10, 10, 10, 10, 10, 10, 10, 10,
661  10, 10, 10, 10, 10, 10};
662 
663  int16 num_subsamps [NUM_REFLECTIVE_BANDS] =
664  {4, 4, 2, 2, 2, 2, 2, 1, 1, 1, 1,
665  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
666 
667  int32 i, n;
668  float32 *work;
669  work = malloc(MAX_DETECTORS_PER_BAND *
672  sizeof(float32));
673  float32 m1;
674 
675  /* Calculate m1 and m1 max */
676 
677  det_490 = 0;
678  for (band = 0; band < NUM_REFLECTIVE_BANDS; band++ )
679  {
680  n = 0;
681 
682  /*
683  * (NUM_REFLECTIVE_DETECTORS - 10) is the index of the first
684  * detector in band 20. MODIS_BAND26_INDEX_AT_RES equals the
685  * difference of band index between band 26 and band 20, which
686  * is 6. Every band has 10 detectors for 1km bands.
687  */
688 
689  if (band == NUM_REFLECTIVE_BANDS - 1) /* band 26 */
690  det_490 = (NUM_REFLECTIVE_DETECTORS - 10) +
692 
693  for ( det = 0; det < num_detectors[band]; det++, det_490++ )
694  {
695  for ( sample = 0; sample < num_subsamps[band]; sample++ )
696  {
697  for ( mirr_side = 0; mirr_side < NUM_MIRROR_SIDES; mirr_side++ )
698  {
699  m1 = tables->refl.m1[band][det][sample][mirr_side];
700  RSB_Cal_Coeff->m1_des_sq[band][det][sample][mirr_side] =
701  m1 * E_S_Dist * E_S_Dist;
702 
703  if (tables->QA.common_QA_tables.dead_detector[det_490] != 1)
704  {
705  work[n] = RSB_Cal_Coeff->m1_des_sq[band][det][sample][mirr_side];
706  n++;
707  }
708  } /* end loop through mirr_side */
709  } /* end loop through sample */
710  } /* end loop through det */
711 
712 
713  RSB_Cal_Coeff->m1_des_sq_max[band] = work[0];
714  for (i = 0; i < n; i++)
715  if (RSB_Cal_Coeff->m1_des_sq_max[band] < work[i])
716  RSB_Cal_Coeff->m1_des_sq_max[band] = work[i];
717 
718  if (RSB_Cal_Coeff->m1_des_sq_max[band] == 0 || n == 0)
720  "invalid m1 maximum value in Calculate_RSB_Cal_Coeff()");
721  }/* end loop through band */
722 
723  free(work);
724 
725  return (returnStatus);
726 }
727 
729  RSB_Cal_Coeff_t *RSB_Cal_Coeff,
730  float E_S_Dist,
732 /*
733 !C**********************************************************************
734 !Description: This routine sets the radiance, reflectance and emissive scales
735  and offsets for the L1B data products.
736 
737 !Input Parameters:
738  lookup_tables_t *tables contains L_Min, L_Max, dn_star_Min
739  dn_star_Max
740  RSB_Cal_Coeff_t *RSB_Cal_Coeff contains m1_des_sq_max and
741  R_star_min
742  float E_S_Dist Earth-sun distance in AU
743 
744 !Output Parameters:
745  L1B_ScaleOffset_t *SO contains all scales and offsets
746  for reflectance, radiance and count
747 
748 !Revision History:
749  (continue at top of the file)
750 
751  Revision 02.13 August 12, 1999
752  Used L_Max, L_Min Luts
753  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
754 
755  Revision 02.12 May 18, 1999
756  Changed to match RSB calibration coefficient algorithm change.
757  Jim Rogers (rogers@mcst.gsfc.nasa.gov) and Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
758 
759  Revision 02.11 Feb 16, 1999
760  Removed outdated and unused variable DN_Star_Max_Band1_7.
761  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
762 
763  Revision 02.10 Apr 6, 1998
764  Commented out the Reflective Scale and Offset expressions,
765  awaiting the V2.1 algorithm.
766  David Catozzi (cato@ltpmail.gsfc.nasa.gov)
767 
768  Revision 02.00 Dec. 1996.
769  Modified Scale and Offset expressions according to V2 spec.
770  Zhidong Hao (hao@acrobat.gsfc.nasa.gov)
771 
772  Revision 01.01 1996/04/05
773  Updated to match Version 1 Design Document.
774  Neal Devine(neal.devine@gsfc.nasa.gov)
775  John Hannon(hannon@highwire.gsfc.nasa.gov)
776 
777  Revision 01.00 1995/12/05
778  Initial development
779  Shi_Yue Qiu(syqiu@ltpmail.gsfc.nasa.gov)
780 
781 !Team-unique Header:
782 
783 !References and Credits:
784  This software is developed by the MODIS Characterization Support
785  Team (MCST)for the National Aeronautics and Space Administration,
786  Goddard Space Flight Center, under contract NAS5-32373.
787 
788  HDF portions developed at the National Center for Supercomputing
789  Applications at the University of Illinois at Urbana-Champaign.
790 
791 !Design Notes:
792  Reflectance does not contain the Sun_Adj factor which varies from slightly
793  less than 1 to 1.03something. See comment below.
794 
795  Replaced `SIL_t *E_Sun' by `refl_tables_t *refl_tables' and
796  removed Sun_Adj as an input parameter, as it is not needed here.
797  --- zh 11/21/96
798 
799 !END********************************************************************
800 */
801 {
802  int16 B = 0;
803  int16 B_emiss = 0;
804  float32 E_sun_over_pi_B[NUM_REFLECTIVE_BANDS];
805  int16 D, D_330;
806 
807  /*set dn_star_Max, dn_star_Min*/
808  for (B = 0; B < NUM_REFLECTIVE_BANDS; B++)
809  {
810  SO->dn_star_Max[B] = tables->refl.dn_star_Max[B];
811  SO->dn_star_Min[B] = tables->refl.dn_star_Min[B];
812  if (SO->dn_star_Max[B] <= SO->dn_star_Min[B])
814  "LUT dn_star_Max <= dn_star_Min, Init_L1B_ScaleOffset");
815  }
816 
817  /*set Emiss radiance scale/offset*/
818  B_emiss = 0;
819  for (B = 0; B < L1A_BANDS_AT_RES[INDEX_1000M_EMISS]; B++)
820  {
821  if (B == MODIS_BAND26_INDEX_AT_RES)
822  continue;
823  SO->rad_scale_Emiss[B_emiss] =
824  (tables->emiss.L_Max[B_emiss] -
825  tables->emiss.L_Min[B_emiss]) / DN15_SAT;
826  SO->rad_offset_Emiss[B_emiss] =
827  -DN15_SAT * tables->emiss.L_Min[B_emiss]/
828  (tables->emiss.L_Max[B_emiss] -
829  tables->emiss.L_Min[B_emiss]);
830  B_emiss++;
831  }
832 
833  /*
834  * Calculate the mean E_sun_over_pi for each band.
835  */
836 
837  D_330 = 0;
838  for (B = 0; B < NUM_250M_BANDS; B++)
839  {
840  E_sun_over_pi_B[B] = 0;
841  for (D = 0; D < DETECTORS_PER_250M_BAND; D++, D_330++)
842  E_sun_over_pi_B[B] += tables->refl.E_sun_over_pi[D_330];
843  E_sun_over_pi_B[B] /= (float32) DETECTORS_PER_250M_BAND;
844  }
845  for ( ; B < (NUM_250M_BANDS+NUM_500M_BANDS); B++)
846  {
847  E_sun_over_pi_B[B] = 0;
848  for (D = 0; D < DETECTORS_PER_500M_BAND; D++, D_330++)
849  E_sun_over_pi_B[B] += tables->refl.E_sun_over_pi[D_330];
850  E_sun_over_pi_B[B] /= (float32) DETECTORS_PER_500M_BAND;
851  }
852  for ( ; B < NUM_REFLECTIVE_BANDS; B++)
853  {
854  E_sun_over_pi_B[B] = 0;
855  for (D = 0; D < DETECTORS_PER_1KM_BAND; D++, D_330++)
856  E_sun_over_pi_B[B] += tables->refl.E_sun_over_pi[D_330];
857  E_sun_over_pi_B[B] /= (float32) DETECTORS_PER_1KM_BAND;
858  }
859 
860  /*set RefSB radiance, reflectance and counts scale/offset*/
861 
862  for (B = 0; B < NUM_REFLECTIVE_BANDS; B++)
863  {
864  SO->counts_scale_RefSB[B] =
865  (SO->dn_star_Max[B] - SO->dn_star_Min[B])/DN15_SAT;
866  SO->counts_offset_RefSB[B] =
867  -DN15_SAT * SO->dn_star_Min[B] /
868  (SO->dn_star_Max[B] - SO->dn_star_Min[B]);
869 
870  SO->refl_scale_RefSB[B] =
871  RSB_Cal_Coeff->m1_des_sq_max[B] * SO->counts_scale_RefSB[B];
872  SO->refl_offset_RefSB[B] =
873  SO->counts_offset_RefSB[B];
874 
875  SO->rad_scale_RefSB[B] =
876  (E_sun_over_pi_B[B] / (E_S_Dist * E_S_Dist))
877  * SO->refl_scale_RefSB[B];
878  SO->rad_offset_RefSB[B] =
879  SO->counts_offset_RefSB[B];
880  }
881 
882  return(MODIS_S_OK);
883 }
884 
885 PGSt_SMF_status Open_W_L1B_Granule
887  L1B_granule_t *L1B_Gran,
888  L1B_Scan_t *L1B_Scan,
889  boolean skip_night_hi_res)
890 /*
891 !C**********************************************************************
892 !Description: Create HDFEOS Swaths and data fields for each L1B output file.
893  Also get SD & V HDF interface ids. The band-subsetting data
894  fields (one-dimensional arrays) are implemented as Vdata while
895  the other fields are implemented as SDSs. Separate band-
896  subsetting SDSs are also created. Open SDS access for each of
897  the EV SDSs in the L1B EV files and create attributes for all.
898  SDS access will remain open until after all scan-by-scan
899  processing is complete.
900 
901 !Input Parameters:
902  lookup_tables_t *tables
903  L1B_granule_t *L1B_Gran
904  L1B_Scan_t *L1B_Scan
905  boolean skip_night_hi_res True if and only if all scans are
906  night mode scans and writing of 250m
907  and 500m night mode granules has been
908  turned off
909 
910 !Output Parameters:
911  L1B_Gran (->sw_f_id[]) Swath file ID for each of the L1B EV files.
912  L1B_Scan_t *L1B_Scan
913 
914 !Revision History:
915  (continue at top of the file)
916 
917  Revision 02.01, November 14, 2001, Razor Issue #169
918  Added input parameter skip_night_hi_res and changed logic so that
919  250m and 500m data are not written when granule has no day mode
920  scans and runtime parameter Write_Night_Mode_HiRes_Data is False.
921  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
922 
923  Revision 02.01, Dec 5, 2000, Razor issue 141.
924  Added "tables" to argument list, add to arg list of "Set_L1B_EV_SDS_Attrs"
925  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
926 
927  Revision 02.00 Feb 16, 1999
928  Split Write_Band_Subsetting_SDS and its subordinate function
929  Write_Subsetting_SDS into two functions: Set_L1B_EV_SDS_Attrs and
930  Create_Band_Subsetting_SDS for clarity.
931  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
932 
933  Revision 02.00 March 1997
934  Modified to match version 2 design.
935  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
936 
937  Revision 01.01 1996/04/05
938  Update to match Version 1 Design Document
939  John Hannon(hannon@highwire.gsfc.nasa.gov)
940  Joan Baden (baden@highwire.gsfc.nasa.gov)
941 
942  Revision 01.00 1993
943  Initial development
944  Geir E. Kvaran(geir@highwire.gsfc.nasa.gov)
945 
946 !Team-unique Header:
947  This software is developed by the MODIS Characterization Support
948  Team (MCST)for the National Aeronautics and Space Administration,
949  Goddard Space Flight Center, under contract NAS5-32373.
950 
951 !References and Credits:
952  HDF portions developed at the National Center for Supercomputing
953  Applications at the University of Illinois at Urbana-Champaign.
954 
955 !Design Notes:
956  1. The PGS_PC logical reference IDs are defined in Fnames.h. These are
957  consecutive integers for the EV files and are indexed as such below.
958 
959 !END********************************************************************
960 */
961 {
962  PGSt_SMF_status returnStatus = MODIS_S_OK;
963  PGSt_PC_Logical logical_id = 0;
964  PGSt_integer version = 1;
965  char fname[PGSd_PC_FILE_PATH_MAX];
966  int16 f = 0;
967  char *location = "Open_W_L1B_Granule";
968  int16 start_output_res = INDEX_L1B_250m;
969 
970  /*
971  * If we are in night mode and we do not wish to write 250m and 500m data
972  * sets, start with the 1KM output data sets.
973  */
974 
975  if (skip_night_hi_res == True)
976  {
977  start_output_res = INDEX_L1B_1km;
978  logical_id = L1B_EV_1000M_FILE;
979  }
980  else
981  {
982  start_output_res = INDEX_L1B_250m;
983  logical_id = L1B_EV_250M_FILE;
984  }
985 
986  for (f = start_output_res; f < NUM_L1B_EV_FILES; f++, logical_id++)
987  {
988  version = 1;
989 
990  if (PGS_PC_GetReference(logical_id, &version, fname) != PGS_S_SUCCESS)
991  {
992  returnStatus = MODIS_F_FILE_NOT_FOUND;
993  L1BErrorMsg(location, returnStatus,
994  "Could not retrieve file name from PCF.",
995  "PGS_PC_GetReference", logical_id, NULL, True);
996  return returnStatus;
997  }
998 
999  if ((L1B_Gran->sw_f_id[f] = SWopen(fname, DFACC_CREATE)) == FAIL)
1000  {
1001  returnStatus = MODIS_F_FILE_NOT_CREATED;
1002  L1BErrorMsg(location, returnStatus,
1003  "Could not create output granule.",
1004  "SWopen", logical_id, NULL, True);
1005  return returnStatus;
1006  }
1007  }
1008 
1009  returnStatus = Create_L1B_Swath (L1B_Gran, skip_night_hi_res);
1010  if (returnStatus != MODIS_S_OK)
1011  {
1012  L1BErrorMsg(location, returnStatus, NULL,
1013  "Create_L1B_Swath", 0, NULL, True);
1014  return returnStatus;
1015  }
1016 
1017  returnStatus = Open_L1B_EV_SDS (L1B_Gran,
1018  L1B_Scan,
1019  skip_night_hi_res);
1020  if (returnStatus != MODIS_S_OK)
1021  {
1022  L1BErrorMsg(location, returnStatus, NULL,
1023  "Open_L1B_EV_SDS", 0, NULL, True);
1024  return returnStatus;
1025  }
1026 
1027  returnStatus = Set_L1B_EV_SDS_Attrs (tables,
1028  L1B_Gran,
1029  L1B_Scan,
1030  skip_night_hi_res);
1031  if (returnStatus != MODIS_S_OK)
1032  {
1033  L1BErrorMsg(location, returnStatus, NULL,
1034  "Set_L1B_EV_SDS_Attrs", 0, NULL, True);
1035  return returnStatus;
1036  }
1037 
1038  returnStatus = Create_Band_Subsetting_SDS (L1B_Gran,
1039  skip_night_hi_res);
1040  if (returnStatus != MODIS_S_OK)
1041  {
1042  L1BErrorMsg(location, returnStatus, NULL,
1043  "Create_Band_Subsetting_SDS", 0, NULL, True);
1044  return returnStatus;
1045  }
1046 
1047  return(MODIS_S_OK);
1048 }
1049 
1050 
1051 PGSt_SMF_status Create_L1B_Swath (L1B_granule_t *L1B_Gran,
1052  boolean skip_night_hi_res)
1053 /*
1054 !C****************************************************************
1055 !Description: Create HDFEOS Swaths and data fields for each L1B output file.
1056  Also get SD & V HDF interface ids. The band-subsetting data
1057  fields (one-dimensional arrays) are implemented as Vdata while
1058  the other data fields (for EV data) are implemented as SDSs.
1059  The values for the band-subsetting fields are assigned here.
1060  For the EV data, after fixing fields here, accesses will be
1061  opened to the SDSs in another routine and used normally
1062  thereafter.
1063 
1064 !Input Parameters:
1065  L1B_Gran (->sw_f_id[]) HDF-EOS swath file IDs for each EV file.
1066  boolean skip_night_hi_res True if and only if all scans are
1067  night mode scans and writing of 250m
1068  and 500m night mode granules has been
1069  turned off
1070 
1071 
1072 !Output Parameters:
1073  L1B_Gran (->v_id[]) Vdata interface IDs for each EV file.
1074  L1B_Gran (->sd_id[]) SD interface IDs for each EV file.
1075 
1076 !Revision History:
1077  (continue at top of the file)
1078  Revision 02.12, January 12, 2005 (Razor Issue #202)
1079  Added new file attribute prefixed with HDFEOS_FractionalOffset for every
1080  dimension of the swath in every MODIS product file.
1081  Liqin Tan SAIC/GSO (ltan@saicmodis.com)
1082 
1083  Revision 02.11 November 15, 2001 Razor Issue #169
1084  Added boolean skip_night_hi_res to input parameters and altered logic so that
1085  if skip_night_hi_res is True, output data sets for 250m and 500m resolution
1086  data are not created.
1087  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
1088 
1089  Revision 02.10 May 13, 1999
1090  Added band 26 section
1091  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1092 
1093  Revision 02.01 Feb 10, 1999
1094  In defining the data fields for band subsetting, changed to use the global
1095  variables Band_subsetting_names and L1B_EV_DIM_NAME defined at the top of
1096  the file.
1097  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1098 
1099  Revision 02.00 April 1997
1100  Modified to match changes in data structures.
1101  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
1102 
1103  Revision 01.00 1997/02/21
1104  Initial development
1105  Neal Devine (neal.devine@gsfc.nasa.gov)
1106 
1107 !Team-unique Header:
1108  This software is developed by the MODIS Characterization Support
1109  Team (MCST)for the National Aeronautics and Space Administration,
1110  Goddard Space Flight Center, under contract NAS5-32373.
1111 
1112 !References and Credits:
1113  HDF portions developed at the National Center for Supercomputing
1114  Applications at the University of Illinois at Urbana-Champaign.
1115 
1116 !Design Notes:
1117  Attributes not yet implemented.
1118  The opening of target SDS's is lengthy enough to warrant a separate sub
1119  function.
1120 
1121 !END********************************************************************
1122 */
1123 {
1124  PGSt_SMF_status returnStatus;
1125  char *location = "Create_L1B_Swath";
1126  int16 file_index = 0; /*file index*/
1127  int16 R = 0; /*L1A resolution index*/
1128  int16 isds = 0; /*sds_index*/
1129  int32 track_dim = 0;
1130  int32 frame_dim = 0;
1131  int16 BG_index = 0; /*Band_Group_index*/
1132  int16 num_BGs = 0; /*num_band_groups*/
1133  int32 sw_id[NUM_L1B_EV_FILES] = {0, 0, 0};
1134  intn hdf_return = 0;
1135  int32 evfile_luns[NUM_L1B_EV_FILES] = {
1139  };
1140  int16 start_output_res = INDEX_L1B_250m;
1141 #define MAX_ATTR_NAME_SIZE2 72
1142  char attr_name_buffer[MAX_ATTR_NAME_SIZE2];
1143 
1144 /*------------------------------------------------------------------------*/
1145 #define SW_DEF_EV_SDS(SI_name, UI_name, str) \
1146 if (SWdefdatafield(sw_id[file_index], SI_name, str, DFNT_UINT16, \
1147  HDFE_NOMERGE) == FAIL) \
1148  { \
1149  returnStatus = MODIS_F_HDF_ERROR; \
1150  L1BErrorMsg(location, returnStatus, SI_name, \
1151  "SWdefdatafield", evfile_luns[file_index], NULL, True); \
1152  return returnStatus; \
1153  } \
1154 if (SWdefdatafield(sw_id[file_index], UI_name, str, DFNT_UINT8, \
1155  HDFE_NOMERGE) == FAIL) \
1156  { \
1157  returnStatus = MODIS_F_HDF_ERROR; \
1158  L1BErrorMsg(location, returnStatus, UI_name, \
1159  "SWdefdatafield", evfile_luns[file_index], NULL, True); \
1160  return returnStatus; \
1161  }
1162 /*------------------------------------------------------------------------*/
1163 #define SW_DEF_EV_Aggr_SDS(SI_name, UI_name, SU_name, str) \
1164 SW_DEF_EV_SDS(SI_name,UI_name,str); \
1165 if (SWdefdatafield(sw_id[file_index], SU_name, str, DFNT_INT8, \
1166  HDFE_NOMERGE) == FAIL) \
1167  { \
1168  returnStatus = MODIS_F_HDF_ERROR; \
1169  L1BErrorMsg(location, returnStatus, SU_name, \
1170  "SWdefdatafield", evfile_luns[file_index], NULL, True); \
1171  return returnStatus; \
1172  }
1173 /*------------------------------------------------------------------------*/
1174 
1175  /*
1176  * If we are in night mode and we do not wish to write 250m and 500m data
1177  * sets, start with the 1KM output data sets.
1178  */
1179 
1180  if (skip_night_hi_res == True)
1181  start_output_res = INDEX_L1B_1km;
1182  else
1183  start_output_res = INDEX_L1B_250m;
1184 
1185  /* create EV swaths */
1186  for (file_index = start_output_res;
1187  file_index < NUM_L1B_EV_FILES; file_index++)
1188  {
1189  /* The V2 Delivery Guide suggests to use "MOD_SWATH_"
1190  Here we use the name in the file spec, "MODIS_SWATH_"
1191  */
1192  sw_id[file_index] = SWcreate(L1B_Gran->sw_f_id[file_index],
1193  "MODIS_SWATH_Type_L1B");
1194  if (sw_id[file_index] == FAIL)
1195  {
1196  returnStatus = MODIS_F_HDF_ERROR;
1197  L1BErrorMsg(location, returnStatus, NULL,
1198  "SWcreate", evfile_luns[file_index], NULL, True);
1199  return returnStatus;
1200  }
1201 
1202  /* Get equivalent HDF v_id & sd_id and assign to L1B_Gran members.
1203  */
1204  if (EHidinfo(L1B_Gran->sw_f_id[file_index],
1205  &L1B_Gran->v_id[file_index],
1206  &L1B_Gran->sd_id[file_index]) == FAIL)
1207  {
1208  returnStatus = MODIS_F_HDF_ERROR;
1209  L1BErrorMsg(location, returnStatus, NULL,
1210  "EHidinfo", evfile_luns[file_index], NULL, True);
1211  return returnStatus;
1212  }
1213 
1214  /* define band_dim and data field
1215  */
1216  num_BGs = file_index + 1;
1217  if (file_index == INDEX_L1B_1km) num_BGs++;
1218 
1219  for (BG_index = 0; BG_index < num_BGs; BG_index++)
1220  {
1221  R = BG_index; /* R = [0], [0, 1], [0, 1, 2, 3] */
1222  hdf_return = SWdefdim(sw_id[file_index], L1B_EV_DIM_NAME[R][0],
1223  (int32)L1B_BANDS_AT_RES[R]);
1224  if (hdf_return == FAIL)
1225  {
1226  returnStatus = MODIS_F_HDF_ERROR;
1227  L1BErrorMsg(location, returnStatus, L1B_EV_DIM_NAME[R][0],
1228  "SWdefdim", evfile_luns[file_index], NULL, True);
1229  return returnStatus;
1230  }
1231  }
1232 
1233  /* The Offset and Increment entries in the HDF-EOS metadata need to be
1234  set appropriately to preserve the geolocation accuracy when the data
1235  stored has a different resolution than the geolocation (see "MODIS
1236  Science Software Delivery Guide" -- 9/23/2004). Because HDF-EOS does
1237  not support fractional offset values, it doesn't properly handle
1238  sub-pixel offsets in Swath files. In order to better document the
1239  true offset, file global attributes of fractional offset are added
1240  to each files (the addition to the "integer" offset provided in the
1241  HDF-EOS metadata).
1242  */
1243  sprintf(attr_name_buffer,
1244  "HDFEOS_FractionalOffset_%s_MODIS_SWATH_Type_L1B",
1245  L1B_EV_DIM_NAME[num_BGs-1][1]);
1246 
1247  if(SDsetattr(L1B_Gran->sd_id[file_index],
1248  attr_name_buffer, DFNT_FLOAT32, 1,
1249  (VOIDP)&L1B_EV_DIM_FRAC_OFFSET[num_BGs-1][0]) == FAIL)
1250  {
1251  L1BErrorMsg(location, MODIS_F_WRITE_ERROR,
1252  "Could not write L1B EV file dimensional attribute.",
1253  "SDsetattr", evfile_luns[file_index], NULL, True);
1254  }
1255 
1256  sprintf(attr_name_buffer,
1257  "HDFEOS_FractionalOffset_%s_MODIS_SWATH_Type_L1B",
1258  L1B_EV_DIM_NAME[num_BGs-1][2]);
1259 
1260  if(SDsetattr(L1B_Gran->sd_id[file_index],
1261  attr_name_buffer, DFNT_FLOAT32, 1,
1262  (VOIDP)&L1B_EV_DIM_FRAC_OFFSET[num_BGs-1][1]) == FAIL)
1263  {
1264  L1BErrorMsg(location, MODIS_F_WRITE_ERROR,
1265  "Could not write L1B EV file dimensional attribute.",
1266  "SDsetattr", evfile_luns[file_index], NULL, True);
1267  }
1268 
1269  /* define track & frame dims
1270  */
1271  R = file_index;
1272 
1273  track_dim = DETECT_PER_BAND_AT_RES[R] * L1B_Gran->num_scans;
1274  frame_dim = BAND_RATIO_AT_RES[R] * EV_1km_FRAMES;
1275 
1276  if (SWdefdim(sw_id[file_index], L1B_EV_DIM_NAME[R][1],
1277  track_dim) == FAIL)
1278  {
1279  returnStatus = MODIS_F_HDF_ERROR;
1280  L1BErrorMsg(location, returnStatus, L1B_EV_DIM_NAME[R][1],
1281  "SWdefdim", evfile_luns[file_index], NULL, True);
1282  return returnStatus;
1283  }
1284 
1285  if (SWdefdim(sw_id[file_index], L1B_EV_DIM_NAME[R][2],
1286  frame_dim) == FAIL)
1287  {
1288  returnStatus = MODIS_F_HDF_ERROR;
1289  L1BErrorMsg(location, returnStatus, L1B_EV_DIM_NAME[R][2],
1290  "SWdefdim", evfile_luns[file_index], NULL, True);
1291  return returnStatus;
1292  }
1293 
1294  /* define geo track & frame dims, and geo/data fields, and dimmaps
1295  */
1296  if (file_index == INDEX_L1B_1km)
1297  {
1298  if (SWdefdim(sw_id[file_index], "2*nscans",
1299  (int32)(2*L1B_Gran->num_scans)) == FAIL)
1300  {
1301  returnStatus = MODIS_F_HDF_ERROR;
1302  L1BErrorMsg(location, returnStatus, "2*nscans",
1303  "SWdefdim", evfile_luns[file_index], NULL, True);
1304  return returnStatus;
1305  }
1306 
1307  if (SWdefdim(sw_id[file_index], "1KM_geo_dim",
1308  (int32)(EV_1km_FRAMES/5 + 1)) == FAIL)
1309  {
1310  returnStatus = MODIS_F_HDF_ERROR;
1311  L1BErrorMsg(location, returnStatus, "1KM_geo_dim",
1312  "SWdefdim", evfile_luns[file_index], NULL, True);
1313  return returnStatus;
1314  }
1315 
1316  if (SWdefgeofield(sw_id[file_index], "Latitude",
1317  "2*nscans,1KM_geo_dim", DFNT_FLOAT32,
1318  HDFE_NOMERGE) == FAIL)
1319  {
1320  returnStatus = MODIS_F_HDF_ERROR;
1321  L1BErrorMsg(location, returnStatus, "Latitude",
1322  "SWdefgeofield", evfile_luns[file_index],
1323  NULL, True);
1324  return returnStatus;
1325  }
1326 
1327  if (SWdefgeofield(sw_id[file_index], "Longitude",
1328  "2*nscans,1KM_geo_dim", DFNT_FLOAT32,
1329  HDFE_NOMERGE) == FAIL)
1330  {
1331  returnStatus = MODIS_F_HDF_ERROR;
1332  L1BErrorMsg(location, returnStatus, "Longitude",
1333  "SWdefgeofield", evfile_luns[file_index],
1334  NULL, True);
1335  return returnStatus;
1336  }
1337 
1340  "Band_1KM_RefSB,10*nscans,Max_EV_frames");
1341 
1344  "Band_1KM_Emissive,10*nscans,Max_EV_frames");
1345 
1349  "Band_250M,10*nscans,Max_EV_frames");
1350 
1354  "Band_500M,10*nscans,Max_EV_frames");
1355 
1356  for (isds = INDEX_HEIGHT; isds < NUM_GEO_SDS; isds++)
1357  {
1358  if (SWdefdatafield(sw_id[file_index], GEO_SDS[isds].name,
1359  "2*nscans,1KM_geo_dim",
1360  GEO_SDS[isds].type,HDFE_NOMERGE) == FAIL)
1361  {
1362  returnStatus = MODIS_F_HDF_ERROR;
1363  L1BErrorMsg(location, returnStatus, GEO_SDS[isds].name,
1364  "SWdefdatafield", evfile_luns[file_index], NULL, True);
1365  return returnStatus;
1366  }
1367  }
1368 
1369  if (SWdefdimmap(sw_id[file_index], "2*nscans", "10*nscans",
1370  GEO_OFFSET, GEO_STRIDE) == FAIL)
1371  {
1372  returnStatus = MODIS_F_HDF_ERROR;
1373  L1BErrorMsg(location, returnStatus, "2*nscans to 10*nscans",
1374  "SWdefdimmap", evfile_luns[file_index], NULL, True);
1375  return returnStatus;
1376  }
1377 
1378  if (SWdefdimmap(sw_id[file_index], "1KM_geo_dim", "Max_EV_frames",
1379  GEO_OFFSET, GEO_STRIDE) == FAIL)
1380  {
1381  returnStatus = MODIS_F_HDF_ERROR;
1382  L1BErrorMsg(location, returnStatus, "1KM_geo_dim to Max_EV_frames",
1383  "SWdefdimmap", evfile_luns[file_index], NULL, True);
1384  return returnStatus;
1385  }
1386 
1387  /* define data fields for band_subsetting
1388  */
1389 
1390  for (R = 0; R < 4; R++) {
1391  if (SWdefdatafield(sw_id[file_index],
1393  L1B_EV_DIM_NAME[R][0],
1394  DFNT_FLOAT32, HDFE_NOMERGE) == FAIL)
1395  {
1396  returnStatus = MODIS_F_HDF_ERROR;
1397  L1BErrorMsg(location, returnStatus, Band_subsetting_names[R],
1398  "SWdefdatafield", evfile_luns[file_index], NULL, True);
1399  return returnStatus;
1400  }
1401  }
1402 
1403  }
1404  else
1405  {
1406  if (SWdefdim(sw_id[file_index], "10*nscans",
1407  (int32)(10*L1B_Gran->num_scans)) == FAIL)
1408  {
1409  returnStatus = MODIS_F_HDF_ERROR;
1410  L1BErrorMsg(location, returnStatus, "10*nscans",
1411  "SWdefdim", evfile_luns[file_index], NULL, True);
1412  return returnStatus;
1413  }
1414 
1415  if (SWdefdim(sw_id[file_index], "Max_EV_frames",
1416  (int32)EV_1km_FRAMES) == FAIL)
1417  {
1418  returnStatus = MODIS_F_HDF_ERROR;
1419  L1BErrorMsg(location, returnStatus, "Max_EV_frames",
1420  "SWdefdim", evfile_luns[file_index], NULL, True);
1421  return returnStatus;
1422  }
1423 
1424  if (SWdefgeofield(sw_id[file_index], "Latitude",
1425  "10*nscans,Max_EV_frames", DFNT_FLOAT32,
1426  HDFE_NOMERGE) == FAIL)
1427  {
1428  returnStatus = MODIS_F_HDF_ERROR;
1429  L1BErrorMsg(location, returnStatus, "Latitude",
1430  "SWdefgeofield", evfile_luns[file_index], NULL, True);
1431  return returnStatus;
1432  }
1433 
1434  if (SWdefgeofield(sw_id[file_index], "Longitude",
1435  "10*nscans,Max_EV_frames", DFNT_FLOAT32,
1436  HDFE_NOMERGE) == FAIL)
1437  {
1438  returnStatus = MODIS_F_HDF_ERROR;
1439  L1BErrorMsg(location, returnStatus, "Longitude",
1440  "SWdefgeofield", evfile_luns[file_index], NULL, True);
1441  return returnStatus;
1442  }
1443 
1444  switch(file_index)
1445  {
1446  case INDEX_L1B_250m:
1449  "Band_250M,40*nscans,4*Max_EV_frames");
1450 
1451  if (SWdefdatafield(sw_id[file_index],
1454  DFNT_FLOAT32, HDFE_NOMERGE) == FAIL)
1455  {
1456  returnStatus = MODIS_F_HDF_ERROR;
1457  L1BErrorMsg(location, returnStatus,
1459  "SWdefdatafield",
1460  evfile_luns[file_index], NULL, True);
1461  return returnStatus;
1462  }
1463 
1464  break;
1465 
1466  case INDEX_L1B_500m:
1469  "Band_500M,20*nscans,2*Max_EV_frames");
1470 
1474  "Band_250M,20*nscans,2*Max_EV_frames");
1475 
1476  for (R = 0; R < 2; R++) {
1477  if (SWdefdatafield(sw_id[file_index],
1479  L1B_EV_DIM_NAME[R][0],
1480  DFNT_FLOAT32, HDFE_NOMERGE) == FAIL)
1481  {
1482  returnStatus = MODIS_F_HDF_ERROR;
1483  L1BErrorMsg(location, returnStatus,
1485  "SWdefdatafield",
1486  evfile_luns[file_index], NULL, True);
1487  return returnStatus;
1488  }
1489  }
1490 
1491  }
1492 
1493  R = file_index;
1494 
1495  if (SWdefdimmap(sw_id[file_index],
1496  "10*nscans",
1497  L1B_EV_DIM_NAME[R][1],
1499  {
1500  returnStatus = MODIS_F_HDF_ERROR;
1501  L1BErrorMsg(location, returnStatus,
1502  "L1B_EV_DIM_NAME[R][1] to 10*nscans",
1503  "SWdefdimmap",
1504  evfile_luns[file_index], NULL, True);
1505  return returnStatus;
1506  }
1507 
1508  if (SWdefdimmap(sw_id[file_index],
1509  "Max_EV_frames",
1510  L1B_EV_DIM_NAME[R][2],
1512  {
1513  returnStatus = MODIS_F_HDF_ERROR;
1514  L1BErrorMsg(location, returnStatus,
1515  "L1B_EV_DIM_NAME[R][2] to 10*nscans",
1516  "SWdefdimmap",
1517  evfile_luns[file_index], NULL, True);
1518  return returnStatus;
1519  }
1520  }
1521 
1522 /************************* Begin Band 26 Section **************************/
1523 #ifdef WRITE_BAND_26_SDS
1524  if (file_index == INDEX_L1B_1km)
1525  {
1526  /*
1527  * Create the band 26 SI and UI SDSs as part of the HDF-EOS
1528  * swath. These are 2D SDSs, using the dimensions indicated.
1529  * These are only created for the L1B 1km EV product.
1530  */
1533  "10*nscans,Max_EV_frames");
1534  }
1535 #endif /* WRITE_BAND_26_SDS */
1536 /************************** End Band 26 Section ***************************/
1537 
1538  }
1539 
1540  for (file_index = start_output_res;
1541  file_index < NUM_L1B_EV_FILES; file_index++)
1542  {
1543 
1544  /* detach from swath (this should be done prior to accessing members
1545  * to ensure that fields are set properly).
1546  */
1547 
1548  if (SWdetach(sw_id[file_index]) == FAIL)
1549  {
1550  returnStatus = MODIS_F_HDF_ERROR;
1551  L1BErrorMsg(location, returnStatus, NULL,
1552  "SWdetach", evfile_luns[file_index], NULL, True);
1553  return returnStatus;
1554  }
1555 
1556  /* Write the band-subsetting fields numerical values to file.
1557  */
1558 
1559  returnStatus = Write_Swath_Band_Number(file_index, L1B_Gran);
1560  if (returnStatus != MODIS_S_OK)
1561  {
1562  L1BErrorMsg(location, returnStatus, NULL,
1563  "Write_Swath_Band_Number",
1564  evfile_luns[file_index], NULL, True);
1565  return returnStatus;
1566  }
1567  }
1568 
1569  return(MODIS_S_OK);
1570 }
1571 
1572 PGSt_SMF_status Write_Swath_Band_Number(int32 file_index,
1573  L1B_granule_t *L1B_Gran)
1574 /*
1575 !C**********************************************************************
1576 !Description: For one EV file, this function writes the numerical values
1577  of the band-subsetting SDS data fields.
1578 
1579 !Input Parameters:
1580  file_index index of the EV file that we will write data to.
1581  L1B_Gran (->sw_f_id[]) array of swath file IDs for the EV files.
1582 
1583 !Output Parameters:
1584 
1585 !Revision History:
1586  (continue at top of the file)
1587 
1588  Revision 01.00 1998
1589  Initial development
1590  Zhenying Gu(zgu@ltpmail.gsfc.nasa.gov)
1591 
1592 !Team-unique Header:
1593  This software is developed by the MODIS Characterization Support
1594  Team (MCST)for the National Aeronautics and Space Administration,
1595  Goddard Space Flight Center, under contract NAS5-32373.
1596 
1597 !References and Credits:
1598  HDF portions developed at the National Center for Supercomputing
1599  Applications at the University of Illinois at Urbana-Champaign.
1600 
1601 !Design Notes:
1602 
1603 !END********************************************************************
1604 */
1605 {
1606  PGSt_SMF_status returnStatus = MODIS_S_OK;
1607  char *location = "Write_Swath_Band_Number";
1608 
1609  int32 swId;
1610  float32 data_250m[2] = {1, 2};
1611  float32 data_500m[5] = {3, 4, 5, 6, 7};
1612  float32 data_1km_refl[15] =
1613  {8, 9, 10, 11, 12, 13, 13.5, 14, 14.5,
1614  15, 16, 17, 18, 19, 26};
1615  float32 data_1km_emiss[16] =
1616  {20, 21, 22, 23, 24, 25, 27, 28, 29,
1617  30, 31, 32, 33, 34, 35, 36};
1618  int32 evfile_luns[NUM_L1B_EV_FILES] =
1619  {
1623  };
1624 
1625  swId = SWattach(L1B_Gran->sw_f_id[file_index], "MODIS_SWATH_Type_L1B");
1626  if (swId == FAIL)
1627  {
1628  returnStatus = MODIS_F_HDF_ERROR;
1629  L1BErrorMsg(location, returnStatus, NULL,
1630  "SWattach", evfile_luns[file_index], NULL, True);
1631  return returnStatus;
1632  }
1633 
1634  switch(file_index)
1635  {
1636  case INDEX_L1B_1km:
1637  if (SWwritefield(swId, "Band_250M", (int32*)NULL, (int32*)NULL,
1638  (int32*)NULL, (VOIDP)data_250m) == FAIL)
1639  {
1640  returnStatus = MODIS_F_WRITE_ERROR;
1641  L1BErrorMsg(location, returnStatus, "Band_250M",
1642  "SWwritefield", evfile_luns[file_index], NULL, True);
1643  return returnStatus;
1644  }
1645 
1646  if (SWwritefield(swId, "Band_500M", (int32*)NULL, (int32*)NULL,
1647  (int32*)NULL, (VOIDP)data_500m) == FAIL)
1648  {
1649  returnStatus = MODIS_F_WRITE_ERROR;
1650  L1BErrorMsg(location, returnStatus, "Band_500M",
1651  "SWwritefield", evfile_luns[file_index], NULL, True);
1652  return returnStatus;
1653  }
1654 
1655  if (SWwritefield(swId, "Band_1KM_RefSB", (int32*)NULL, (int32*)NULL,
1656  (int32*)NULL, (VOIDP)data_1km_refl)== FAIL)
1657  {
1658  returnStatus = MODIS_F_WRITE_ERROR;
1659  L1BErrorMsg(location, returnStatus, "Band_1KM_RefSB",
1660  "SWwritefield", evfile_luns[file_index], NULL, True);
1661  return returnStatus;
1662  }
1663 
1664  if (SWwritefield(swId, "Band_1KM_Emissive", (int32*)NULL, (int32*)NULL,
1665  (int32*)NULL, (VOIDP)data_1km_emiss)== FAIL)
1666  {
1667  returnStatus = MODIS_F_WRITE_ERROR;
1668  L1BErrorMsg(location, returnStatus, "Band_1KM_Emissive",
1669  "SWwritefield", evfile_luns[file_index], NULL, True);
1670  return returnStatus;
1671  }
1672  break;
1673 
1674  case INDEX_L1B_500m:
1675  if (SWwritefield(swId, "Band_250M", (int32*)NULL, (int32*)NULL,
1676  (int32*)NULL, (VOIDP)data_250m) == FAIL)
1677  {
1678  returnStatus = MODIS_F_WRITE_ERROR;
1679  L1BErrorMsg(location, returnStatus, "Band_250M",
1680  "SWwritefield", evfile_luns[file_index], NULL, True);
1681  return returnStatus;
1682  }
1683 
1684  if (SWwritefield(swId, "Band_500M", (int32*)NULL, (int32*)NULL,
1685  (int32*)NULL, (VOIDP)data_500m) == FAIL)
1686  {
1687  returnStatus = MODIS_F_WRITE_ERROR;
1688  L1BErrorMsg(location, returnStatus, "Band_500M",
1689  "SWwritefield", evfile_luns[file_index], NULL, True);
1690  return returnStatus;
1691  }
1692  break;
1693 
1694  case INDEX_L1B_250m:
1695  if (SWwritefield(swId, "Band_250M", (int32*)NULL, (int32*)NULL,
1696  (int32*)NULL, (VOIDP)data_250m) == FAIL)
1697  {
1698  returnStatus = MODIS_F_WRITE_ERROR;
1699  L1BErrorMsg(location, returnStatus, "Band_250M",
1700  "SWwritefield", evfile_luns[file_index], NULL, True);
1701  return returnStatus;
1702  }
1703  break;
1704  }
1705 
1706  if (SWdetach(swId) == FAIL)
1707  {
1708  returnStatus = MODIS_F_HDF_ERROR;
1709  L1BErrorMsg(location, returnStatus, NULL,
1710  "SWdetach", evfile_luns[file_index], NULL, True);
1711  return returnStatus;
1712  }
1713 
1714  return(MODIS_S_OK);
1715 }
1716 
1717 PGSt_SMF_status Open_L1B_EV_SDS (L1B_granule_t *L1B_Gran,
1718  L1B_Scan_t *L1B_Scan,
1719  boolean skip_night_hi_res)
1720 /*
1721 !C****************************************************************
1722 !Description: Given the L1B file swaths and their EV data fields created
1723  earlier (implemented as SDSs), open SDS access for each of the
1724  SDSs. Additionally, set the "long name" attribute for each SDS.
1725  SDS access will remain open until after all scan-by-scan
1726  processing is complete.
1727 
1728 !Input Parameters:
1729  L1B_Gran (->sd_id) SD file IDs for each of the L1B EV files.
1730  boolean skip_night_hi_res True if and only if all scans are
1731  night mode scans and writing of 250m
1732  and 500m night mode granules has been
1733  turned off
1734 !Output Parameters:
1735  L1B_Scan SDS access ID members:
1736  SI_sds_id[]
1737  EV_250m_Aggr500m_RefSB_sds_id
1738  EV_250m_Aggr1km_RefSB_sds_id
1739  EV_500m_Aggr1km_RefSB_sds_id
1740  UI_sds_id[]
1741  EV_250m_Aggr500m_RefSB_UI_sds_id
1742  EV_250m_Aggr1km_RefSB_UI_sds_id
1743  EV_500m_Aggr1km_RefSB_UI_sds_id
1744  EV_250m_Aggr500m_RefSB_SU_sds_id
1745  EV_250m_Aggr1km_RefSB_SU_sds_id
1746  EV_500m_Aggr1km_RefSB_SU_sds_id
1747 
1748 !Revision History:
1749  (continue at top of the file)
1750 
1751  Revision 03.11 November 15, 2001 Razor Issue #169
1752  Added boolean skip_night_hi_res to input parameters and altered logic so that
1753  if skip_night_hi_res is True, output data sets for 250m and 500m resolution
1754  data are not created.
1755  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
1756 
1757  Revision 03.10 May 1999
1758  Added Band 26 SDS.
1759  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
1760 
1761  Revision 03.00 April 1997
1762  Modified to match changes in data structures.
1763  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
1764 
1765  Revision 02.0 1996/06/28
1766  Version 2, initial redesign
1767  Neal Devine(neal.devine@gsfc.nasa.gov)
1768 
1769  Revision 01.02 1996/04/05
1770  Update to match Version 1 Design Document
1771  Neal Devine(neal.devine@gsfc.nasa.gov)
1772  John Hannon(hannon@highwire.gsfc.nasa.gov)
1773 
1774  Revision 01.00 1993
1775  Initial development
1776  Geir E. Kvaran(geir@highwire.gsfc.nasa.gov)
1777 
1778 !Team-unique Header:
1779  This software is developed by the MODIS Characterization Support
1780  Team (MCST)for the National Aeronautics and Space Administration,
1781  Goddard Space Flight Center, under contract NAS5-32373.
1782 
1783 !References and Credits:
1784  HDF portions developed at the National Center for Supercomputing
1785  Applications at the University of Illinois at Urbana-Champaign.
1786 
1787 !Design Notes:
1788 
1789 !END********************************************************************
1790 */
1791 {
1792  PGSt_SMF_status returnStatus;
1793  char *location = "Open_L1B_EV_SDS";
1794  int32 sds_index = 0;
1795  int16 file_index = 0;
1796  int32 evfile_luns[NUM_L1B_EV_FILES] = {
1800  };
1801 
1802  int32 scaled_250[2] = {13,16};
1803  int32 scaled_500[2] = {10,12};
1804 
1805  /*
1806  * ----------------------------------------------------------------------
1807  * This macro opens SDS access to a pair of L1B EV SDS's (Scaled_Integer
1808  * and Uncert_Index) and sets the long-name attribute for each SDS.
1809  * Input: sd_id, SI_name, UI_name, SI_longName, UI_longName
1810  * Output: SI_id, UI_id
1811  * ----------------------------------------------------------------------
1812  */
1813 #define CREATE_EV_SDS(sd_id, SI_name, UI_name, SI_longName, UI_longName, \
1814  SI_id,UI_id) \
1815 if((sds_index = SDnametoindex(sd_id, SI_name)) == FAIL) \
1816  { \
1817  returnStatus = MODIS_F_HDF_ERROR; \
1818  L1BErrorMsg(location, returnStatus, SI_name, \
1819  "SDnametoindex", evfile_luns[file_index], NULL, True); \
1820  return returnStatus; \
1821  } \
1822 if((SI_id = SDselect(sd_id, sds_index)) == FAIL) \
1823  { \
1824  returnStatus = MODIS_F_HDF_ERROR; \
1825  L1BErrorMsg(location, returnStatus, SI_name, \
1826  "SDselect", evfile_luns[file_index], NULL, True); \
1827  return returnStatus; \
1828  } \
1829 if(SDsetattr(SI_id, "long_name", DFNT_CHAR8,(int32)strlen(SI_longName), \
1830  SI_longName) == FAIL) \
1831  { \
1832  returnStatus = MODIS_F_HDF_ERROR; \
1833  L1BErrorMsg(location, returnStatus, SI_name, \
1834  "SDsetattr", evfile_luns[file_index], "long_name", True); \
1835  return returnStatus; \
1836  } \
1837 if((sds_index = SDnametoindex(sd_id, UI_name)) == FAIL) \
1838  { \
1839  returnStatus = MODIS_F_HDF_ERROR; \
1840  L1BErrorMsg(location, returnStatus, UI_name, \
1841  "SDnametoindex", evfile_luns[file_index], NULL, True); \
1842  return returnStatus; \
1843  } \
1844 if((UI_id = SDselect(sd_id, sds_index)) == FAIL) \
1845  { \
1846  returnStatus = MODIS_F_HDF_ERROR; \
1847  L1BErrorMsg(location, returnStatus, UI_name, \
1848  "SDselect", evfile_luns[file_index], NULL, True); \
1849  return returnStatus; \
1850  } \
1851 if(SDsetattr(UI_id, "long_name", DFNT_CHAR8,(int32)strlen(UI_longName), \
1852  UI_longName) == FAIL) \
1853  { \
1854  returnStatus = MODIS_F_HDF_ERROR; \
1855  L1BErrorMsg(location, returnStatus, UI_name, \
1856  "SDsetattr", evfile_luns[file_index], "long_name", True); \
1857  return returnStatus; \
1858  }
1859 
1860  /*
1861  * -----------------------------------------------------------------------
1862  * This macro opens SDS access to a set of three L1B EV_Aggr SDS's
1863  * (SI, UI and SU) and sets the long-name attribute for each SDS
1864  * Input: sd_id, SI_name, UI_name, SU_name, SI_LName, UI_LName, SU_LName
1865  * Output: SI_id, UI_id, SU_id
1866  * -----------------------------------------------------------------------
1867  */
1868 #define CREATE_EV_Aggr_SDS(sd_id, SI_name, UI_name, SU_name, SI_LName, \
1869  UI_LName, SU_LName, SI_id, UI_id, SU_id) \
1870 CREATE_EV_SDS(sd_id, SI_name, UI_name, SI_LName, UI_LName, SI_id, UI_id); \
1871 if((sds_index = SDnametoindex(sd_id, SU_name)) == FAIL) \
1872  { \
1873  returnStatus = MODIS_F_HDF_ERROR; \
1874  L1BErrorMsg(location, returnStatus, SU_name, \
1875  "SDnametoindex", evfile_luns[file_index], NULL, True); \
1876  return returnStatus; \
1877  } \
1878 if((SU_id = SDselect(sd_id, sds_index)) == FAIL) \
1879  { \
1880  returnStatus = MODIS_F_HDF_ERROR; \
1881  L1BErrorMsg(location, returnStatus, SU_name, \
1882  "SDselect", evfile_luns[file_index], NULL, True); \
1883  return returnStatus; \
1884  } \
1885 if(SDsetattr(SU_id, "long_name", DFNT_CHAR8,(int32)strlen(SU_LName), \
1886  SU_LName) == FAIL) \
1887  { \
1888  returnStatus = MODIS_F_HDF_ERROR; \
1889  L1BErrorMsg(location, returnStatus, SU_name, \
1890  "SDsetattr", evfile_luns[file_index], "long_name", True); \
1891  return returnStatus; \
1892  }
1893 /*--------------------------------------------------------------------*/
1894 
1895  /* Create 250m and 500m files only when skip_night_hi_res is False. */
1896 
1897  if (skip_night_hi_res == False)
1898  {
1899  /*250m file*/
1900  file_index = INDEX_L1B_250m;
1901 
1902  CREATE_EV_SDS (L1B_Gran->sd_id[INDEX_L1B_250m],
1907  L1B_Scan->SI_sds_id[INDEX_250M],
1908  L1B_Scan->UI_sds_id[INDEX_250M]);
1909 
1910  /*500m file*/
1911  file_index = INDEX_L1B_500m;
1912  CREATE_EV_SDS (L1B_Gran->sd_id[INDEX_L1B_500m],
1917  L1B_Scan->SI_sds_id[INDEX_500M],
1918  L1B_Scan->UI_sds_id[INDEX_500M]);
1919 
1930  }
1931 
1932  /*1km file*/
1933  file_index = INDEX_L1B_1km;
1934  CREATE_EV_SDS (L1B_Gran->sd_id[INDEX_L1B_1km],
1939  L1B_Scan->SI_sds_id[INDEX_1000M_REFL],
1940  L1B_Scan->UI_sds_id[INDEX_1000M_REFL]);
1941 
1949  L1B_Scan->EV_250m_Aggr1km_RefSB_sds_id,
1952 
1960  L1B_Scan->EV_500m_Aggr1km_RefSB_sds_id,
1963 
1964  CREATE_EV_SDS (L1B_Gran->sd_id[INDEX_L1B_1km],
1969  L1B_Scan->SI_sds_id[INDEX_1000M_EMISS],
1970  L1B_Scan->UI_sds_id[INDEX_1000M_EMISS]);
1971 
1972  if ((RSCL_FLAG & 1) == 1)
1973  {
1974  if (SDsetattr(L1B_Scan->EV_250m_Aggr1km_RefSB_sds_id,
1975  "Rescaled Ocean R", DFNT_INT32,
1976  1, &scaled_250[0]) == FAIL)
1977  {
1978  returnStatus = MODIS_F_WRITE_ERROR;
1979  L1BErrorMsg(location, returnStatus, "Rescaled Ocean R",
1980  "SDsetattr", 0, NULL, False);
1981  return returnStatus;
1982  }
1983  }
1984 
1985  if ((RSCL_FLAG & 2) == 2)
1986  {
1987  if (SDsetattr(L1B_Scan->EV_250m_Aggr1km_RefSB_sds_id,
1988  "Rescaled Ocean NIR", DFNT_INT32,
1989  1, &scaled_250[1]) == FAIL)
1990  {
1991  returnStatus = MODIS_F_WRITE_ERROR;
1992  L1BErrorMsg(location, returnStatus, "Rescaled Ocean NIR",
1993  "SDsetattr", 0, NULL, False);
1994  return returnStatus;
1995  }
1996  }
1997 
1998  if ((RSCL_FLAG & 4) == 4)
1999  {
2000  if (SDsetattr(L1B_Scan->EV_500m_Aggr1km_RefSB_sds_id,
2001  "Rescaled Ocean B", DFNT_INT32,
2002  1, &scaled_500[0]) == FAIL)
2003  {
2004  returnStatus = MODIS_F_WRITE_ERROR;
2005  L1BErrorMsg(location, returnStatus, "Rescaled Ocean B",
2006  "SDsetattr", 0, NULL, False);
2007  return returnStatus;
2008  }
2009  }
2010 
2011  if ((RSCL_FLAG & 8) == 8)
2012  {
2013  if (SDsetattr(L1B_Scan->EV_500m_Aggr1km_RefSB_sds_id,
2014  "Rescaled Ocean G", DFNT_INT32,
2015  1, &scaled_500[1]) == FAIL)
2016  {
2017  returnStatus = MODIS_F_WRITE_ERROR;
2018  L1BErrorMsg(location, returnStatus, "Rescaled Ocean G",
2019  "SDsetattr", 0, NULL, False);
2020  return returnStatus;
2021  }
2022  }
2023 
2024 /************************* Begin Band 26 Section **************************/
2025 #ifdef WRITE_BAND_26_SDS
2026 /*
2027  * Open SDS access to the band 26 SDSs and save the
2028  * SDS ids in the L1B_Scan structure. SDS access is closed in function
2029  * Close_L1B_Granule. Note that the SDSs are not really created here
2030  * depite the name of the macro. They were created in Create_L1B_Swath.
2031  */
2032  CREATE_EV_SDS (L1B_Gran->sd_id[INDEX_L1B_1km],
2037  L1B_Scan->Band26.SI_sds_id,
2038  L1B_Scan->Band26.UI_sds_id);
2039 #endif /* WRITE_BAND_26_SDS */
2040 /************************** End Band 26 Section ***************************/
2041 
2042  return(MODIS_S_OK);
2043 }
2044 
2045 
2047  L1B_granule_t *L1B_Gran,
2048  L1B_Scan_t *L1B_Scan,
2049  boolean skip_night_hi_res)
2050 /*
2051 !C****************************************************************
2052 !Description: This routine creates and set the units, valid range and
2053  fill-value attributes for each of the EV SDSs (SI, UI and SU).
2054  This routine also writes the following attributes of scaled
2055  integer SDSs: (1) band names, (2) reflectance scales, offsets
2056  and units (only if reflectance SDSs are present), (3) radiance
2057  scales, offsets and units and (4) corrected counts scales,
2058  offsets and units.
2059 
2060 !Input Parameters:
2061  L1B_Gran ->sd_id[] SD file ids for the EV files.
2062  ->SO Scale-Offset struct, contains the radiance,
2063  reflectance and corrected counts scales,
2064  offsets.
2065  L1B_Scan SDS access ids used in Get_SDS_id and in
2066  Set_Unit_Range_Fillvalue.
2067  boolean skip_night_hi_res True if and only if all scans are
2068  night mode scans and writing of 250m
2069  and 500m night mode granules has been
2070  turned off
2071 !Output Parameters:
2072  None
2073 
2074 !Revision History:
2075  (continue at top of the file)
2076 
2077  Revision 02.21 November 15, 2001 Razor Issue #169
2078  Added boolean skip_night_hi_res to input parameters and altered logic so that
2079  if skip_night_hi_res is True, output data sets for 250m and 500m resolution
2080  data are not created.
2081  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
2082 
2083  Revision 02.20 May 13, 1999
2084  Added band 26 section.
2085  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
2086 
2087  Revision 02.11 Sept 14 1998
2088  Change dimension attribute to sds attribute based on
2089  file specs V2.1.1
2090  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
2091 
2092  Revision 02.10 April 10 1998
2093  Changed to the V2.1 L1B_Gran->momos (from the V2
2094  L1B_Gran->SO.rad_scale_RefSB and L1B_Gran->SO.refl_scale_RefSB)
2095  David Catozzi (cato@ltpmail.gsfc.nasa.gov)
2096 
2097  Revision 02.00 April 1997
2098  Modified to match changes in data structures.
2099  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
2100 
2101  Revision 01.00 1997/03/01
2102  Initial development
2103  Neal Devine (neal.devine@gsfc.nasa.gov)
2104 
2105 !Team-unique Header:
2106  This software is developed by the MODIS Characterization Support
2107  Team (MCST)for the National Aeronautics and Space Administration,
2108  Goddard Space Flight Center, under contract NAS5-32373.
2109 
2110 !References and Credits:
2111  HDF portions developed at the National Center for Supercomputing
2112  Applications at the University of Illinois at Urbana-Champaign.
2113 
2114 !Design Notes:
2115  Note that the band dim sds's are used for two distinct purposes:
2116  dim attributes, which happen to create float32 sdss, and band subsetting
2117  numbers.
2118 
2119 !END********************************************************************
2120 */
2121 {
2122  PGSt_SMF_status returnStatus;
2123  char *location = "Set_L1B_EV_SDS_Attrs";
2124  int16 f = 0; /*L1B EV file index (0,2)*/
2125  int16 loc = 0; /*location in an array*/
2126  int16 num_sds = 0; /*num band subsetting sds's within one file*/
2127  int32 sds_ids[4] = {0, 0, 0, 0}; /* added by gu */
2128 
2129  typedef enum {
2130  radiance,
2131  reflectance,
2132  counts,
2133  Num_Kinds
2134  } ScaleOffset_Kind_t;
2135 
2136  float32 *scale[Num_Kinds][NUM_L1A_RESOLUTIONS];
2137  float32 *offset[Num_Kinds][NUM_L1A_RESOLUTIONS];
2138  char *BandNames[NUM_L1A_RESOLUTIONS] = {
2139  "1,2",
2140  "3,4,5,6,7",
2141  "8,9,10,11,12,13lo,13hi,14lo,14hi,15,16,17,18,19,26",
2142  "20,21,22,23,24,25,27,28,29,30,31,32,33,34,35,36"
2143  };
2144  char *rad_units = "Watts/m^2/micrometer/steradian";
2145  char *refl_units = "none";
2146  char *counts_units = "counts";
2147  int32 evfile_luns[NUM_L1B_EV_FILES] =
2148  {
2152  };
2153  int16 start_output_res = INDEX_L1B_250m;
2154 
2155  returnStatus = Set_Unit_Range_Fillvalue(L1B_Scan, skip_night_hi_res);
2156  if (returnStatus != MODIS_S_OK)
2157  {
2158  L1BErrorMsg(location, returnStatus, NULL,
2159  "Set_Unit_Range_Fillvalue", 0, NULL, True);
2160  return returnStatus;
2161  }
2162 
2163  /*
2164  * Add additional attributes to uncertainty index SDSs.
2165  */
2166 
2167  returnStatus = Set_UI_ConvertToPercent_Attrs(tables,
2168  L1B_Scan,
2169  skip_night_hi_res);
2170  if (returnStatus != MODIS_S_OK)
2171  {
2172  L1BErrorMsg(location, returnStatus, NULL,
2173  "Set_UI_ConvertToPercent_Attrs", 0, NULL, True);
2174  return returnStatus;
2175  }
2176 
2177  /********************************
2178  * 250m scales and offsets *
2179  ********************************/
2180  scale[radiance][INDEX_250M] = &(L1B_Gran->SO.rad_scale_RefSB[0]);
2181  scale[reflectance][INDEX_250M] = &(L1B_Gran->SO.refl_scale_RefSB[0]);
2182 
2183  offset[radiance][INDEX_250M] = &(L1B_Gran->SO.rad_offset_RefSB[0]);
2184  offset[reflectance][INDEX_250M] = &(L1B_Gran->SO.refl_offset_RefSB[0]);
2185 
2186  scale[counts][INDEX_250M] = &(L1B_Gran->SO.counts_scale_RefSB[0]);
2187  offset[counts][INDEX_250M] = &(L1B_Gran->SO.counts_offset_RefSB[0]);
2188 
2189 
2190  /********************************
2191  * 500m scales and offsets *
2192  ********************************/
2194 
2195  scale[radiance][INDEX_500M] =
2196  &(L1B_Gran->SO.rad_scale_RefSB[loc]);
2197  scale[reflectance][INDEX_500M] =
2198  &(L1B_Gran->SO.refl_scale_RefSB[loc]);
2199 
2200  offset[radiance][INDEX_500M] =
2201  &(L1B_Gran->SO.rad_offset_RefSB[loc]);
2202  offset[reflectance][INDEX_500M] =
2203  &(L1B_Gran->SO.refl_offset_RefSB[loc]);
2204 
2205  scale[counts][INDEX_500M] =
2206  &(L1B_Gran->SO.counts_scale_RefSB[loc]);
2207  offset[counts][INDEX_500M] =
2208  &(L1B_Gran->SO.counts_offset_RefSB[loc]);
2209 
2210  /********************************
2211  * 1Km Refl scales and offsets *
2212  ********************************/
2214 
2215  scale[radiance][INDEX_1000M_REFL] =
2216  &(L1B_Gran->SO.rad_scale_RefSB[loc]);
2217  scale[reflectance][INDEX_1000M_REFL] =
2218  &(L1B_Gran->SO.refl_scale_RefSB[loc]);
2219 
2220  offset[radiance][INDEX_1000M_REFL] =
2221  &(L1B_Gran->SO.rad_offset_RefSB[loc]);
2222  offset[reflectance][INDEX_1000M_REFL] =
2223  &(L1B_Gran->SO.refl_offset_RefSB[loc]);
2224 
2226  &(L1B_Gran->SO.counts_scale_RefSB[loc]);
2228  &(L1B_Gran->SO.counts_offset_RefSB[loc]);
2229 
2230 
2231  /********************************
2232  * 1Km Emiss scales and offsets *
2233  ********************************/
2234  scale[radiance][INDEX_1000M_EMISS] =
2235  &(L1B_Gran->SO.rad_scale_Emiss[0]);
2236  offset[radiance][INDEX_1000M_EMISS] =
2237  &(L1B_Gran->SO.rad_offset_Emiss[0]);
2238 
2239  /*******************************
2240  * 250m holds rescaled R & NIR *
2241  *******************************/
2242  if ((RFLAG & 1) == 1) {
2243  scale[reflectance][INDEX_250M][0] = scale[counts][INDEX_250M][0]*
2244  scale[reflectance][INDEX_1000M_REFL][5]/scale[counts][INDEX_1000M_REFL][5];
2245  scale[reflectance][INDEX_250M][1] = scale[counts][INDEX_250M][1]*
2246  scale[reflectance][INDEX_1000M_REFL][10]/scale[counts][INDEX_1000M_REFL][10];
2247  }
2248 
2249  /*****************************
2250  * 500m holds rescaled B & G *
2251  *****************************/
2252  if ((RFLAG & 2) == 2) {
2253  scale[reflectance][INDEX_500M][0] = scale[counts][INDEX_500M][0]*
2254  scale[reflectance][INDEX_1000M_REFL][2]/scale[counts][INDEX_1000M_REFL][2];
2255  scale[reflectance][INDEX_500M][1] = scale[counts][INDEX_500M][1]*
2256  scale[reflectance][INDEX_1000M_REFL][4]/scale[counts][INDEX_1000M_REFL][4];
2257  }
2258 
2259  /*
2260  * If we are in night mode and we do not wish to write 250m and 500m data
2261  * sets, start with the 1KM output data sets.
2262  */
2263 
2264  if (skip_night_hi_res == True)
2265  start_output_res = INDEX_L1B_1km;
2266  else
2267  start_output_res = INDEX_L1B_250m;
2268 
2269  for (f = start_output_res; f < NUM_L1B_EV_FILES; f++)
2270  {
2271  returnStatus = Get_SDS_id(f, L1B_Scan, &num_sds, sds_ids);
2272 
2273  if (returnStatus != MODIS_S_OK)
2274  {
2275  L1BErrorMsg(location, returnStatus, NULL,
2276  "Get_SDS_id", evfile_luns[f], NULL, True);
2277  return returnStatus;
2278  }
2279 
2280  returnStatus = Set_SDS_Attributes(sds_ids, BandNames,
2281  (float32 **)scale,
2282  (float32 **)offset,
2283  rad_units,
2284  refl_units,
2285  counts_units,
2286  num_sds);
2287 
2288  if (returnStatus != MODIS_S_OK)
2289  {
2290  L1BErrorMsg(location, returnStatus, NULL,
2291  "Set_SDS_Attributes", evfile_luns[f], NULL, True);
2292  return returnStatus;
2293  }
2294 
2295  } /*f*/
2296 
2297 /************************* Begin Band 26 Section **************************/
2298 #ifdef WRITE_BAND_26_SDS
2299  /*
2300  * Set the radiance, reflectance and corrected counts scales for
2301  * the Band 26 scaled integer SDS.
2302  */
2303 
2304  f = INDEX_L1B_1km; /* file index, for LUN identification */
2305  loc = NUM_REFLECTIVE_BANDS - 1; /* index of Band 26 in SO arrays */
2306 
2307  if (SDsetattr(L1B_Scan->Band26.SI_sds_id, "radiance_scales",
2308  DFNT_FLOAT32,
2309  1, &(L1B_Gran->SO.rad_scale_RefSB[loc])) == FAIL)
2310  {
2311  returnStatus = MODIS_F_WRITE_ERROR;
2312  L1BErrorMsg(location, returnStatus,
2313  "Could not write Band 26 SI SDS "
2314  "attribute "
2315  "\"radiance_scales\".",
2316  "SDsetattr", evfile_luns[f], NULL, True);
2317  return returnStatus;
2318  }
2319 
2320  if (SDsetattr(L1B_Scan->Band26.SI_sds_id, "radiance_offsets",
2321  DFNT_FLOAT32,
2322  1, &(L1B_Gran->SO.rad_offset_RefSB[loc])) == FAIL)
2323  {
2324  returnStatus = MODIS_F_WRITE_ERROR;
2325  L1BErrorMsg(location, returnStatus,
2326  "Could not write Band 26 SI SDS "
2327  "attribute "
2328  "\"radiance_offsets\".",
2329  "SDsetattr", evfile_luns[f], NULL, True);
2330  return returnStatus;
2331  }
2332 
2333  if (SDsetattr(L1B_Scan->Band26.SI_sds_id, "radiance_units",
2334  DFNT_CHAR8,
2335  (int32)strlen(rad_units), rad_units) == FAIL)
2336  {
2337  returnStatus = MODIS_F_WRITE_ERROR;
2338  L1BErrorMsg(location, returnStatus,
2339  "Could not write Band 26 SI SDS "
2340  "attribute "
2341  "\"radiance_units\".",
2342  "SDsetattr", evfile_luns[f], NULL, True);
2343  return returnStatus;
2344  }
2345 
2346  if (SDsetattr(L1B_Scan->Band26.SI_sds_id, "reflectance_scales",
2347  DFNT_FLOAT32,
2348  1, &(L1B_Gran->SO.refl_scale_RefSB[loc])) == FAIL)
2349  {
2350  returnStatus = MODIS_F_WRITE_ERROR;
2351  L1BErrorMsg(location, returnStatus,
2352  "Could not write Band 26 SI SDS "
2353  "attribute "
2354  "\"reflectance_scales\".",
2355  "SDsetattr", evfile_luns[f], NULL, True);
2356  return returnStatus;
2357  }
2358 
2359  if (SDsetattr(L1B_Scan->Band26.SI_sds_id, "reflectance_offsets",
2360  DFNT_FLOAT32,
2361  1, &(L1B_Gran->SO.refl_offset_RefSB[loc])) == FAIL)
2362  {
2363  returnStatus = MODIS_F_WRITE_ERROR;
2364  L1BErrorMsg(location, returnStatus,
2365  "Could not write Band 26 SI SDS "
2366  "attribute "
2367  "\"reflectance_offsets\".",
2368  "SDsetattr", evfile_luns[f], NULL, True);
2369  return returnStatus;
2370  }
2371 
2372  if (SDsetattr(L1B_Scan->Band26.SI_sds_id, "reflectance_units",
2373  DFNT_CHAR8,
2374  (int32)strlen(refl_units), refl_units) == FAIL)
2375  {
2376  returnStatus = MODIS_F_WRITE_ERROR;
2377  L1BErrorMsg(location, returnStatus,
2378  "Could not write Band 26 SI SDS "
2379  "attribute "
2380  "\"reflectance_units\".",
2381  "SDsetattr", evfile_luns[f], NULL, True);
2382  return returnStatus;
2383  }
2384 
2385  if (SDsetattr(L1B_Scan->Band26.SI_sds_id, "corrected_counts_scales",
2386  DFNT_FLOAT32,
2387  1, &(L1B_Gran->SO.counts_scale_RefSB[loc])) == FAIL)
2388  {
2389  returnStatus = MODIS_F_WRITE_ERROR;
2390  L1BErrorMsg(location, returnStatus,
2391  "Could not write Band 26 SI SDS "
2392  "attribute "
2393  "\"corrected_counts_scales\".",
2394  "SDsetattr", evfile_luns[f], NULL, True);
2395  return returnStatus;
2396  }
2397 
2398  if (SDsetattr(L1B_Scan->Band26.SI_sds_id, "corrected_counts_offsets",
2399  DFNT_FLOAT32,
2400  1, &(L1B_Gran->SO.counts_offset_RefSB[loc])) == FAIL)
2401  {
2402  returnStatus = MODIS_F_WRITE_ERROR;
2403  L1BErrorMsg(location, returnStatus,
2404  "Could not write Band 26 SI SDS "
2405  "attribute "
2406  "\"corrected_counts_offsets\".",
2407  "SDsetattr", evfile_luns[f], NULL, True);
2408  return returnStatus;
2409  }
2410 
2411  if (SDsetattr(L1B_Scan->Band26.SI_sds_id, "corrected_counts_units",
2412  DFNT_CHAR8,
2413  (int32)strlen(counts_units), counts_units) == FAIL)
2414  {
2415  returnStatus = MODIS_F_WRITE_ERROR;
2416  L1BErrorMsg(location, returnStatus,
2417  "Could not write Band 26 SI SDS "
2418  "attribute "
2419  "\"corrected_counts_units\".",
2420  "SDsetattr", evfile_luns[f], NULL, True);
2421  return returnStatus;
2422  }
2423 
2424 #endif /* WRITE_BAND_26_SDS */
2425 /************************** End Band 26 Section ***************************/
2426 
2427  return(MODIS_S_OK);
2428 }
2429 
2430 PGSt_SMF_status Set_Unit_Range_Fillvalue(L1B_Scan_t *L1B_Scan,
2431  boolean skip_night_hi_res)
2432 /*
2433 !C**********************************************************************
2434 !Description: This routine creates and set the units, valid range and
2435  fill-value attributes for each of the EV SDSs (SI, UI and SU).
2436 
2437 !Input Parameters:
2438  L1B_Scan_t * L1B_Scan
2439  boolean skip_night_hi_res True if and only if all scans are
2440  night mode scans and writing of 250m
2441  and 500m night mode granules has been
2442  turned off
2443 
2444 !Output Parameters:
2445 
2446 !Revision History:
2447  (continue at top of the file)
2448 
2449  Revision 01.11 October 16, 2004 Razor Issue #200
2450  Casted Int32 variables in sprintf calls to "long" with the
2451  format specifier "%ld" for better code portability.
2452  Liqin Tan, SAIC GSO (ltan@saicmodis.com)
2453 
2454  Revision 01.10 May 13, 1999
2455  Added band 26 section.
2456  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
2457 
2458  Revision 01.01 Feb 18, 1999
2459  Made the SU_valid_range an array of pointers, since there are different
2460  valid ranges for the different aggregated SDSs.
2461  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
2462 
2463  Revision 01.00 1998
2464  Initial development
2465  Zhenying Gu(zgu@ltpmail.gsfc.nasa.gov)
2466 
2467 !Team-unique Header:
2468  This software is developed by the MODIS Characterization Support
2469  Team (MCST)for the National Aeronautics and Space Administration,
2470  Goddard Space Flight Center, under contract NAS5-32373.
2471 
2472 !References and Credits:
2473  HDF portions developed at the National Center for Supercomputing
2474  Applications at the University of Illinois at Urbana-Champaign.
2475 
2476 !Design Notes:
2477 
2478 !END********************************************************************
2479 */
2480 
2481 {
2482  PGSt_SMF_status returnStatus = MODIS_S_OK;
2483  char *location = "Set_Unit_Range_Fillvalue";
2484  char errmsg[256];
2485  char *errmsgfmt = "Could not write attribute \"%s\", "
2486  "type[%ld], sds_number[%ld].";
2487  typedef enum {
2488  SI,
2489  UI,
2490  SU,
2491  Num_Data_types
2492  } EV_Data_Type_t;
2493  typedef enum { RefSB_250_Data,
2494  RefSB_500_Data,
2495  RefSB_1KM_Data,
2496  Emissive_Data,
2497  Aggr_250_500_RefSB_Data,
2498  Aggr_250_1km_RefSB_Data,
2499  Aggr_500_1km_RefSB_Data,
2500  NUM_EV_DATA_SETS
2501  } ev_Data_Sets_t;
2502  typedef enum { Aggr_250_500_RefSB_Samples,
2503  Aggr_250_1km_RefSB_Samples,
2504  Aggr_500_1km_RefSB_Samples,
2505  NUM_EV_AGGR_SAMPLES
2506  } ev_Aggr_Samples_t;
2507  int32 type;
2508  int32 sds_number;
2509  int32 num_sds_ids[Num_Data_types] = {7, 7, 3};
2510  int32 R;
2511  char *units = "none";
2512  uint16 SI_valid_range[2] = {0, 32767};
2513  uint8 UI_valid_range[2] = {0, 15};
2514  int8 SU_valid_range_X2[2] = {0, 6}; /* aggregating by a factor of 2 */
2515  int8 SU_valid_range_X4[2] = {0, 28}; /* aggregating by a factor of 4 */
2516  int8 *SU_valid_range[3];
2517  uint16 SI_fillvalue = 65535;
2518  uint8 UI_fillvalue = 255;
2519  int8 SU_fillvalue = -1;
2520  int32 SI_sds_ids[7];
2521  int32 UI_sds_ids[7];
2522  int32 SU_sds_ids[3];
2523  int32 *sds_ids[Num_Data_types];
2524  int16 start_output_res = INDEX_L1B_250m;
2525  /* in the loop below, these are indexed with sds_number for SU case */
2526 
2527  /* 250m_Aggr500 */
2528  SU_valid_range[Aggr_250_500_RefSB_Samples] = SU_valid_range_X2;
2529  /* 250m_Aggr1km */
2530  SU_valid_range[Aggr_250_1km_RefSB_Samples] = SU_valid_range_X4;
2531  /* 500m_Aggr1km */
2532  SU_valid_range[Aggr_500_1km_RefSB_Samples] = SU_valid_range_X2;
2533 
2534  sds_ids[0] = SI_sds_ids;
2535  sds_ids[1] = UI_sds_ids;
2536  sds_ids[2] = SU_sds_ids;
2537 
2538  for(R = 0; R < NUM_L1A_RESOLUTIONS; R++)
2539  {
2540  SI_sds_ids[R] = L1B_Scan->SI_sds_id[R];
2541  UI_sds_ids[R] = L1B_Scan->UI_sds_id[R];
2542  }
2543 
2544  SI_sds_ids[Aggr_250_500_RefSB_Data] =
2546  SI_sds_ids[Aggr_250_1km_RefSB_Data] =
2547  L1B_Scan->EV_250m_Aggr1km_RefSB_sds_id;
2548  SI_sds_ids[Aggr_500_1km_RefSB_Data] =
2549  L1B_Scan->EV_500m_Aggr1km_RefSB_sds_id;
2550 
2551  UI_sds_ids[Aggr_250_500_RefSB_Data] =
2553  UI_sds_ids[Aggr_250_1km_RefSB_Data] =
2555  UI_sds_ids[Aggr_500_1km_RefSB_Data] =
2557 
2558  SU_sds_ids[Aggr_250_500_RefSB_Samples] =
2560  SU_sds_ids[Aggr_250_1km_RefSB_Samples] =
2562  SU_sds_ids[Aggr_500_1km_RefSB_Samples] =
2564 
2565  /*
2566  * The following shows the relationship between index, type, and sds#.
2567  * index type sds# good night indices = [2, 3, 5, 6]
2568  * 0 0 0 SI_name = EV_250_RefSB
2569  * 1 0 1 SI_name = EV_500_RefSB
2570  * 2 0 2 SI_name = EV_1KM_RefSB
2571  * 2 0 3 SI_name = EV_1KM_Emissive
2572  * 1 0 4 SI_name = EV_250_Aggr500_RefSB
2573  * 2 0 5 SI_name = EV_250_Aggr1km_RefSB
2574  * 2 0 6 SI_name = EV_500_Aggr1km_RefSB
2575  * good night indices = [2, 3, 5, 6]
2576  * 0 1 0 UI_name = EV_250_RefSB_Uncert_Indexes
2577  * 1 1 1 UI_name = EV_500_RefSB_Uncert_Indexes
2578  * 2 1 2 UI_name = EV_1KM_RefSB_Uncert_Indexes
2579  * 2 1 3 UI_name = EV_1KM_Emissive_Uncert_Indexes
2580  * 1 1 4 UI_name = EV_250_Aggr500_RefSB_Uncert_Indexes
2581  * 2 1 5 UI_name = EV_250_Aggr1km_RefSB_Uncert_Indexes
2582  * 2 1 6 UI_name = EV_500_Aggr1km_RefSB_Uncert_Indexes
2583  * good night indices = none
2584  * 1 2 0 SU_name = EV_250_Aggr500_RefSB_Samples_Used
2585  * 2 2 1 SU_name = EV_250_Aggr1km_RefSB_Samples_Used
2586  * 2 2 2 SU_name = EV_500_Aggr1km_RefSB_Samples_Used
2587  */
2588 
2589 
2590 
2591  for (type = 0; type < Num_Data_types; type++)
2592  {
2593  if (type < SU && skip_night_hi_res == True)
2594  start_output_res = INDEX_L1B_1km;
2595  else
2596  start_output_res = INDEX_L1B_250m;
2597 
2598  for (sds_number = start_output_res;
2599  sds_number < num_sds_ids[type]; sds_number++)
2600 
2601  {
2602  if (skip_night_hi_res == True)
2603  if ((type < SU && sds_number == Aggr_250_500_RefSB_Data) ||
2604  (type == SU && sds_number == Aggr_250_500_RefSB_Samples))
2605  continue;
2606 
2607  if (SDsetattr(sds_ids[type][sds_number], "units",
2608  DFNT_CHAR, 4, (VOIDP)units) == FAIL)
2609  {
2610  sprintf(errmsg, errmsgfmt, "units", (long)type, (long)sds_number);
2611  returnStatus = MODIS_F_WRITE_ERROR;
2612  L1BErrorMsg(location, returnStatus, errmsg,
2613  "SDsetattr", 0, NULL, True);
2614  return returnStatus;
2615  }
2616 
2617  switch(type)
2618  {
2619  case SI:
2620 
2621  if (SDsetattr(sds_ids[type][sds_number], "valid_range",
2622  DFNT_UINT16, 2, (VOIDP)SI_valid_range) == FAIL)
2623  {
2624  sprintf(errmsg, errmsgfmt, "valid_range", (long)type, (long)sds_number);
2625  returnStatus = MODIS_F_WRITE_ERROR;
2626  L1BErrorMsg(location, returnStatus, errmsg,
2627  "SDsetattr", 0, NULL, True);
2628  return returnStatus;
2629  }
2630 
2631  if (SDsetattr(sds_ids[type][sds_number], "_FillValue",
2632  DFNT_UINT16, 1,(VOIDP)&SI_fillvalue) == FAIL)
2633  {
2634  sprintf(errmsg, errmsgfmt, "_FillValue", (long)type, (long)sds_number);
2635  returnStatus = MODIS_F_WRITE_ERROR;
2636  L1BErrorMsg(location, returnStatus, errmsg,
2637  "SDsetattr", 0, NULL, True);
2638  return returnStatus;
2639  }
2640  break;
2641 
2642  case UI:
2643 
2644  if (SDsetattr(sds_ids[type][sds_number], "valid_range",
2645  DFNT_UINT8, 2, (VOIDP)UI_valid_range) == FAIL)
2646  {
2647  sprintf(errmsg, errmsgfmt, "valid_range", (long)type, (long)sds_number);
2648  returnStatus = MODIS_F_WRITE_ERROR;
2649  L1BErrorMsg(location, returnStatus, errmsg,
2650  "SDsetattr", 0, NULL, True);
2651  return returnStatus;
2652  }
2653 
2654  if (SDsetattr(sds_ids[type][sds_number], "_FillValue",
2655  DFNT_UINT8, 1,(VOIDP)&UI_fillvalue) == FAIL)
2656  {
2657  sprintf(errmsg, errmsgfmt, "_FillValue", (long)type, (long)sds_number);
2658  returnStatus = MODIS_F_WRITE_ERROR;
2659  L1BErrorMsg(location, returnStatus, errmsg,
2660  "SDsetattr", 0, NULL, True);
2661  return returnStatus;
2662  }
2663  break;
2664 
2665  case SU:
2666 
2667  if (SDsetattr(sds_ids[type][sds_number], "valid_range",
2668  DFNT_INT8, 2,
2669  (VOIDP)SU_valid_range[sds_number]) == FAIL)
2670  {
2671  sprintf(errmsg, errmsgfmt, "valid_range", (long)type, (long)sds_number);
2672  returnStatus = MODIS_F_WRITE_ERROR;
2673  L1BErrorMsg(location, returnStatus, errmsg,
2674  "SDsetattr", 0, NULL, True);
2675  return returnStatus;
2676  }
2677 
2678  if (SDsetattr(sds_ids[type][sds_number], "_FillValue",
2679  DFNT_INT8, 1,(VOIDP)&SU_fillvalue) == FAIL)
2680  {
2681  sprintf(errmsg, errmsgfmt, "_FillValue", (long)type, (long)sds_number);
2682  returnStatus = MODIS_F_WRITE_ERROR;
2683  L1BErrorMsg(location, returnStatus, errmsg,
2684  "SDsetattr", 0, NULL, True);
2685  return returnStatus;
2686  }
2687  break;
2688  default:
2689  {
2690  returnStatus = MODIS_F_NOK;
2691  L1BErrorMsg(location, returnStatus,
2692  "Invalid \"type\" ... must be code bug.",
2693  "SDsetattr", 0, NULL, True);
2694  return returnStatus;
2695  }
2696  }
2697  }
2698  }/* end loop through type */
2699 
2700 /************************* Begin Band 26 Section **************************/
2701 #ifdef WRITE_BAND_26_SDS
2702  /*
2703  * Set the units, valid_range and _FillValue attributes for the
2704  * Band 26 SDSs.
2705  */
2706  /* Scaled Integer SDS */
2707 
2708  if (SDsetattr(L1B_Scan->Band26.SI_sds_id, "units",
2709  DFNT_CHAR, 4, (VOIDP)units) == FAIL)
2710  {
2711  strcpy(errmsg, "Could not write Band 26 SI SDS "
2712  "attribute \"units\".");
2713  returnStatus = MODIS_F_WRITE_ERROR;
2714  L1BErrorMsg(location, returnStatus, errmsg,
2715  "SDsetattr", 0, NULL, True);
2716  return returnStatus;
2717  }
2718  if (SDsetattr(L1B_Scan->Band26.SI_sds_id, "valid_range",
2719  DFNT_UINT16, 2, (VOIDP)SI_valid_range) == FAIL)
2720  {
2721  strcpy(errmsg, "Could not write Band 26 SI SDS "
2722  "attribute \"valid_range\".");
2723  returnStatus = MODIS_F_WRITE_ERROR;
2724  L1BErrorMsg(location, returnStatus, errmsg,
2725  "SDsetattr", 0, NULL, True);
2726  return returnStatus;
2727  }
2728  if (SDsetattr(L1B_Scan->Band26.SI_sds_id, "_FillValue",
2729  DFNT_UINT16, 1,(VOIDP)&SI_fillvalue) == FAIL)
2730  {
2731  strcpy(errmsg, "Could not write Band 26 SI SDS "
2732  "attribute \"_FillValue\".");
2733  returnStatus = MODIS_F_WRITE_ERROR;
2734  L1BErrorMsg(location, returnStatus, errmsg,
2735  "SDsetattr", 0, NULL, True);
2736  return returnStatus;
2737  }
2738 
2739  /* Undertainty SDS */
2740 
2741  if (SDsetattr(L1B_Scan->Band26.UI_sds_id, "units",
2742  DFNT_CHAR, 4, (VOIDP)units) == FAIL)
2743  {
2744  strcpy(errmsg, "Could not write Band 26 UI SDS "
2745  "attribute \"units\".");
2746  returnStatus = MODIS_F_WRITE_ERROR;
2747  L1BErrorMsg(location, returnStatus, errmsg,
2748  "SDsetattr", 0, NULL, True);
2749  return returnStatus;
2750  }
2751  if (SDsetattr(L1B_Scan->Band26.UI_sds_id, "valid_range",
2752  DFNT_UINT8, 2, (VOIDP)UI_valid_range) == FAIL)
2753  {
2754  strcpy(errmsg, "Could not write Band 26 UI SDS "
2755  "attribute \"valid_range\".");
2756  returnStatus = MODIS_F_WRITE_ERROR;
2757  L1BErrorMsg(location, returnStatus, errmsg,
2758  "SDsetattr", 0, NULL, True);
2759  return returnStatus;
2760  }
2761  if (SDsetattr(L1B_Scan->Band26.UI_sds_id, "_FillValue",
2762  DFNT_UINT8, 1,(VOIDP)&UI_fillvalue) == FAIL)
2763  {
2764  strcpy(errmsg, "Could not write Band 26 UI SDS "
2765  "attribute \"_FillValue\".");
2766  returnStatus = MODIS_F_WRITE_ERROR;
2767  L1BErrorMsg(location, returnStatus, errmsg,
2768  "SDsetattr", 0, NULL, True);
2769  return returnStatus;
2770  }
2771 
2772 #endif /* WRITE_BAND_26_SDS */
2773 /************************** End Band 26 Section ***************************/
2774 
2775  return(MODIS_S_OK);
2776 }
2777 
2778 PGSt_SMF_status Get_SDS_id(int32 f,
2779  L1B_Scan_t *L1B_Scan,
2780  int16 *num_sds,
2781  int32 *sds_id)
2782 /*
2783 !C**********************************************************************
2784 !Description: For one L1B EV file of index f, this routine gets the number
2785  of EV, scaled integer (SI), SDSs and an array of the SDS ids.
2786  These include both aggregated and non-aggregated SI SDSs.
2787 
2788 !Input Parameters:
2789  f Index of one of the L1B EV files.
2790  L1B_Scan Members which are SDS ids for scaled integer (SI) SDSs.
2791 
2792 !Output Parameters:
2793  num_sds Number of SDS ids assigned to array sds_id.
2794  sds_id Array of SDS ids pertaining to the particular file
2795  of index f. This array should be allocated large
2796  enough to hold at least 4 ids.
2797 
2798 !Revision History:
2799  (continue at top of the file)
2800 
2801  Revision 01.01 Feb 10, 1999
2802  Added address of num_sds to argument list to be able to assign the variable
2803  in this function.
2804  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
2805 
2806  Revision 01.00 1998
2807  Initial development
2808  Zhenying Gu(zgu@ltpmail.gsfc.nasa.gov)
2809 
2810 !Team-unique Header:
2811 
2812 !References and Credits:
2813  This software is developed by the MODIS Characterization Support
2814  Team (MCST)for the National Aeronautics and Space Administration,
2815  Goddard Space Flight Center, under contract NAS5-32373.
2816 
2817  HDF portions developed at the National Center for Supercomputing
2818  Applications at the University of Illinois at Urbana-Champaign.
2819 
2820 !Design Notes:
2821  The ordering of the SDS ids follows the ordering in resolution_index_t
2822  so that we can later use the macros INDEX_250M, ... INDEX_1000M_EMISS.
2823 
2824 !END********************************************************************
2825 */
2826 {
2827  switch(f)
2828  {
2829  case INDEX_L1B_250m:
2830  *num_sds = 1;
2831  sds_id[INDEX_250M] = L1B_Scan->SI_sds_id[INDEX_250M];
2832  break;
2833 
2834  case INDEX_L1B_500m:
2835  *num_sds = 2;
2836  sds_id[INDEX_250M] =
2838  sds_id[INDEX_500M] =
2839  L1B_Scan->SI_sds_id[INDEX_500M];
2840  break;
2841 
2842  case INDEX_L1B_1km:
2843  *num_sds =
2844  4;
2845  sds_id[INDEX_250M] =
2846  L1B_Scan->EV_250m_Aggr1km_RefSB_sds_id;
2847  sds_id[INDEX_500M] =
2848  L1B_Scan->EV_500m_Aggr1km_RefSB_sds_id;
2849  sds_id[INDEX_1000M_REFL] =
2850  L1B_Scan->SI_sds_id[INDEX_1000M_REFL];
2851  sds_id[INDEX_1000M_EMISS] =
2852  L1B_Scan->SI_sds_id[INDEX_1000M_EMISS];
2853  break;
2854 
2855  default:
2856  break;
2857  }
2858 
2859  return(MODIS_S_OK);
2860 }
2861 
2862 PGSt_SMF_status Set_SDS_Attributes(int32 *sds_id,
2863  char **BandNames,
2864  float32 **scale,
2865  float32 **offset,
2866  char *rad_units,
2867  char *refl_units,
2868  char *counts_units,
2869  int32 num_sds)
2870 /*
2871 !C**********************************************************************
2872 !Description: This routine writes the the following attributes of
2873  scaled integer SDSs: (1) band names, (2) reflectance
2874  scales, offsets and units (only if reflectance SDSs are
2875  present), (3) radiance scales, offsets and units and
2876  (4) corrected counts scales, offsets and units.
2877 
2878 !Input Parameters:
2879  int32 * sds_id array of SDS ids for EV SDSs. The ordering
2880  follows the order in resolution_index_t
2881  so we can use the macros defined there.
2882  char ** BandNames Array of band names for each SDS.
2883  float32 ** scale
2884  float32 ** offset
2885  char * rad_units String containing radiance units.
2886  char * refl_units String containing reflectance units.
2887  char * counts_units String containing corrected counts units.
2888  int32 num_sds Number of SDSs in array sds_id.
2889 !Output Parameters:
2890 
2891 !Revision History:
2892  (continue at top of the file)
2893 
2894  Revision 01.01 October 16, 2004 Razor Issue #200
2895  Casted Int32 variables in sprintf calls to "long" with the
2896  format specifier "%ld" for better code portability.
2897  Liqin Tan, SAIC GSO (ltan@saicmodis.com)
2898 
2899  Revision 01.00 1998
2900  Initial development
2901  Zhenying Gu(zgu@ltpmail.gsfc.nasa.gov)
2902 
2903 !Team-unique Header:
2904  This software is developed by the MODIS Characterization Support
2905  Team (MCST)for the National Aeronautics and Space Administration,
2906  Goddard Space Flight Center, under contract NAS5-32373.
2907 
2908 !References and Credits:
2909  HDF portions developed at the National Center for Supercomputing
2910  Applications at the University of Illinois at Urbana-Champaign.
2911 
2912 !Design Notes:
2913  If there is an error, write the L1BErrorMsg but do not error-out.
2914  Let the parent error out so that LUN can be identified.
2915 
2916 !END********************************************************************
2917 */
2918 {
2919  PGSt_SMF_status returnStatus = MODIS_S_OK;
2920  char *location = "Set_SDS_Attributes";
2921  char *errmsgfmt = "Could not write attribute \"%s\" for R = %ld";
2922  char errmsg[256];
2923  int32 R;
2924  typedef enum {
2925  radiance,
2926  reflectance,
2927  counts,
2928  Num_Kinds
2929  } ScaleOffset_Kind_t;
2930 
2931  int16 sds_dim = 4;
2932  int32 dim_size[4] = {2, 5, 15, 16};
2933 
2934  for (R = 0; R < num_sds; R++)
2935  {
2936  if (SDsetattr(sds_id[R],"band_names",DFNT_CHAR8,
2937  (int32)strlen(BandNames[R]), BandNames[R]) == FAIL)
2938  {
2939  returnStatus = MODIS_F_WRITE_ERROR;
2940  sprintf(errmsg, errmsgfmt, "band_names", (long)R);
2941  L1BErrorMsg(location, returnStatus, errmsg,
2942  "SDsetattr", 0, NULL, False);
2943  return returnStatus;
2944  }
2945 
2946  if (SDsetattr(sds_id[R],"radiance_scales",DFNT_FLOAT32,
2947  dim_size[R],scale[radiance * sds_dim + R]) == FAIL)
2948  {
2949  returnStatus = MODIS_F_WRITE_ERROR;
2950  sprintf(errmsg, errmsgfmt, "radiance_scales", (long)R);
2951  L1BErrorMsg(location, returnStatus, errmsg,
2952  "SDsetattr", 0, NULL, False);
2953  return returnStatus;
2954  }
2955 
2956  if (SDsetattr(sds_id[R],"radiance_offsets",DFNT_FLOAT32,
2957  dim_size[R], offset[radiance * sds_dim + R]) == FAIL)
2958  {
2959  returnStatus = MODIS_F_WRITE_ERROR;
2960  sprintf(errmsg, errmsgfmt, "radiance_offsets", (long)R);
2961  L1BErrorMsg(location, returnStatus, errmsg,
2962  "SDsetattr", 0, NULL, False);
2963  return returnStatus;
2964  }
2965 
2966  if (SDsetattr(sds_id[R],"radiance_units",DFNT_CHAR8,
2967  (int32)strlen(rad_units), rad_units) == FAIL)
2968  {
2969  returnStatus = MODIS_F_WRITE_ERROR;
2970  sprintf(errmsg, errmsgfmt, "radiance_units", (long)R);
2971  L1BErrorMsg(location, returnStatus, errmsg,
2972  "SDsetattr", 0, NULL, False);
2973  return returnStatus;
2974  }
2975 
2976  if (R != INDEX_1000M_EMISS)
2977  {
2978  if (SDsetattr(sds_id[R],"reflectance_scales",DFNT_FLOAT32,
2979  dim_size[R],scale[reflectance * sds_dim + R])
2980  == FAIL)
2981  {
2982  returnStatus = MODIS_F_WRITE_ERROR;
2983  sprintf(errmsg, errmsgfmt, "reflectance_scales", (long)R);
2984  L1BErrorMsg(location, returnStatus, errmsg,
2985  "SDsetattr", 0, NULL, False);
2986  return returnStatus;
2987  }
2988 
2989  if (SDsetattr(sds_id[R],"reflectance_offsets",DFNT_FLOAT32,
2990  dim_size[R],offset[reflectance * sds_dim + R])
2991  == FAIL)
2992  {
2993  returnStatus = MODIS_F_WRITE_ERROR;
2994  sprintf(errmsg, errmsgfmt, "reflectance_offsets", (long)R);
2995  L1BErrorMsg(location, returnStatus, errmsg,
2996  "SDsetattr", 0, NULL, False);
2997  return returnStatus;
2998  }
2999 
3000  if (SDsetattr(sds_id[R],"reflectance_units",DFNT_CHAR8,
3001  (int32)strlen(refl_units),refl_units) == FAIL)
3002  {
3003  returnStatus = MODIS_F_WRITE_ERROR;
3004  sprintf(errmsg, errmsgfmt, "reflectance_units", (long)R);
3005  L1BErrorMsg(location, returnStatus, errmsg,
3006  "SDsetattr", 0, NULL, False);
3007  return returnStatus;
3008  }
3009 
3010  if (SDsetattr(sds_id[R],"corrected_counts_scales",DFNT_FLOAT32,
3011  dim_size[R],scale[counts * sds_dim + R]) == FAIL)
3012  {
3013  returnStatus = MODIS_F_WRITE_ERROR;
3014  sprintf(errmsg, errmsgfmt, "corrected_counts_scales", (long)R);
3015  L1BErrorMsg(location, returnStatus, errmsg,
3016  "SDsetattr", 0, NULL, False);
3017  return returnStatus;
3018  }
3019 
3020  if (SDsetattr(sds_id[R],"corrected_counts_offsets",DFNT_FLOAT32,
3021  dim_size[R],offset[counts * sds_dim + R]) == FAIL)
3022  {
3023  returnStatus = MODIS_F_WRITE_ERROR;
3024  sprintf(errmsg, errmsgfmt, "corrected_counts_offsets", (long)R);
3025  L1BErrorMsg(location, returnStatus, errmsg,
3026  "SDsetattr", 0, NULL, False);
3027  return returnStatus;
3028  }
3029 
3030  if (SDsetattr(sds_id[R],"corrected_counts_units",DFNT_CHAR8,
3031  (int32)strlen(counts_units),counts_units) == FAIL)
3032  {
3033  returnStatus = MODIS_F_WRITE_ERROR;
3034  sprintf(errmsg, errmsgfmt, "corrected_counts_units", (long)R);
3035  L1BErrorMsg(location, returnStatus, errmsg,
3036  "SDsetattr", 0, NULL, False);
3037  return returnStatus;
3038  }
3039  }
3040 
3041  } /*R*/
3042 
3043  return(MODIS_S_OK);
3044 }
3045 
3046 PGSt_SMF_status Create_Band_Subsetting_SDS(L1B_granule_t *L1B_Gran,
3047  boolean skip_night_hi_res)
3048 /*
3049 !C**********************************************************************
3050 !Description: For each of the L1B output granule files, this routine
3051  creates band-subsetting SDSs, writes the
3052  numerical equivalents of the band values and writes
3053  long-name attributes for each. Note that this creates new
3054  SDSs, independent of the Swath data fields (which are
3055  implemented as Vdata, not as SDSs).
3056 
3057 !Input Parameters:
3058  L1B_Gran (->sd_id[]) SD file interface ID for all L1B EV files.
3059  boolean skip_night_hi_res True if and only if all scans are
3060  night mode scans and writing of 250m
3061  and 500m night mode granules has been
3062  turned off
3063 !Output Parameters:
3064  None
3065 
3066 !Revision History:
3067  (continue at top of the file)
3068 
3069  Revision 01.04 January 17, 2002 Razor Issue #171
3070  Improve portability of code to 64-bit mode.
3071  Cast strlen returns to int32 in calls to SDSetattr.
3072  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
3073 
3074  Revision 01.03 November 16, 2001 Razor Issue #169
3075  Added boolean skip_night_hi_res to input parameters and altered logic so that
3076  if skip_night_hi_res is True, output data sets for 250m and 500m resolution
3077  data are not created.
3078  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
3079 
3080  Revision 01.02 Feb 12, 1999
3081  Formed this by including the loop through L1B output files in
3082  Write_Subsetting_SDS and changing the name to an appropriate name.
3083  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
3084 
3085  Revision 01.01 Feb 10, 1999
3086  Made the Band_subsetting_names variable a global at top of file so that the
3087  same names can be used in create Swath. Used the L1B_EV_DIM_NAME variable
3088  for dimension name rather than re-defining it here. Added SDendaccess.
3089  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
3090 
3091  Revision 01.00 1998
3092  Initial development
3093  Zhenying Gu(zgu@ltpmail.gsfc.nasa.gov)
3094 
3095 !Team-unique Header:
3096 
3097 !References and Credits:
3098  This software is developed by the MODIS Characterization Support
3099  Team (MCST)for the National Aeronautics and Space Administration,
3100  Goddard Space Flight Center, under contract NAS5-32373.
3101 
3102  HDF portions developed at the National Center for Supercomputing
3103  Applications at the University of Illinois at Urbana-Champaign.
3104 
3105 !Design Notes:
3106  file index res. # bnd. sub. SDSs
3107  ---------- ------ ---------------
3108  0 250m 1
3109  1 500m 2
3110  2 1km 4
3111 
3112 !END********************************************************************
3113 */
3114 {
3115  PGSt_SMF_status returnStatus;
3116  char *location = "Create_Band_Subsetting_SDS";
3117  int32 f;
3118  int32 hdf_return;
3119  int32 sds_index;
3120  int32 sds_id;
3121  int32 num_sds = 0;
3122  int32 R = 0;
3123  int32 dims[NUM_L1A_RESOLUTIONS] = {2, 5, 15, 16};
3124  float32 data_250m[2] = {1, 2};
3125  float32 data_500m[5] = {3, 4, 5, 6, 7};
3126  float32 data_1km_refl[15] = {8, 9, 10, 11, 12, 13, 13.5, 14, 14.5, 15,
3127  16, 17, 18, 19, 26};
3128  float32 data_1km_emiss[16] = {20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31,
3129  32, 33, 34, 35, 36};
3130  float32 *data[NUM_L1A_RESOLUTIONS];
3131  char *SDS_LongName[NUM_L1A_RESOLUTIONS] =
3132  {
3133  "250M Band Numbers for Subsetting",
3134  "500M Band Numbers for Subsetting",
3135  "1KM Reflective Solar Band Numbers for Subsetting",
3136  "1KM Emissive Band Numbers for Subsetting"
3137  };
3138  int32 evfile_luns[NUM_L1B_EV_FILES] = {
3142  };
3143  char errmsg[256];
3144  int16 start_output_res = INDEX_L1B_250m;
3145 
3146  data[0] = data_250m;
3147  data[1] = data_500m;
3148  data[2] = data_1km_refl;
3149  data[3] = data_1km_emiss;
3150 
3151  /*
3152  * If we are in night mode and we do not wish to write 250m and
3153  * 500m data sets, start with the 1KM output data sets.
3154  */
3155 
3156  if (skip_night_hi_res == True)
3157  start_output_res = INDEX_L1B_1km;
3158  else
3159  start_output_res = INDEX_L1B_250m;
3160 
3161  for (f = start_output_res; f < NUM_L1B_EV_FILES; f++)
3162  {
3163 
3164  num_sds = f + 1;
3165  if (f == INDEX_L1B_1km)
3166  num_sds++;
3167 
3168  for (R = 0; R < num_sds; R++)
3169  {
3170 
3171  returnStatus = write_sds_rank1(L1B_Gran->sd_id[f],
3173  L1B_EV_DIM_NAME[R][0], dims[R],
3174  "float32", data[R]);
3175  if(returnStatus != MODIS_S_OK)
3176  {
3177  L1BErrorMsg(location, returnStatus, NULL,
3178  "write_sds_rank1", evfile_luns[f], NULL, True);
3179  return returnStatus;
3180  }
3181 
3182  sds_index = SDnametoindex(L1B_Gran->sd_id[f],
3184  if(sds_index == FAIL)
3185  {
3186  sprintf(errmsg, "Could not get SDS index of \"%s\".",
3188  returnStatus = MODIS_F_HDF_ERROR;
3189  L1BErrorMsg(location, returnStatus, errmsg,
3190  "SDnametoindex", evfile_luns[f], NULL, True);
3191  return returnStatus;
3192  }
3193 
3194  sds_id = SDselect(L1B_Gran->sd_id[f], sds_index);
3195  if(sds_id == FAIL)
3196  {
3197  sprintf(errmsg, "Could not get SDS ID for \"%s\".",
3199  returnStatus = MODIS_F_HDF_ERROR;
3200  L1BErrorMsg(location, returnStatus, errmsg,
3201  "SDselect", evfile_luns[f], NULL, True);
3202  return returnStatus;
3203  }
3204 
3205  if(SDsetattr(sds_id, "long_name", DFNT_CHAR8,
3206  (int32)strlen(SDS_LongName[R]),
3207  (VOIDP)SDS_LongName[R]) == FAIL)
3208  {
3209  sprintf(errmsg,
3210  "Could not write long_name attribute for SDS \"%s\".",
3212  returnStatus = MODIS_F_WRITE_ERROR;
3213  L1BErrorMsg(location, returnStatus, errmsg,
3214  "SDsetattr", evfile_luns[f], NULL, True);
3215  return returnStatus;
3216  }
3217 
3218  hdf_return = SDendaccess(sds_id);
3219  if (hdf_return == FAIL)
3220  {
3221  sprintf(errmsg, "Could not end access to SDS \"%s\".",
3223  returnStatus = MODIS_F_HDF_ERROR;
3224  L1BErrorMsg(location, returnStatus, errmsg,
3225  "SDendaccess", evfile_luns[f], NULL, True);
3226  return returnStatus;
3227  }
3228 
3229  } /* R */
3230  } /* f */
3231  return(MODIS_S_OK);
3232 }
3233 
3234 PGSt_SMF_status Copy_Geo_SDS (L1B_granule_t *L1B_Gran,
3235  boolean skip_night_hi_res)
3236 
3237 /*
3238 !C****************************************************************
3239 !Description:
3240  Read subsampled SDSs from geolocation file and write those data and
3241  their attributes into the 1km L1B file. For the 250m and 500m L1B
3242  granules, read and write the full geolocation latitude and longitude
3243  SDS (but not others). Only the units, valid_range and fill-value
3244  attributes are written to the 250m and 500m granules. Note that SDSs
3245  have been previously created (in function Create_L1B_Swath), but open
3246  access, read/write, and end access, are performed for both input and
3247  output here.
3248 
3249 !Input Parameters:
3250  L1B_granule_t *L1B_Gran
3251  boolean skip_night_hi_res True if and only if all scans are
3252  night mode scans and writing of 250m
3253  and 500m night mode granules has been
3254  turned off
3255 
3256 !Output Parameters:
3257  L1B_granule_t *L1B_Gran
3258 
3259 !Revision History:
3260  (continue at top of the file)
3261 
3262  Revision 02.14 March 27, 2003 Razor Issue #173
3263  Iinitialized both "attr_name" and "attr_value" to NULL for ANSI-C compliance.
3264  Liqin Tan, SAIC GSO (ltan@saicmodis.com)
3265 
3266  Revision 02.13 November 16, 2001 Razor Issue #169
3267  Added boolean skip_night_hi_res to input parameters and altered logic
3268  so that if skip_night_hi_res is True, output data sets for 250m and
3269  500m resolution data are not created.
3270  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
3271 
3272  Revision 02.12, Feb 22, 1999
3273  Moved calculations of Nadir_Frame ... to Scan_Meta_Cal, deleted
3274  L1B_ScanMeta from argument list since no longer needed.
3275  Jim Rogers (rogers@msct.gsfc.nasa.gov)
3276 
3277  Revision 02.11, Feb 19, 1999
3278  Added SDendaccess for the L1B sds_ids in the loop through 250m and
3279  500m files when writing the lat and long SDSs.
3280  Also, for the geo_sds_id in the 1st loop through isds, the SDendaccess
3281  was moved to be just before the end-loop curly brace (after the loop
3282  through L1B granules).
3283  Jim Rogers (rogers@msct.gsfc.nasa.gov)
3284 
3285  Revision 02.10 Oct. 1997
3286  Modified to copy SDS attributes instead of write.
3287  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
3288 
3289  Revision 02.00 April 1997
3290  Modified to match some changes in data structures.
3291  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
3292 
3293  Revision 01.00 1997/02/23
3294  Initial development
3295  Neal Devine(neal.devine@gsfc.nasa.gov)
3296 
3297 !Team-unique Header:
3298  This software is developed by the MODIS Characterization Support
3299  Team (MCST)for the National Aeronautics and Space Administration,
3300  Goddard Space Flight Center, under contract NAS5-32373.
3301 
3302 !References and Credits:
3303  HDF portions developed at the National Center for Supercomputing
3304  Applications at the University of Illinois at Urbana-Champaign.
3305 
3306 !Design Notes:
3307 
3308 !END********************************************************************
3309 */
3310 {
3311  PGSt_SMF_status returnStatus = MODIS_S_OK;
3312  char *location = "Copy_Geo_SDS";
3313  PGSt_integer Version = 1;
3314  char fname[512];
3315  int32 geo_sd_id = 0;
3316  geo_sds_index_t isds = INDEX_LATITUDE; /*Geo sds index*/
3317  int16 i = 0; /*generic index*/
3318  int32 geo_sds_index = 0; /*Geo sds index in hdf file*/
3319  int32 geo_sds_id = 0;
3320  int32 geo_attr_index = 0;
3321  int32 L1B_sds_index = 0;
3322  int32 L1B_sds_id = 0;
3323  int32 geo_start[2] = {GEO_OFFSET, GEO_OFFSET};
3324  int32 geo_stride[2] = {GEO_STRIDE, GEO_STRIDE};
3325  int32 start[2] = {0, 0};
3326  int32 edge[2] = {0, 0};
3327  intn hdf_return = FAIL;
3328  int32 evfile_luns[NUM_L1B_EV_FILES]
3329  = {
3333  };
3334 
3335  /* these two are used for setting gflags attributes */
3336  char *attr_name = NULL;
3337  char *attr_value = NULL;
3338 
3339 #define MAX_ATTR_NAME_SIZE 26
3340 #define MAX_ATTR_BUFFER_SIZE 72
3341 
3342  /* used in SDattrinfo() */
3343  char attr_name_buffer[MAX_ATTR_NAME_SIZE];
3344 
3345  int32 attr_data_type = 0;
3346  int32 attr_count = 0;
3347  char attr_buffer[MAX_ATTR_BUFFER_SIZE];
3348  float32 *buffer;
3349  buffer = malloc(10 * MAX_NUM_SCANS * EV_1km_FRAMES * sizeof(float32));
3350  char errmsg[256];
3351 
3352 
3353 #define COPY_ATTR(attr_name) \
3354  geo_attr_index = SDfindattr(geo_sds_id, attr_name); \
3355  if (geo_attr_index == FAIL) \
3356  { \
3357  sprintf(errmsg, "Could not get attribute index for \"%s\".", \
3358  attr_name); \
3359  returnStatus = MODIS_F_READ_ERROR; \
3360  L1BErrorMsg(location, returnStatus, errmsg, \
3361  "SDfindattr", GEOLOCATION_FILE, NULL, True); \
3362  return returnStatus; \
3363  } \
3364  hdf_return = SDattrinfo(geo_sds_id, geo_attr_index, attr_name_buffer, \
3365  &attr_data_type, &attr_count); \
3366  if (hdf_return == FAIL) \
3367  { \
3368  sprintf(errmsg, "Could not get attribute info for \"%s\".", \
3369  attr_name); \
3370  returnStatus = MODIS_F_HDF_ERROR; \
3371  L1BErrorMsg(location, returnStatus, errmsg, \
3372  "SDattrinfo", GEOLOCATION_FILE, NULL, True); \
3373  return returnStatus; \
3374  } \
3375  hdf_return = SDreadattr(geo_sds_id, geo_attr_index, \
3376  (void *)attr_buffer); \
3377  if (hdf_return == FAIL) \
3378  { \
3379  sprintf(errmsg, "Could not read attribute \"%s\".", attr_name); \
3380  returnStatus = MODIS_F_READ_ERROR; \
3381  L1BErrorMsg(location, returnStatus, errmsg, \
3382  "SDreadattr", GEOLOCATION_FILE, NULL, True); \
3383  return returnStatus; \
3384  } \
3385  hdf_return = SDsetattr(L1B_sds_id, attr_name, attr_data_type, \
3386  attr_count, (void *)attr_buffer); \
3387  if (hdf_return == FAIL) \
3388  { \
3389  sprintf(errmsg, "Could not write attribute \"%s\".", attr_name); \
3390  returnStatus = MODIS_F_WRITE_ERROR; \
3391  L1BErrorMsg(location, returnStatus, errmsg, \
3392  "SDsetattr", evfile_luns[i], NULL, True); \
3393  return returnStatus; \
3394  }
3395 
3396  /* Get Geoloc file name */
3397 
3398  Version = 1;
3399  if ( PGS_PC_GetReference(GEOLOCATION_FILE, &Version, fname) !=
3400  PGS_S_SUCCESS )
3401  {
3402  returnStatus = MODIS_F_FILE_NOT_FOUND;
3403  L1BErrorMsg(location, returnStatus,
3404  "Could not retrieve file name from PCF.",
3405  "PGS_PC_GetReference", GEOLOCATION_FILE, NULL, True);
3406  return returnStatus;
3407  }
3408 
3409  /* Open geolocation file */
3410 
3411  geo_sd_id = SDstart(fname, DFACC_RDONLY);
3412  if (geo_sd_id == FAIL)
3413  {
3414  returnStatus = MODIS_F_FILE_NOT_OPENED;
3415  L1BErrorMsg(location, returnStatus,
3416  "Could not open file for SD read access.",
3417  "SDstart", GEOLOCATION_FILE,
3418  "The file may be missing, corrupted or "
3419  "not an HDF-4 file.", True);
3420  return returnStatus;
3421  }
3422 
3423  /* loop over all Geo_SDSs. This first loop is for L1B EV 250m
3424  * and EV 500m granules only, so if skip_night_hi_res is True, will not
3425  * be executed.
3426  */
3427 
3428  if (skip_night_hi_res == False)
3429  {
3430  edge[0] = 10 * L1B_Gran->num_scans;
3431  edge[1] = EV_1km_FRAMES ;
3432 
3433  for (isds = INDEX_LATITUDE; isds < INDEX_HEIGHT; isds++)
3434  {
3435  geo_sds_index = SDnametoindex(geo_sd_id, GEO_SDS[isds].src_name);
3436  if (geo_sds_index == FAIL)
3437  {
3438  sprintf(errmsg, "Could not get SDS index of \"%s\".",
3439  GEO_SDS[isds].src_name);
3440  returnStatus = MODIS_F_READ_ERROR;
3441  L1BErrorMsg(location, returnStatus, errmsg,
3442  "SDnametoindex", GEOLOCATION_FILE, NULL, True);
3443  return returnStatus;
3444  }
3445 
3446  geo_sds_id = SDselect(geo_sd_id, geo_sds_index);
3447  if (geo_sds_id == FAIL)
3448  {
3449  sprintf(errmsg, "Could not get SDS ID for \"%s\".",
3450  GEO_SDS[isds].src_name);
3451  returnStatus = MODIS_F_HDF_ERROR;
3452  L1BErrorMsg(location, returnStatus, errmsg,
3453  "SDselect", GEOLOCATION_FILE, NULL, True);
3454  return returnStatus;
3455  }
3456 
3457  hdf_return = SDreaddata(geo_sds_id, start, NULL, edge,
3458  (void *)buffer);
3459  if (hdf_return == FAIL)
3460  {
3461  sprintf(errmsg, "Could not read data for SDS \"%s\".",
3462  GEO_SDS[isds].src_name);
3463  returnStatus = MODIS_F_READ_ERROR;
3464  L1BErrorMsg(location, returnStatus, errmsg,
3465  "SDreaddata", GEOLOCATION_FILE, NULL, True);
3466  return returnStatus;
3467  }
3468 
3469  for (i = INDEX_L1B_250m; i < INDEX_L1B_1km; i++)
3470  {
3471  L1B_sds_index = SDnametoindex(L1B_Gran->sd_id[i],
3472  GEO_SDS[isds].name);
3473  if (L1B_sds_index == FAIL)
3474  {
3475  sprintf(errmsg, "Could not get SDS index of \"%s\".",
3476  GEO_SDS[isds].name);
3477  returnStatus = MODIS_F_HDF_ERROR;
3478  L1BErrorMsg(location, returnStatus, errmsg,
3479  "SDnametoindex", evfile_luns[i], NULL, True);
3480  return returnStatus;
3481  }
3482 
3483  L1B_sds_id = SDselect(L1B_Gran->sd_id[i], L1B_sds_index);
3484  if (L1B_sds_id == FAIL)
3485  {
3486  sprintf(errmsg, "Could not get SDS ID for \"%s\".",
3487  GEO_SDS[isds].name);
3488  returnStatus = MODIS_F_HDF_ERROR;
3489  L1BErrorMsg(location, returnStatus, errmsg,
3490  "SDselect", evfile_luns[i], NULL, True);
3491  return returnStatus;
3492  }
3493 
3494  hdf_return = SDwritedata(L1B_sds_id, start,
3495  NULL, edge, (void *)buffer);
3496  if (hdf_return == FAIL)
3497  {
3498  sprintf(errmsg, "Could not write SDS \"%s\".",
3499  GEO_SDS[isds].name);
3500  returnStatus = MODIS_F_WRITE_ERROR;
3501  L1BErrorMsg(location, returnStatus, errmsg,
3502  "SDwritedata", evfile_luns[i], NULL, True);
3503  return returnStatus;
3504  }
3505 
3506  COPY_ATTR("units");
3507  COPY_ATTR("valid_range");
3508  COPY_ATTR("_FillValue");
3509 
3510  /* Done with this L1B_sds_id
3511  */
3512  hdf_return = SDendaccess(L1B_sds_id);
3513  if (hdf_return == FAIL)
3514  {
3515  sprintf(errmsg, "Could not end access for SDS \"%s\".",
3516  GEO_SDS[isds].name);
3517  returnStatus = MODIS_F_HDF_ERROR;
3518  L1BErrorMsg(location, returnStatus, errmsg,
3519  "SDendaccess", evfile_luns[i], NULL, True);
3520  return returnStatus;
3521  }
3522 
3523  }
3524 
3525  /* End access for this geolocation SDS.
3526  */
3527  hdf_return = SDendaccess(geo_sds_id);
3528  if (hdf_return == FAIL)
3529  {
3530  sprintf(errmsg, "Could not end access for SDS \"%s\".",
3531  GEO_SDS[isds].src_name);
3532  returnStatus = MODIS_F_HDF_ERROR;
3533  L1BErrorMsg(location, returnStatus, errmsg,
3534  "SDendaccess", GEOLOCATION_FILE, NULL, True);
3535  return returnStatus;
3536  }
3537 
3538  } /* for (isds = INDEX_LATITUDE; isds < INDEX_HEIGHT; isds++) */
3539  } /* if (skip_night_hi_res == False) */
3540 
3541  /* Loop through all geolocations SDSs. This loop is for the
3542  * L1B EV 1km granule.
3543  */
3544 
3545  edge[0] = 2 * L1B_Gran->num_scans;
3546  edge[1] = 1 + (EV_1km_FRAMES - 3) / 5;
3547 
3548  for (isds = INDEX_LATITUDE; isds < NUM_GEO_SDS; isds++)
3549  {
3550  /* Open a geo sds */
3551 
3552  geo_sds_index = SDnametoindex(geo_sd_id, GEO_SDS[isds].src_name);
3553  if (geo_sds_index == FAIL)
3554  {
3555  sprintf(errmsg, "Could not get SDS index of \"%s\".",
3556  GEO_SDS[isds].src_name);
3557  returnStatus = MODIS_F_READ_ERROR;
3558  L1BErrorMsg(location, returnStatus, errmsg,
3559  "SDnametoindex", GEOLOCATION_FILE, NULL, True);
3560  return returnStatus;
3561  }
3562 
3563  geo_sds_id = SDselect(geo_sd_id, geo_sds_index);
3564  if (geo_sds_id == FAIL)
3565  {
3566  sprintf(errmsg, "Could not get SDS ID for \"%s\".",
3567  GEO_SDS[isds].src_name);
3568  returnStatus = MODIS_F_HDF_ERROR;
3569  L1BErrorMsg(location, returnStatus, errmsg,
3570  "SDselect", GEOLOCATION_FILE, NULL, True);
3571  return returnStatus;
3572  }
3573 
3574  /* Open an L1B sds */
3575 
3576  L1B_sds_index = SDnametoindex(L1B_Gran->sd_id[INDEX_L1B_1km],
3577  GEO_SDS[isds].name);
3578  if (L1B_sds_index == FAIL)
3579  {
3580  sprintf(errmsg, "Could not get SDS index of \"%s\".",
3581  GEO_SDS[isds].name);
3582  returnStatus = MODIS_F_HDF_ERROR;
3583  L1BErrorMsg(location, returnStatus, errmsg,
3584  "SDnametoindex", evfile_luns[INDEX_L1B_1km], NULL, True);
3585  return returnStatus;
3586  }
3587 
3588  L1B_sds_id = SDselect(L1B_Gran->sd_id[INDEX_L1B_1km], L1B_sds_index);
3589  if (L1B_sds_id == FAIL)
3590  {
3591  sprintf(errmsg, "Could not get SDS ID for \"%s\".",
3592  GEO_SDS[isds].name);
3593  returnStatus = MODIS_F_HDF_ERROR;
3594  L1BErrorMsg(location, returnStatus, errmsg,
3595  "SDselect", evfile_luns[INDEX_L1B_1km], NULL, True);
3596  return returnStatus;
3597  }
3598 
3599  /* Read an sds from geo file into buffer */
3600 
3601  hdf_return = SDreaddata(geo_sds_id, geo_start, geo_stride,
3602  edge, (void *)buffer);
3603  if (hdf_return == FAIL)
3604  {
3605  sprintf(errmsg, "Could not read data for SDS \"%s\".",
3606  GEO_SDS[isds].src_name);
3607  returnStatus = MODIS_F_READ_ERROR;
3608  L1BErrorMsg(location, returnStatus, errmsg,
3609  "SDreaddata", GEOLOCATION_FILE, NULL, True);
3610  return returnStatus;
3611  }
3612 
3613  /* Write the sds stored in the buffer to L1B_1km file */
3614 
3615  hdf_return = SDwritedata(L1B_sds_id, start, NULL, edge, (void *)buffer);
3616  if (hdf_return == FAIL)
3617  {
3618  sprintf(errmsg, "Could not write SDS \"%s\".", GEO_SDS[isds].name);
3619  returnStatus = MODIS_F_WRITE_ERROR;
3620  L1BErrorMsg(location, returnStatus, errmsg,
3621  "SDwritedata", evfile_luns[INDEX_L1B_1km], NULL, True);
3622  return returnStatus;
3623  }
3624 
3625  /*
3626  * Copy attributes:
3627  * copy units, valid_range, _FillValue for all sdss except gflags,
3628  * and scale_factor for all except Latitude and Longitude and gflags
3629  * Set other attributes:
3630  * set line_numbers and frame_numbers for all sdss except gflags
3631  */
3632 
3633  if (isds != INDEX_GFLAGS)
3634  {
3635  i = INDEX_L1B_1km; /* to set correct lun in the macro */
3636  COPY_ATTR("units");
3637  COPY_ATTR("valid_range");
3638  COPY_ATTR("_FillValue");
3639 
3640  if (isds > INDEX_HEIGHT)
3641  {
3642  COPY_ATTR("scale_factor");
3643  }
3644 
3645  hdf_return = SDsetattr(L1B_sds_id, "line_numbers", DFNT_CHAR8,
3646  (int32)strlen("3,8"), (VOIDP)"3,8");
3647  if (hdf_return == FAIL)
3648  {
3649  sprintf(errmsg, "Could not write attribute \"line_numbers\" "
3650  "to SDS \"%s\".",
3651  GEO_SDS[isds].name);
3652  returnStatus = MODIS_F_WRITE_ERROR;
3653  L1BErrorMsg(location, returnStatus, errmsg,
3654  "SDsetattr", evfile_luns[INDEX_L1B_1km], NULL, True);
3655  return returnStatus;
3656  }
3657 
3658  hdf_return = SDsetattr(L1B_sds_id, "frame_numbers", DFNT_CHAR8,
3659  (int32)strlen("3,8,13,..."),
3660  (VOIDP)"3,8,13,...");
3661  if (hdf_return == FAIL)
3662  {
3663  sprintf(errmsg, "Could not write attribute \"frame_numbers\" "
3664  "to SDS \"%s\".",
3665  GEO_SDS[isds].name);
3666  returnStatus = MODIS_F_WRITE_ERROR;
3667  L1BErrorMsg(location, returnStatus, errmsg,
3668  "SDsetattr", evfile_luns[INDEX_L1B_1km],
3669  NULL, True);
3670  return returnStatus;
3671  }
3672  }
3673  else
3674  {
3675  i = INDEX_L1B_1km; /* to set correct lun in the macro */
3676  COPY_ATTR("_FillValue");
3677  for (i = 0; i < 5; i++)
3678  {
3679  switch(i)
3680  {
3681  case 0: attr_name = "Bit 7(MSB)";
3682  attr_value = "1 = invalid input data";
3683  break;
3684  case 1: attr_name = "Bit 6";
3685  attr_value = "1 = no ellipsoid intersection";
3686  break;
3687  case 2: attr_name = "Bit 5";
3688  attr_value = "1 = no valid terrain data";
3689  break;
3690  case 3: attr_name = "Bit 4";
3691  attr_value = "1 = DEM missing or of inferior quality";
3692  break;
3693  case 4: attr_name = "Bit 3";
3694  attr_value = "1 = invalid sensor range";
3695  }
3696  hdf_return = SDsetattr(L1B_sds_id, attr_name, DFNT_CHAR8,
3697  (int32)strlen(attr_value), attr_value);
3698  if (hdf_return == FAIL)
3699  {
3700  sprintf(errmsg,
3701  "Could not write attribute \"%s\" to SDS \"%s\".",
3702  attr_name, GEO_SDS[isds].name);
3703  returnStatus = MODIS_F_WRITE_ERROR;
3704  L1BErrorMsg(location, returnStatus, errmsg,
3705  "SDsetattr", evfile_luns[INDEX_L1B_1km], NULL, True);
3706  return returnStatus;
3707  }
3708  }
3709  }
3710 
3711  /* Done with this geo_sds */
3712 
3713  hdf_return = SDendaccess(geo_sds_id);
3714  if (hdf_return == FAIL)
3715  {
3716  sprintf(errmsg, "Could not end access for SDS \"%s\".",
3717  GEO_SDS[isds].src_name);
3718  returnStatus = MODIS_F_HDF_ERROR;
3719  L1BErrorMsg(location, returnStatus, errmsg,
3720  "SDendaccess", GEOLOCATION_FILE, NULL, True);
3721  return returnStatus;
3722  }
3723 
3724  /* Done with this L1B_sds */
3725 
3726  hdf_return = SDendaccess(L1B_sds_id);
3727  if (hdf_return == FAIL)
3728  {
3729  sprintf(errmsg, "Could not end access for SDS \"%s\".",
3730  GEO_SDS[isds].name);
3731  returnStatus = MODIS_F_HDF_ERROR;
3732  L1BErrorMsg(location, returnStatus, errmsg,
3733  "SDendaccess", evfile_luns[INDEX_L1B_1km], NULL, True);
3734  return returnStatus;
3735  }
3736 
3737  } /* for (isds = INDEX_LATITUDE; isds < NUM_GEO_SDS; isds++) */
3738 
3739  /* Done with the geo file */
3740 
3741  hdf_return = SDend(geo_sd_id);
3742  if (hdf_return == FAIL)
3743  {
3744  returnStatus = MODIS_F_HDF_ERROR;
3745  L1BErrorMsg(location, returnStatus, NULL, "SDend",
3747  "Memory or the disk file must have become corrupted.",
3748  True);
3749  return returnStatus;
3750  }
3751 
3752  free(buffer);
3753 
3754  return(MODIS_S_OK);
3755 }
3756 
3758  L1A_granule_t *L1A_Gran,
3759  L1B_granule_t *L1B_Gran,
3760  L1B_Scan_Metadata_t *L1B_Scan_Meta,
3761  QA_Data_t *QA)
3762 /*
3763 !C****************************************************************
3764 !Description:
3765  This routine assigns members of the L1B_Scan_Meta to be written to
3766  the L1B EV files later in Write_L1B_ScanMeta. Values already
3767  determined are simply assigned while other data, such as telemetry
3768  and SRCA calibration mode, are read in from the L1A granule and
3769  then assigned.
3770 
3771 !Input Parameters:
3772  L1A_granule_t *L1A_Gran
3773  L1B_granule_t *L1B_Gran
3774  QA_Data_t *QA
3775 !Output Parameters:
3776  L1B_Scan_Metadata_t *L1B_Scan_Meta
3777  QA_Data_t *QA
3778 !Revision History:
3779  (continue at top of the file)
3780 
3781  Revision 01.06 October 24, 2003 Razor Issue #196 (formerly Issue #184)
3782  All changes are in the function "Scan_Meta_Cal". Added parameter "tables",
3783  array "Attitude_Angles", and constant "rtod". Moved the code which opens the
3784  geolocation file to just before the Scan-by-Scan loop which sets bit flags.
3785  Added the code which reads "Attitude_Angles" from the geolocation file.
3786  Changed the setting of QA flag bit 1 (Spacecraft Maneuver) so that the code
3787  will check the attitude angles against their threshold angles in the QA LUT.
3788  If any one of them is more than its threshold angle set the "maneuver" bit
3789  for that scan. Added a new "Sci Abnormal" bit (bit 26) which is set when
3790  SS_FR_SCIABNORM was set (the way the "maneuver" flag is originaly set).
3791  Liqin Tan, SAIC GSO (ltan@saicmodis.com)
3792 
3793  Revision 01.05 April 23, 2003
3794  Changed the telemetry mnemonic which determines whether the nadir aperture
3795  door (NAD) is open from "CR_DR_NAD_OPEN" to the equivalent "CR_DR_NAD_CLSD"
3796  mnemonic and altered the L1B code logic to correctly use the new value. It
3797  was discovered that at two different times in the history of the MODIS/Terra
3798  instrument the mnemonic "CR_DR_NAD_OPEN" did not correctly reflect the state
3799  of the NAD, whereas the mnemonic "CR_DR_NAD_CLSD" has been consistently
3800  reliable.
3801  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
3802 
3803  Revision 01.04 March 27, 2003 Razor Issue #173
3804  Enclosed the rows in the initializer of array-of-struct "temp" with braces
3805  for ANSI-C compliance.
3806  Liqin Tan, SAIC GSO (ltan@saicmodis.com)
3807 
3808  Revision 01.03 April 16, 2002 Razor Issue #166
3809  Added leading/trailing granule scan gap to bit QA flags.
3810  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
3811 
3812  Revision 01.02 August 26, 1999
3813  Added checking if the data read from L1A are valid.
3814  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
3815  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
3816 
3817  Revision 01.01 Feb 20, 1999
3818  Fixed some minor bugs. Moved the assignment of nadir frame values into
3819  macro NADIR_FRAME_GEO_VALS. Moved the assignment of nadir frame
3820  latitude and longitude into here from Create_L1B_Swath to have all
3821  these in one place.
3822  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
3823 
3824  Revision 01.00 1998/4/8
3825  Original Development
3826  Zhenying Gu (zgu@gscmail.gsfc.nasa.gov)
3827 
3828 !Team-unique Header:
3829  This software is developed by the MODIS Characterization Support
3830  Team (MCST)for the National Aeronautics and Space Administration,
3831  Goddard Space Flight Center, under contract NAS5-32373.
3832 
3833 !References and Credits:
3834  HDF portions developed at the National Center for Supercomputing
3835  Applications at the University of Illinois at Urbana-Champaign.
3836 
3837 !Design Notes:
3838 
3839 !END********************************************************************
3840 */
3841 {
3842  PGSt_SMF_status returnStatus;
3843  PGSt_integer Version = 1;
3844  int32 geo_sd_id;
3845  char fname[512];
3846  int f = 0;
3847  int S = 0;
3848  int start_scan = 0;
3849  int16 *SRCA_mode;
3850  SRCA_mode = (int16*) malloc(MAX_NUM_SCANS * sizeof(int16));
3851  int16 *i16_buffer;
3852  i16_buffer = (int16*) malloc(10 * MAX_NUM_SCANS * EV_1km_FRAMES * sizeof(int16));
3853  float32 *f32_buffer;
3854  f32_buffer = (float32*) malloc(10 * MAX_NUM_SCANS * EV_1km_FRAMES * sizeof(float32));
3855  int32 buf_index = 0;
3856  float32 *SD_Sun_zenith;
3857  SD_Sun_zenith = (float32*) malloc(MAX_NUM_SCANS * sizeof(float32));
3858  float32 *SD_Sun_Azimuth;
3859  SD_Sun_Azimuth = (float32*) malloc(MAX_NUM_SCANS * sizeof(float32));
3860  float32 Z_MODIS;
3861  char *location = "Scan_Meta_Cal";
3862  char upper_bound_str[20];
3863  typedef float64 Attitude_Angles_t[NUM_ATTITUDE_ANGLES];
3864  Attitude_Angles_t *Attitude_Angles;
3865  Attitude_Angles = (Attitude_Angles_t*) malloc(MAX_NUM_SCANS * sizeof(Attitude_Angles_t));
3866  float32 rtod = 180.0/PGS_PI;
3867 
3868 
3869  enum {
3870  SCAN_SECTOR_ROTATION,
3871  PC_LW_A,
3872  PC_LW_B,
3873  PV_VIS_A,
3874  PV_VIS_B,
3875  PV_NIR_A,
3876  PV_NIR_B,
3877  PV_SW_A,
3878  PV_SW_B,
3879  PV_LW_A,
3880  PV_LW_B,
3881  SDSM_A,
3882  SDSM_B,
3883  RC_CSH,
3884  RC_ISH,
3885  RC_OSH,
3886  BB_HEATER_A,
3887  BB_HEATER_B,
3888  SD_DOOR,
3889  SD_SCREEN,
3890  SCI_ABNORM,
3891  NAD_DOOR,
3892  MACRO_ID,
3893  PCLW_ADC_PRI,
3894  PCLW_ADC_RED,
3895  NUM_FIELD
3896  }i;
3897  struct {
3898  char *vname; /*vdata_name*/
3899  char *fname; /*field_name*/
3900  /*data buffer; all eng_vdata are type of uint16*/
3901  uint16 buffer[MAX_NUM_SCANS];
3902  } temp[NUM_FIELD] = {
3903  /* XG 3/12/2015
3904  * use SET_FR_ENC_DELTA in the field Command Parameters to get the
3905  * sector rotation status
3906  */
3907  /*{"Telemetry Major Cycle 6 of 7", "CS_FR_ENC_DELTA", {0} },*/
3908  {"Command Parameters", "SET_FR_ENC_DELTA", {0} },
3909  {"Telemetry Major Cycle 4A of 7", "CR_PCLWA_ECAL_ON", {0} },
3910  {"Telemetry Major Cycle 4A of 7", "CR_PCLWB_ECAL_ON", {0} },
3911  {"Telemetry Major Cycle 4B of 7", "CR_PVVISA_ECALON", {0} },
3912  {"Telemetry Major Cycle 4B of 7", "CR_PVVISB_ECALON", {0} },
3913  {"Telemetry Major Cycle 4B of 7", "CR_PVNIRA_ECALON", {0} },
3914  {"Telemetry Major Cycle 4B of 7", "CR_PVNIRB_ECALON", {0} },
3915  {"Telemetry Major Cycle 4B of 7", "CR_PVSMA_ECAL_ON", {0} },
3916  {"Telemetry Major Cycle 4B of 7", "CR_PVSMB_ECAL_ON", {0} },
3917  {"Telemetry Major Cycle 4A of 7", "CR_PVLWA_ECAL_ON", {0} },
3918  {"Telemetry Major Cycle 4A of 7", "CR_PVLWB_ECAL_ON", {0} },
3919  {"Telemetry Major Cycle 5B of 7", "CR_SM_SDSM_A_ON", {0} },
3920  {"Telemetry Major Cycle 5B of 7", "CR_SM_SDSM_B_ON", {0} },
3921  {"Telemetry Major Cycle 5A of 7", "CR_RC_CSHTR_ON", {0} },
3922  {"Telemetry Major Cycle 5A of 7", "CR_RC_ISHTR_ON", {0} },
3923  {"Telemetry Major Cycle 5A of 7", "CR_RC_OSHTR_ON", {0} },
3924  {"Telemetry Major Cycle 0 of 7", "CR_BB_A_PWR_ON", {0} },
3925  {"Telemetry Major Cycle 0 of 7", "CR_BB_B_PWR_ON", {0} },
3926  {"Telemetry Major Cycle 3A of 7", "CR_DR_SDD_OPEN", {0} },
3927  {"Telemetry Major Cycle 3A of 7", "CR_DR_SDS_OPEN", {0} },
3928  {"Telemetry Major Cycle 1 of 7", "SS_FR_SCIABNORM", {0} },
3929  {"Telemetry Major Cycle 3A of 7", "CR_DR_NAD_CLSD", {0} },
3930  {"Telemetry Major Cycle All Part 3", "SS_CP_MACRO_ID", {0} },
3931  {"Telemetry Major Cycle 4A of 7" , "CR_PCLW_A_ON", {0} },
3932  {"Telemetry Major Cycle 4A of 7" , "CR_PCLW_B_ON", {0} }
3933  };
3934 
3935 /********************** MACRO NADIR_FRAME_GEO_VALS ************************
3936  For one geolocation SDS, this macro will read the data from the
3937  geolocation SDS (includes all scan lines and all frames) and assign
3938  one value for the nadir frame per scan to an appropriate variable
3939  in L1B_Scan_Meta. "geoname" is a string that is the name of the
3940  geolocation SDS and "var" is the variable to assign values to.
3941  "scalefactor" converts numbers in the SDS to match the units of the
3942  data. The geolocation file should already be open and the variable
3943  geo_sd_id should thus be valid. "buf" is the buffer (either int16
3944  or float 32) that we read data into. Lat and Long use float32, the
3945  others use int16.
3946 ****************************************************************************/
3947 #define NADIR_FRAME_GEO_VALS(geoname,var,scalefactor,buf) \
3948  returnStatus = read_sds_rank2(geo_sd_id, geoname, \
3949  10 * L1A_Gran->num_scans, \
3950  EV_1km_FRAMES, buf); \
3951  if (returnStatus != MODIS_S_OK) \
3952  { \
3953  L1BErrorMsg(location, returnStatus, NULL, \
3954  "read_sds_rank2", GEOLOCATION_FILE, NULL, True); \
3955  return returnStatus; \
3956  } \
3957  for (S = 0; S < L1A_Gran->num_scans; S++) { \
3958  buf_index = (S * 10 + 4) * EV_1km_FRAMES + NADIR_1km_FRAME_NUM - 1; \
3959  var[S] = buf[buf_index] * scalefactor; \
3960  }
3961 
3962  for (i = SCAN_SECTOR_ROTATION; i < NUM_FIELD; i++)
3963  {
3964  returnStatus = read_vdata (L1A_Gran->v_id,
3965  start_scan,
3966  L1A_Gran->num_scans,
3967  temp[i].vname,
3968  temp[i].fname,
3969  (VOIDP)temp[i].buffer);
3970  if (returnStatus != MODIS_S_OK)
3971  {
3972  L1BErrorMsg(location, returnStatus, NULL,
3973  "read_vdata", FIRST_L1A_GRANULE, NULL, True);
3974  return returnStatus;
3975  }
3976 
3977  if (i == MACRO_ID)
3978  strcpy(upper_bound_str, "31");
3979  else if (i == SCAN_SECTOR_ROTATION)
3980  strcpy(upper_bound_str, "16383");
3981  else
3982  strcpy(upper_bound_str, "1");
3983 
3984  returnStatus = Check_Valid_Range(temp[i].fname, DFNT_UINT16,
3985  NULL, upper_bound_str, NULL,
3986  L1A_Gran->num_scans,
3987  (void *) temp[i].buffer);
3988  if (returnStatus != MODIS_S_OK)
3989  {
3990  L1BErrorMsg(location, returnStatus, NULL, "Check_Valid_Range",
3992  return returnStatus;
3993  }
3994  }
3995 
3996 
3997  /*
3998  * Set the SRCA calibration mode based on macro ID. This will be a
3999  * more accurate determination than using the SDS "SRCA calibration
4000  * mode". If the mode is "undetermined", use the electronics
4001  * redundancy vector to determine if the SRCA is actually on or
4002  * off. If ON, then either the macro has not turned on yet or this
4003  * is a special SRCA event (not one of the normal OAs).
4004  */
4005 
4006 
4007  for (S = 0; S < L1A_Gran->num_scans; S++)
4008  {
4009  if (temp[MACRO_ID].buffer[S] == 15 ||
4010  temp[MACRO_ID].buffer[S] == 16 ||
4011  temp[MACRO_ID].buffer[S] == 17)
4012  SRCA_mode[S] = 0; /* Radiometric */
4013  else if (temp[MACRO_ID].buffer[S] == 18 ||
4014  temp[MACRO_ID].buffer[S] == 19 ||
4015  temp[MACRO_ID].buffer[S] == 20 ||
4016  temp[MACRO_ID].buffer[S] == 21)
4017  SRCA_mode[S] = 2; /* Spectral */
4018  else if (temp[MACRO_ID].buffer[S] == 22 ||
4019  temp[MACRO_ID].buffer[S] == 23 ||
4020  temp[MACRO_ID].buffer[S] == 24)
4021  SRCA_mode[S] = 1; /* Spatial */
4022  else
4023  SRCA_mode[S] = 3; /* undetermined */
4024  }
4025 
4026  /* calculate Nadir frame quantities and assign to L1B_Scan_Meta */
4027 
4028  if (PGS_PC_GetReference(GEOLOCATION_FILE, &Version, fname) !=
4029  PGS_S_SUCCESS)
4030  {
4031  returnStatus = MODIS_F_FILE_NOT_FOUND;
4032  L1BErrorMsg(location, returnStatus,
4033  "Could not retrieve file name from PCF.",
4034  "PGS_PC_GetReference", GEOLOCATION_FILE, NULL, True);
4035  return returnStatus;
4036  }
4037 
4038  /* Open geolocation file
4039  */
4040  geo_sd_id = SDstart(fname, DFACC_RDONLY);
4041  if (geo_sd_id == FAIL)
4042  {
4043  returnStatus = MODIS_F_FILE_NOT_OPENED;
4044  L1BErrorMsg(location, returnStatus,
4045  "Could not open file for SD read access.",
4046  "SDstart", GEOLOCATION_FILE,
4047  "The file may be missing, corrupted or "
4048  "not an HDF-4 file.", True);
4049  return returnStatus;
4050  }
4051 
4052  /* Read s/c attitude angles */
4053  returnStatus = read_sds_rank2(geo_sd_id, "attitude_angles",
4054  L1A_Gran->num_scans,
4055  NUM_ATTITUDE_ANGLES, Attitude_Angles);
4056  if (returnStatus != MODIS_S_OK)
4057  {
4058  L1BErrorMsg(location, returnStatus, NULL, "read_sds_rank2",
4060  return returnStatus;
4061  }
4062 
4063  for (S = 0; S < L1A_Gran->num_scans; S++)
4064  {
4065  /* initialize all bits to zero */
4066 
4067  L1B_Scan_Meta->Bit_QA_Flags[S] = 0;
4068 
4069  /* bit 0: Moon within defined limits of SVP */
4070 
4073  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00000001;
4074 
4075  /* bit 1: Spacecraft Maneuver */
4076 
4077  if ( fabs((double) (Attitude_Angles[S][0]))*rtod >
4078  tables->QA.common_QA_tables.roll_threshold_angle ||
4079  fabs((double) (Attitude_Angles[S][1]))*rtod >
4080  tables->QA.common_QA_tables.pitch_threshold_angle ||
4081  fabs((double) (Attitude_Angles[S][2]))*rtod >
4082  tables->QA.common_QA_tables.yaw_threshold_angle )
4083  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00000002;
4084 
4085 
4086  /* bit 2: Sector Rotation */
4087 
4088  if ( temp[SCAN_SECTOR_ROTATION].buffer[S])
4089  {
4090  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00000004;
4091  QA->QA_common.Sector_Rotation[S] = True;
4092  }
4093  else
4094  QA->QA_common.Sector_Rotation[S] = False;
4095 
4096  /* Set QA flag for both PCLW A and B on */
4097  if ( temp[PCLW_ADC_PRI].buffer[S] == 1 && temp[PCLW_ADC_RED].buffer[S] == 1)
4098  {
4100  }
4101  else
4103 
4104  /* bit 3: Negative Radiance Beyond Noise Level, is set in Emissive_Cal. */
4105 
4106  /* bit 4: PC Ecal on */
4107 
4108  if (temp[PC_LW_A].buffer[S] || temp[PC_LW_B].buffer[S])
4109  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00000010;
4110 
4111  /* bit 5: PV Ecal on */
4112 
4113  if (temp[PV_VIS_A].buffer[S] || temp[PV_VIS_B].buffer[S]
4114  || temp[PV_NIR_A].buffer[S] || temp[PV_NIR_B].buffer[S]
4115  || temp[PV_SW_A].buffer[S] || temp[PV_SW_B].buffer[S]
4116  || temp[PV_LW_A].buffer[S] || temp[PV_LW_B].buffer[S])
4117  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00000020;
4118 
4119  /* bit 6: SD Door Open */
4120 
4121  if (temp[SD_DOOR].buffer[S] == 1)
4122  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00000040;
4123 
4124  /* bit 7: SD Screen Down */
4125 
4126  if (temp[SD_SCREEN].buffer[S] == 0)
4127  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00000080;
4128 
4129  /*
4130  * check NAD door open and this will be used in Reflective_Cal
4131  * and Emissive_Cal
4132  */
4133 
4134  if (temp[NAD_DOOR].buffer[S] == 0)
4135  QA->QA_common.NAD_Door_Open[S] = True;
4136  else
4137  {
4138  QA->QA_common.NAD_Door_Open[S] = False;
4139 
4140  /* bit 8: NAD closed. Added by CCR-508. */
4141 
4142  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00000100;
4143  }
4144 
4145  /* bit 9: SDSM on */
4146 
4147  if (temp[SDSM_A].buffer[S] || temp[SDSM_B].buffer[S])
4148  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00000200;
4149 
4150  /* bit 10: Radcooler Heaters On */
4151 
4152  if (temp[RC_CSH].buffer[S] || temp[RC_ISH].buffer[S]
4153  || temp[RC_OSH].buffer[S])
4154  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00000400;
4155 
4156  /*
4157  * bit 11: Day mode bands telemetered at night. Added by CCR-508.
4158  * It is set at the end of this function.
4159  */
4160 
4161  /*
4162  * bit 12: Linear Emissive Calibration.
4163  * The current emissive algorithm is non-linear. So it is not set.
4164  */
4165 
4166  /* bit 13: DC Restore Change. Set in Calculate_DCR_Change() */
4167 
4168  /* bit 14: Unused. */
4169 
4170  /* bit 15: BB Heater on */
4171  if (temp[BB_HEATER_A].buffer[S] || temp[BB_HEATER_B].buffer[S])
4172  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00008000;
4173 
4174  /* bit 16: Missing Leading Granule */
4175 
4177  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00010000;
4178 
4179  /* bit 17: Missing Trailing Granule */
4180 
4182  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00020000;
4183 
4184  /* bit 18, 19: SRCA calibration mode */
4185 
4186  if (SRCA_mode[S] == 2 || SRCA_mode[S] == 3 || SRCA_mode[S] == -1)
4187  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00040000;
4188  if (SRCA_mode[S] == 1 || SRCA_mode[S] == 3 || SRCA_mode[S] == -1)
4189  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00080000;
4190 
4191  /* bit 20: Moon within the SV keep-out box for RSB (any band)*/
4192 
4194  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00100000;
4195 
4196  /* bit 21: Moon within the SV keep-out box for Emissive bands (any band)*/
4197 
4199  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00200000;
4200 
4201  /* bit 22: all SV data are bad for any subsamples, detectors and bands */
4202 
4203  if (QA->QA_refl.all_SV_DN_bad[S] == 1)
4204  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00400000;
4205 
4206  /* bit 23: all BB data are bad for any subsamples, detectors and bands */
4207 
4208  if (QA->QA_refl.all_BB_DN_bad[S] == 1)
4209  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00800000;
4210 
4211  /* bit 24: Leading Granule Scan Gap */
4212 
4214  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x01000000;
4215 
4216  /* bit 25: Trailing Granule Scan Gap */
4217 
4219  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x02000000;
4220 
4221  /* bit 26: Sci Abnormal*/
4222 
4223  if (temp[SCI_ABNORM].buffer[S] == 0)
4224  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x04000000;
4225 
4226  /* bits 27 - 31: Remaining bits reserved for future use */
4227 
4228  }
4229 
4230  /********************************
4231  * Initialize variable values *
4232  ********************************/
4233 
4234  L1B_Scan_Meta->num_scans = L1A_Gran->num_scans;
4235  L1B_Scan_Meta->EV_frames = EV_1km_FRAMES;
4236  L1B_Scan_Meta->Nadir_Frame_Number = NADIR_1km_FRAME_NUM;
4237 
4238  for (S = 0; S < L1A_Gran->num_scans; S++)
4239  {
4240  strcpy(L1B_Scan_Meta->ScanType[S], L1A_Gran->ScanType[S]);
4241  L1B_Scan_Meta->MirrorSide[S] =
4242  L1A_Gran->MirrorSide[S];
4243  L1B_Scan_Meta->EVStartTime_TAIsecond[S] =
4244  L1A_Gran->EVStartTime_TAIsecond[S];
4245  }
4246 
4247  for (f = 0; f< NUM_L1B_EV_FILES; f++)
4248  L1B_Scan_Meta->v_id[f] = L1B_Gran->v_id[f];
4249 
4250  returnStatus = read_sds_rank1(geo_sd_id, "SD Sun azimuth",
4251  L1A_Gran->num_scans, SD_Sun_Azimuth);
4252  if (returnStatus != MODIS_S_OK)
4253  {
4254  L1BErrorMsg(location, returnStatus, NULL, "read_sds_rank1",
4256  return returnStatus;
4257  }
4258 
4259  returnStatus = read_sds_rank1(geo_sd_id, "SD Sun zenith",
4260  L1A_Gran->num_scans, SD_Sun_zenith);
4261  if (returnStatus != MODIS_S_OK)
4262  {
4263  L1BErrorMsg(location, returnStatus, NULL, "read_sds_rank1",
4265  return returnStatus;
4266  }
4267 
4268  /*
4269  * Validation of the SWIR out-of-band correction algorithm requires
4270  * the collection of reflective band data at night. In this case, the
4271  * scan type is "Day", even it is really night. The following calculation
4272  * determines the MODIS nadir pixel sees day or night. If it is night and
4273  * the scan type is "Day", set bit 11 to 1. See MCST internal memo "How
4274  * To Determine Whether the MODIS Nadir Pixel Seeds Day Or Night" by
4275  * Joe Esposito and Bruce Berriman, Nov 1, 1999 (Draft) and CCR-508.
4276  */
4277 
4278  /*
4279  * The SD sun zenith and azimuth angles in the MOD03 file are in radians.
4280  */
4281 
4282  for (S = 0; S < L1A_Gran->num_scans; S++)
4283  {
4284  Z_MODIS = - 0.34582 * sin((double)SD_Sun_zenith[S]) *
4285  cos((double)SD_Sun_Azimuth[S]) +
4286  0.923830 * cos((double)SD_Sun_zenith[S]);
4287 
4288  /* bit 11: Day mode bands telemetered at night */
4289 
4290  if (Z_MODIS > 0 && strcmp(L1A_Gran->ScanType[S], "Day") == 0)
4291  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00000800;
4292  }
4293 
4294  NADIR_FRAME_GEO_VALS("SolarAzimuth",
4295  L1B_Scan_Meta->Nadir_Frame_Solar_Azimuth,
4297 
4298  NADIR_FRAME_GEO_VALS("SolarZenith",
4299  L1B_Scan_Meta->Nadir_Frame_Solar_Zenith,
4301 
4302  NADIR_FRAME_GEO_VALS("Latitude",
4303  L1B_Scan_Meta->Nadir_Frame_Latitude,
4304  1.0,f32_buffer);
4305 
4306  NADIR_FRAME_GEO_VALS("Longitude",
4307  L1B_Scan_Meta->Nadir_Frame_Longitude,
4308  1.0,f32_buffer);
4309 
4310  if (SDend(geo_sd_id) == FAIL)
4311  {
4312  returnStatus = MODIS_F_HDF_ERROR;
4313  L1BErrorMsg(location, returnStatus, NULL, "SDend",
4315  "Memory or the disk file must have become corrupted.",
4316  True);
4317  return returnStatus;
4318  }
4319 
4320  free(SRCA_mode);
4321  free(i16_buffer);
4322  free(f32_buffer);
4323  free(SD_Sun_zenith);
4324  free(SD_Sun_Azimuth);
4325  free(Attitude_Angles);
4326 
4327  return(MODIS_S_OK);
4328 }
4329 
4330 PGSt_SMF_status Calculate_DCR_Change(L1A_granule_t *L1A_Gran,
4331  QA_Data_t *QA,
4332  L1B_Scan_Metadata_t *L1B_Scan_Meta)
4333 /*
4334 !C****************************************************************
4335 !Description: Read in the DCR offset values of the last scan in
4336  leading granule and all the DCR values of L1A granule.
4337  Compare the DCR values of the current scan with the
4338  same ones in previous scan. Set DCR changes to 1, if
4339  they are different. Otherwise set them to 0.
4340 
4341 !Input Parameters:
4342  L1A_granule_t *L1A_Gran
4343 !Output Parameters:
4344  QA_Data_t *QA
4345 
4346 !Revision History:
4347  (continue at top of the file)
4348 
4349  Revision 01.02 8/26/1999
4350  Added checking if the dcr offset values are valid.
4351  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
4352 
4353  Revision 01.01 1/26/1999
4354  Two minor bug fixes. Move DCR_550 = 0 into loop through scans,
4355  change the last "or" to an "and".
4356  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
4357 
4358  Revision 01.00 1/26/1999
4359  Original Development
4360  Zhenying Gu (zgu@gscmail.gsfc.nasa.gov)
4361 
4362 !Team-unique Header:
4363  This software is developed by the MODIS Characterization Support
4364  Team (MCST)for the National Aeronautics and Space Administration,
4365  Goddard Space Flight Center, under contract NAS5-32373.
4366 
4367 !References and Credits:
4368  The time setting code was borrowed from Paul Fishers timea.c
4369 
4370  HDF portions developed at the National Center for Supercomputing
4371  Applications at the University of Illinois at Urbana-Champaign.
4372 
4373 !Design Notes:
4374 
4375 !END********************************************************************
4376 */
4377 
4378 {
4379  PGSt_SMF_status returnStatus;
4380  int32 S, B, B_emiss, D, D_1km, num_scans;
4381  int32 DCR_550;
4382  int32 file_id;
4383  int16 flag = 0;
4384  int8 Leading_DCR_offset[NUM_DCR_VALUE];
4385  typedef int8 DCR_offset_t[NUM_DCR_VALUE];
4386  DCR_offset_t *DCR_offset;
4387  DCR_offset = (DCR_offset_t*) malloc(MAX_NUM_SCANS * sizeof(DCR_offset_t));
4388  typedef int8 XDCR_offset_t[NUM_DCR_VALUE];
4389  XDCR_offset_t *XDCR_offset;
4390  XDCR_offset = (XDCR_offset_t*) malloc((MAX_NUM_SCANS + 1) * sizeof(XDCR_offset_t));
4391  PGSt_integer Version = 1;
4392  char file_name[PGSd_PC_FILE_PATH_MAX];
4393  char *location = "Calculate_DCR_Change";
4394 
4395  /* Read DCR_offset from the last scan of the leading granule, if present */
4396 
4398  returnStatus = PGS_PC_GetReference (LEADING_L1A_GRANULE,
4399  &Version, file_name);
4400  if (returnStatus != PGS_S_SUCCESS)
4401  {
4402  returnStatus = MODIS_F_FILE_NOT_FOUND;
4403  L1BErrorMsg(location, returnStatus,
4404  "Could not retrieve file name from PCF.",
4405  "PGS_PC_GetReference", LEADING_L1A_GRANULE, NULL, True);
4406  return returnStatus;
4407  }
4408 
4409  /* Open file */
4410 
4411  file_id = SDstart(file_name, DFACC_RDONLY); /*for sds interfaces*/
4412  if (file_id == FAIL)
4413  {
4414  returnStatus = MODIS_F_FILE_NOT_OPENED;
4415  L1BErrorMsg(location, returnStatus,
4416  "Could not open file for SD read access.",
4417  "SDstart", LEADING_L1A_GRANULE,
4418  "The file may be missing, corrupted or "
4419  "not an HDF-4 file.", True);
4420  return returnStatus;
4421  }
4422 
4423  returnStatus = read_attribute (file_id, "Number of Scans",
4424  DFNT_INT32, (void *)&num_scans);
4425  if (returnStatus != MODIS_S_OK)
4426  {
4427  L1BErrorMsg(location, returnStatus,
4428  "Could not read Number of Scans.",
4429  "read_attribute", LEADING_L1A_GRANULE,
4431  return returnStatus;
4432  }
4433 
4434  returnStatus = read_part_sds_rank2 (file_id,
4435  "fpa_dcr_offset",
4436  num_scans - 1,
4437  0,
4438  1,
4439  NUM_DCR_VALUE,
4440  Leading_DCR_offset);
4441  if (returnStatus != MODIS_S_OK)
4442  {
4443  L1BErrorMsg(location, returnStatus,
4444  "Could not read fpa_dcr_offset.",
4445  "read_part_sds_rank2", LEADING_L1A_GRANULE,
4447  return returnStatus;
4448  }
4449 
4450  if (SDend(file_id) == FAIL)
4451  {
4452  returnStatus = MODIS_F_HDF_ERROR;
4453  L1BErrorMsg(location, returnStatus, NULL, "SDend",
4455  "Memory or the disk file must have become "
4456  "corrupted.", True);
4457  return returnStatus;
4458  }
4459 
4460  }
4461 
4462  /* Read DCR_offset from all scans of the middle granule */
4463 
4464  returnStatus = read_sds_rank2(L1A_Gran->sd_id, "fpa_dcr_offset",
4465  L1A_Gran->num_scans,
4466  NUM_DCR_VALUE, DCR_offset);
4467  if (returnStatus != MODIS_S_OK)
4468  {
4469  L1BErrorMsg(location, returnStatus,
4470  "Could not read fpa_dcr_offset.",
4471  "read_sds_rank2", FIRST_L1A_GRANULE,
4473  return returnStatus;
4474  }
4475 
4476  /* Place data in the XDCR_offset array. If the leading granule
4477  * is missing, use the values from the first scan of the
4478  * middle granule to begin the XDCR array.
4479  */
4480 
4482  for(DCR_550 = 0; DCR_550 < NUM_DCR_VALUE; DCR_550++)
4483  XDCR_offset[0][DCR_550] = Leading_DCR_offset[DCR_550];
4484  }
4485  else {
4486  for(DCR_550 = 0; DCR_550 < NUM_DCR_VALUE; DCR_550++)
4487  XDCR_offset[0][DCR_550] = DCR_offset[0][DCR_550];
4488  }
4489 
4490  for(S = 0; S < L1A_Gran->num_scans; S++) {
4491  for(DCR_550 = 0; DCR_550 < NUM_DCR_VALUE; DCR_550++)
4492  XDCR_offset[S+1][DCR_550] = DCR_offset[S][DCR_550];
4493  }
4494 
4495  for(S = 0; S < L1A_Gran->num_scans; S++)
4496  {
4497  DCR_550 = 0;
4498  flag = 0;
4499 
4500  for(D_1km = 0; D_1km < DETECTORS_PER_1KM_BAND; D_1km++)
4501  {
4502  for(B = 0; B < NUM_250M_BANDS; B++)
4503  {
4504  for(D = 0; D < BAND_RATIO_AT_RES[INDEX_250M]; D++, DCR_550++)
4505  {
4506  if(XDCR_offset[S+1][DCR_550] == XDCR_offset[S][DCR_550])
4508  [S][B][(DETECTORS_PER_1KM_BAND - D_1km) * 4 - D - 1] = 0;
4509  else
4510  {
4512  [S][B][(DETECTORS_PER_1KM_BAND - D_1km) * 4 - D - 1] = 1;
4513  flag = 1;
4514  }
4515  }
4516  }
4517 
4518  for(B = 0; B < NUM_500M_BANDS; B++)
4519  {
4520  for(D = 0; D < BAND_RATIO_AT_RES[INDEX_500M]; D++, DCR_550++)
4521  {
4522  if(XDCR_offset[S+1][DCR_550] == XDCR_offset[S][DCR_550])
4524  [S][B][(DETECTORS_PER_1KM_BAND -D_1km) * 2 - D - 1] = 0;
4525  else
4526  {
4528  [S][B][(DETECTORS_PER_1KM_BAND -D_1km) * 2 - D - 1] = 1;
4529  flag = 1;
4530  }
4531  }
4532  }
4533 
4534  for(B = 0; B < NUM_1000M_REFL_BANDS - 1; B++, DCR_550++)
4535  {
4536  if(XDCR_offset[S+1][DCR_550] == XDCR_offset[S][DCR_550])
4538  [S][B][DETECTORS_PER_1KM_BAND - D_1km - 1] = 0;
4539  else
4540  {
4542  [S][B][DETECTORS_PER_1KM_BAND - D_1km - 1] = 1;
4543  flag = 1;
4544  }
4545  }
4546 
4547  B_emiss = 0;
4548  for(B = 0; B <= NUM_EMISSIVE_BANDS; B++, DCR_550++)
4549  {
4550  if(B < BAND31)
4551  {
4552  if(B == BAND26)
4553  {
4554  if(XDCR_offset[S+1][DCR_550] == XDCR_offset[S][DCR_550])
4556  [S][NUM_1000M_REFL_BANDS - 1]
4557  [DETECTORS_PER_1KM_BAND - D_1km - 1] = 0;
4558  else
4559  {
4561  [S][NUM_1000M_REFL_BANDS - 1]
4562  [DETECTORS_PER_1KM_BAND - D_1km - 1] = 1;
4563  flag = 1;
4564  }
4565  continue;
4566  }
4567 
4568  if(XDCR_offset[S+1][DCR_550] == XDCR_offset[S][DCR_550])
4570  [S][B_emiss][DETECTORS_PER_1KM_BAND - D_1km - 1] = 0;
4571  else
4572  {
4574  [S][B_emiss][DETECTORS_PER_1KM_BAND - D_1km - 1] = 1;
4575  flag = 1;
4576  }
4577  }
4578 
4579  else
4580  {
4581  if(XDCR_offset[S+1][DCR_550] == XDCR_offset[S][DCR_550] &&
4582  XDCR_offset[S+1][DCR_550 + 1] == XDCR_offset[S][DCR_550 + 1])
4584  [S][B_emiss][DETECTORS_PER_1KM_BAND - D_1km - 1] = 0;
4585  else
4586  {
4588  [S][B_emiss][DETECTORS_PER_1KM_BAND - D_1km - 1] = 1;
4589  flag = 1;
4590  }
4591  DCR_550++;
4592  }
4593 
4594  B_emiss++;
4595  }
4596  }/*end D_1km */
4597 
4598  if (flag == 1)
4599  L1B_Scan_Meta->Bit_QA_Flags[S] |= 0x00002000;
4600  }/*end S */
4601 
4602  free(DCR_offset);
4603  free(XDCR_offset);
4604 
4605  return(returnStatus);
4606 }
4607 
4608 PGSt_SMF_status Init_QA_Parameters (L1A_granule_t *L1A_Gran,
4609  L1B_granule_t *L1B_Gran,
4610  QA_Data_t *QA)
4611 /*
4612 !C**********************************************************************
4613 !Description:
4614  This routine initializes the QA values of total numbr of pixels, number of
4615  valid pixels, number of saturated pixels, number of missing pixels and
4616  pixels representing negative values below noise. Initially, all pixels
4617  are assumed to be valid. Then it checks missing scans. If there is missing
4618  scan, the function update these values and set bad data flag to be true.
4619  Later, in Emissive_Cal and Reflective_Cal, these values will be adjusted
4620  on a pixel by pixel basis if some values are determined to be missing,
4621  saturated, etc.
4622 
4623 !Input Parameters:
4624  L1A_granule_t *L1A_Gran contains L1A granule sd_id and scan type and
4625  scan quality array
4626  L1B_granule_t *L1B_Gran contains number scans and number day mode scans
4627 
4628 !Output Parameters:
4629  L1B_granule_t *L1B_Gran contains number of total pixels, missing pixels,
4630  valid pixels, saturate pixels, negative value
4631  below noise level pixels and bad data flag for
4632  each band
4633 
4634  QA_Data_t *QA contains QA data such as number of missing scans,
4635  number of dead detector EV data, number of sector
4636  rotation EV data, etc.
4637 
4638 !Revision History:
4639  (continue at top of the file)
4640 
4641  Revision 01.04 February 7, 2002 Razor Issue 180
4642  Added counting num_b1_lt_0
4643  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
4644 
4645  Revision 01.03 October 29, 2000
4646  The missing scans are now flagged in an array in L1A_Gran, Razor issue 142.
4647  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
4648 
4649  Revision 01.02 September 21, 2000
4650  Added counting num_rsb_at_night_scans as per Razor issue 137.
4651  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
4652 
4653  ... (many changes not logged) ...
4654 
4655  Revision 01.01 Nov. 16, 1999
4656  Added checking missing scans and consequentially update the QA parameters
4657  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
4658 
4659  Revision 01.00 Oct. 1997
4660  Initial development
4661  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
4662 
4663 !Team-unique Header:
4664  This software is developed by the MODIS Characterization Support
4665  Team (MCST)for the National Aeronautics and Space Administration,
4666  Goddard Space Flight Center, under contract NAS5-32373.
4667 
4668 !References and Credits:
4669  HDF portions developed at the National Center for Supercomputing
4670  Applications at the University of Illinois at Urbana-Champaign.
4671 
4672 !Design Notes:
4673 
4674 !END********************************************************************
4675 */
4676 {
4677  int16 B = 0; /* band index within L1A resolution */
4678  int16 B_38 = 0;
4679  int16 D_490 = 0; /* detector index within set of MODIS bands (0-489) */
4680  int16 R = 0;
4681  int16 S = 0; /* scan index */
4682 
4683  QA->QA_common.num_missing_scans = 0;
4685  for(D_490 = 0; D_490 < NUM_DETECTORS; D_490++)
4686  {
4687  QA->QA_common.num_missing_data_in_scans[D_490] = 0;
4688  QA->QA_common.num_dead_detector_EV_data[D_490] = 0;
4689  QA->QA_common.num_sector_rotation_EV_data[D_490] = 0;
4690  QA->QA_common.num_saturated_EV_data[D_490] = 0;
4691  QA->QA_common.num_no_bg_DN_EV_data[D_490] = 0;
4692  QA->QA_common.num_moon_in_SVP_TEB_EV_data[D_490] = 0;
4694  QA->QA_common.num_exceed_max_for_scaling[D_490] = 0;
4696  QA->QA_common.num_negative_b1[D_490] = 0;
4697  if(D_490 < NUM_HIGH_RESOLUTION_DETECTORS)
4698  QA->QA_common.num_dead_subframe_EV_data[D_490] = 0;
4699  }
4700 
4701  for (R = 0; R < NUM_L1A_RESOLUTIONS; R++)
4702  for (B = 0; B < L1A_BANDS_AT_RES[R]; B++, B_38++)
4703  {
4704  if (R != INDEX_1000M_EMISS || B_38 == MODIS_BAND26_INDEX)
4705  {
4706  L1B_Gran->valid_pixels[B_38] = L1B_Gran->num_day_scans *
4708  BAND_RATIO_AT_RES[R] *
4709  EV_1km_FRAMES;
4710  }
4711  else
4712  {
4713  L1B_Gran->valid_pixels[B_38] = L1B_Gran->num_scans *
4715  BAND_RATIO_AT_RES[R] *
4716  EV_1km_FRAMES;
4717  }
4718 
4719 /************************* Begin Band 26 Section **************************/
4720 #ifdef WRITE_BAND_26_SDS
4721  /*
4722  * This resets the number of valid pixels for band 26 to
4723  * include all scans, both day and night.
4724  */
4725  if (B_38 == MODIS_BAND26_INDEX)
4726  L1B_Gran->valid_pixels[B_38] = L1B_Gran->num_scans *
4729 #endif /* WRITE_BAND_26_SDS */
4730 /************************** End Band 26 Section ***************************/
4731 
4732  L1B_Gran->total_pixels[B_38] =
4733  L1B_Gran->num_scans *
4736  L1B_Gran->saturated_pixels[B_38] = 0;
4737  L1B_Gran->missing_pixels[B_38] =
4738  L1B_Gran->total_pixels[B_38] -
4739  L1B_Gran->valid_pixels[B_38];
4740  L1B_Gran->negative_value_below_noise_pixels[B_38] = 0;
4741  L1B_Gran->interpolated_pixels[B_38] = 0;
4742  L1B_Gran->dead_detector_pixels[B_38] = 0;
4743  L1B_Gran->dead_subframe_pixels[B_38] = 0;
4744  L1B_Gran->bad_data_flag[B_38] = 0;
4745  }
4746 
4747  /*
4748  * Adjust qa counter variables for scans that are completely missing.
4749  */
4750 
4751  for (S = 0; S < L1B_Gran->num_scans; S++)
4752  {
4753  if (L1A_Gran->missing_scan[S] == True)
4754  {
4755  B_38 = 0;
4756  for (R = 0; R < NUM_L1A_RESOLUTIONS; R++)
4757  for (B = 0; B < L1A_BANDS_AT_RES[R]; B++, B_38++)
4758  {
4759  if (strcmp(L1A_Gran->ScanType[S], "Day") == SAME ||
4760  (R == INDEX_1000M_EMISS && B_38 != MODIS_BAND26_INDEX))
4761  {
4762  L1B_Gran->missing_pixels[B_38] +=
4765  L1B_Gran->valid_pixels[B_38] -=
4768  }
4769 /************************* Begin Band 26 Section **************************/
4770 #ifdef WRITE_BAND_26_SDS
4771 
4772  /*
4773  * If WRITE_BAND_26_SDS is defined, the valid pixels for band 26
4774  * is computed based on the number of all scans. So, if the scan
4775  * is missing, number of the missing pixels and valid pixels should
4776  * be recalculated even if the scan is in night mode.
4777  */
4778 
4779  else if (B_38 == MODIS_BAND26_INDEX)
4780  {
4781  L1B_Gran->missing_pixels[B_38] +=
4784  L1B_Gran->valid_pixels[B_38] -=
4787  }
4788 
4789 #endif /* WRITE_BAND_26_SDS */
4790 /************************** End Band 26 Section ***************************/
4791 
4792  L1B_Gran->bad_data_flag[B_38] = 1;
4793  }
4795  }
4796  }
4797 
4798  return MODIS_S_OK;
4799 }
4800 
4801 PGSt_SMF_status Write_L1B_ScanMeta (L1B_Scan_Metadata_t *L1B_Scan_Meta,
4802  L1A_granule_t *L1A_Gran,
4803  QA_Data_t *QA,
4804  boolean skip_night_hi_res)
4805 /*
4806 !C**************************************************************************
4807 !Description: This routine writes level 1B scan metadata into EV files and
4808  also writes bit QA flags into OBC file.
4809 
4810 !Input Parameters:
4811  L1B_Scan_Metadata_t *L1B_Scan_Meta contains L1A scan metadata
4812  L1A_granule_t *L1A_Gran contains number of scans, v_id
4813  and scan quality array
4814  QA_Data_t *QA contains number of thermistor
4815  outliers
4816  boolean skip_night_hi_res True if and only if all scans are
4817  night mode scans and writing of 250m
4818  and 500m night mode granules has been
4819  turned off
4820 
4821 !Output Parameters:
4822  none
4823 !Revision History:
4824  (continue at top of the file)
4825 
4826  Revision 02.20 March 27, 2003 Razor Issue #173
4827  Enclosed the rows in the initializer of array-of-struct "vd_field" with braces
4828  for ANSI-C compliance.
4829  Liqin Tan, SAIC GSO (ltan@saicmodis.com)
4830 
4831  Revision 02.19 November 19, 2001 Razor Issue #169
4832  Added boolean skip_night_hi_res to input parameters and altered logic
4833  so that if skip_night_hi_res is True, output data sets for 250m and
4834  500m resolution data are not created.
4835  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
4836 
4837  Revision 02.18 September 30, 1999
4838  The structure member "num_thermistor_outliers" is now indexed thorugh scan.
4839  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
4840 
4841  Revision 02.17 August 1999
4842  Added checking if the scan quality array data are valid in L1A file.
4843  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
4844 
4845  Revision 02.16 May 1999
4846  Wrote bit QA flags into OBC file also
4847  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
4848  Zhenying Gu(zgu@mcst.gsfc.nasa.gov)
4849 
4850  Revision 02.00 April 1997
4851  Combined V_Data_Create & Write_L1B_ScanMeta of version 1.
4852  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
4853 
4854  Revision 01.01 1996/04/05
4855  Update to match Version 1 Design Document
4856  Neal Devine(devine@ltpmail.gsfc.nasa.gov)
4857  John Hannon(hannon@highwire.gsfc.nasa.gov)
4858  Joan Baden (baden@highwire.gsfc.nasa.gov)
4859 
4860  Revision 01.00 1993
4861  Initial development
4862  Geir E. Kvaran(geir@highwire.gsfc.nasa.gov)
4863 
4864 !Team-unique Header:
4865 
4866 !References and Credits:
4867  This software is developed by the MODIS Characterization Support
4868  Team (MCST)for the National Aeronautics and Space Administration,
4869  Goddard Space Flight Center, under contract NAS5-32373.
4870 
4871  HDF portions developed at the National Center for Supercomputing
4872  Applications at the University of Illinois at Urbana-Champaign.
4873 
4874 !Design Notes:
4875 
4876 !END********************************************************************
4877 */
4878 {
4879  PGSt_SMF_status returnStatus = MODIS_S_OK;
4880  char *location = "Write_L1B_ScanMeta";
4881  PGSt_integer Version = 1;
4882  int16 f = 0; /*L1B_file index (0,2)*/
4883  int16 i = 0; /*vdata field index*/
4884  int32 S = 0; /*Scan index*/
4885  int16 num_fields = 14;
4886  int32 vd_id = 0;
4887  int32 list_len = 0;
4888  char *list = NULL;
4889  int32 scan_number = 0;
4890  int32 complete_scan_flag = 0;
4891  char8 scan_type[4] = {' ', ' ', ' ', ' '};
4892  int32 mirror_side = 0;
4893  int32 EV_frames = 0;
4894  int32 nadir_frame = 0;
4895  float32 nadir_frame_latitude = 0;
4896  float32 nadir_frame_longitude = 0;
4897  float32 nadir_frame_solar_azimuth = 0;
4898  float32 nadir_frame_solar_zenith = 0;
4899  int32 BB_thermistor_outliers = 0;
4900  uint32 bit_QA_flags = 0;
4901  uint16 sector_rotation_dn[MAX_NUM_SCANS];
4902  float32 sector_rotation_angle;
4903  char buffer[64];
4904  char *buffer_ptr;
4905  int32 obc_file_id;
4906  intn hdf_return;
4907  char file_name[512];
4908  struct { char *name; int32 type; int32 order; } vd_field[14] =
4909  {
4910  {"Scan Number" , DFNT_INT32 , 1},
4911  {"Complete Scan Flag" , DFNT_INT32 , 1},
4912  {"Scan Type" , DFNT_CHAR8 , 4},
4913  {"Mirror Side" , DFNT_INT32 , 1},
4914  {"EV Sector Start Time" , DFNT_FLOAT64, 1},
4915  {"EV_Frames" , DFNT_INT32 , 1},
4916  {"Nadir_Frame_Number" , DFNT_INT32 , 1},
4917  {"Latitude of Nadir Frame" , DFNT_FLOAT32, 1},
4918  {"Longitude of Nadir Frame" , DFNT_FLOAT32, 1},
4919  {"Solar Azimuth of Nadir Frame" , DFNT_FLOAT32, 1},
4920  {"Solar Zenith of Nadir Frame" , DFNT_FLOAT32, 1},
4921  {"No. OBC BB thermistor outliers" , DFNT_INT32 , 1},
4922  {"Bit QA Flags" , DFNT_UINT32 , 1},
4923  {"Sector Rotation Angle" , DFNT_FLOAT32, 1}
4924  };
4925  int32 evfile_luns[NUM_L1B_EV_FILES] =
4926  {
4930  };
4931  int16 start_output_res = INDEX_L1B_250m;
4932 
4933 #define PACK_MEMBER(member, buffer_ptr) \
4934 memcpy(buffer_ptr, (void *)&member, sizeof(member)); \
4935 buffer_ptr += sizeof(member)
4936 
4937  if (skip_night_hi_res == True)
4938  start_output_res = INDEX_L1B_1km;
4939  else
4940  start_output_res = INDEX_L1B_250m;
4941 
4942  for (f = start_output_res; f < NUM_L1B_EV_FILES; f++)
4943  {
4944 
4945  /*create a new v_data*/
4946 
4947  if ((vd_id = VSattach(L1B_Scan_Meta->v_id[f],-1,"w")) == FAIL)
4948  {
4949  returnStatus = MODIS_F_HDF_ERROR;
4950  L1BErrorMsg(location, returnStatus,
4951  "Could not attach to vdata for writing Level "
4952  "1B Swath Metadata",
4953  "VSattach", evfile_luns[f], NULL, True);
4954  return returnStatus;
4955  }
4956 
4957  /*give it a name*/
4958 
4959  if (VSsetname(vd_id,"Level 1B Swath Metadata") == FAIL)
4960  {
4961  returnStatus = MODIS_F_HDF_ERROR;
4962  L1BErrorMsg(location, returnStatus,
4963  "Could not create vdata name for writing "
4964  "Level 1B Swath Metadata",
4965  "VSsetname", evfile_luns[f], NULL, True);
4966  return returnStatus;
4967  }
4968 
4969  /*define and set fields of the v_data*/
4970 
4971  list_len = 0;
4972  for (i = 0; i < num_fields; i++)
4973  {
4974  if (VSfdefine(vd_id,
4975  vd_field[i].name,
4976  vd_field[i].type,
4977  vd_field[i].order) == FAIL)
4978  {
4979  char errmsg[256];
4980  if (vd_field[i].name)
4981  sprintf(errmsg,
4982  "Could not define vdata field for \"%s\".",
4983  vd_field[i].name);
4984  else
4985  strcpy(errmsg, "Could not define vdata field -- name is NULL.");
4986  returnStatus = MODIS_F_HDF_ERROR;
4987  L1BErrorMsg(location, returnStatus, errmsg,
4988  "VSfdefine", evfile_luns[f], NULL, True);
4989  return returnStatus;
4990  }
4991 
4992  /*total num of char's in all names*/
4993  list_len += strlen(vd_field[i].name);
4994  }
4995 
4996  /*allocate memory for char's & commas & \0*/
4997  list = (char *)malloc((list_len + num_fields + 1) * sizeof(char));
4998  if (!list)
4999  {
5000  returnStatus = MODIS_F_OUT_OF_MEMORY;
5001  L1BErrorMsg(location, returnStatus, NULL, "malloc", 0, NULL, True);
5002  return returnStatus;
5003  }
5004 
5005  /* Initialize list */
5006 
5007  list[0] = '\0';
5008 
5009  /*Append names and commas*/
5010 
5011  for (i = 0; i < num_fields - 1; i++)
5012  {
5013  strcat(list,vd_field[i].name);
5014  strcat(list,",");
5015  }
5016 
5017  /*Last name is not followed by a comma*/
5018 
5019  strcat(list,vd_field[i].name);
5020 
5021  /*set fields*/
5022 
5023  if (VSsetfields(vd_id,list) == FAIL)
5024  {
5025  returnStatus = MODIS_F_HDF_ERROR;
5026  L1BErrorMsg(location, returnStatus, NULL,
5027  "VSsetfields", evfile_luns[f], NULL, True);
5028  return returnStatus;
5029  }
5030 
5031  /* read sector rotation dn */
5032 
5033  /* XG 3/12/2015
5034  * use SET_FR_ENC_DELTA from "Command Parameters" field for sector rotation status
5035  */
5036  /*
5037  returnStatus = read_vdata(L1A_Gran->v_id, 0,
5038  L1B_Scan_Meta->num_scans,
5039  "Telemetry Major Cycle 6 of 7",
5040  "CS_FR_ENC_DELTA",
5041  (VOIDP)sector_rotation_dn);
5042  if (returnStatus != MODIS_S_OK)
5043  {
5044  L1BErrorMsg(location, returnStatus, NULL,
5045  "read_vdata", FIRST_L1A_GRANULE, NULL, True);
5046  return returnStatus;
5047  }
5048  returnStatus = Check_Valid_Range("CS_FR_ENC_DELTA",
5049  DFNT_UINT16,
5050  NULL,
5051  "16383",
5052  NULL,
5053  L1A_Gran->num_scans,
5054  (void *) sector_rotation_dn);
5055  */
5056 
5057  returnStatus = read_vdata(L1A_Gran->v_id, 0,
5058  L1B_Scan_Meta->num_scans,
5059  "Command Parameters",
5060  "SET_FR_ENC_DELTA",
5061  (VOIDP)sector_rotation_dn);
5062  if (returnStatus != MODIS_S_OK)
5063  {
5064  L1BErrorMsg(location, returnStatus, NULL,
5065  "read_vdata", FIRST_L1A_GRANULE, NULL, True);
5066  return returnStatus;
5067  }
5068  returnStatus = Check_Valid_Range("SET_FR_ENC_DELTA",
5069  DFNT_UINT16,
5070  NULL,
5071  "16383",
5072  NULL,
5073  L1A_Gran->num_scans,
5074  (void *) sector_rotation_dn);
5075 
5076  if (returnStatus != MODIS_S_OK)
5077  {
5078  L1BErrorMsg(location, returnStatus, NULL, "Check_Valid_Range",
5080  return returnStatus;
5081  }
5082 
5083  for (S = 0; S < L1B_Scan_Meta->num_scans; S++)
5084  {
5085  buffer_ptr = buffer;
5086 
5087  scan_number = S + 1;
5088  PACK_MEMBER(scan_number, buffer_ptr);
5089 
5090  if (L1A_Gran->scan_quality[S][1] != 0)
5091  complete_scan_flag = 0;
5092  else
5093  complete_scan_flag = 1;
5094 
5095 
5096  PACK_MEMBER(complete_scan_flag, buffer_ptr);
5097 
5098  if (strcmp(L1B_Scan_Meta->ScanType[S],"Day") == SAME)
5099  scan_type[0] = 'D';
5100  else if (strcmp(L1B_Scan_Meta->ScanType[S],"Night") == SAME)
5101  scan_type[0] = 'N';
5102  else
5103  scan_type[0] = 'O';
5104  memcpy(buffer_ptr, (void *)scan_type, sizeof(scan_type));
5105  buffer_ptr += sizeof(scan_type);
5106 
5107  mirror_side =
5108  L1B_Scan_Meta->MirrorSide[S];
5109  PACK_MEMBER(mirror_side, buffer_ptr);
5110 
5111  PACK_MEMBER(L1B_Scan_Meta->EVStartTime_TAIsecond[S], buffer_ptr);
5112 
5113  EV_frames =
5114  L1B_Scan_Meta->EV_frames;
5115  PACK_MEMBER(EV_frames, buffer_ptr);
5116 
5117  nadir_frame =
5118  L1B_Scan_Meta->Nadir_Frame_Number;
5119  PACK_MEMBER(nadir_frame, buffer_ptr);
5120 
5121  nadir_frame_latitude =
5122  L1B_Scan_Meta->Nadir_Frame_Latitude[S];
5123  PACK_MEMBER(nadir_frame_latitude, buffer_ptr);
5124 
5125  nadir_frame_longitude =
5126  L1B_Scan_Meta->Nadir_Frame_Longitude[S];
5127  PACK_MEMBER(nadir_frame_longitude, buffer_ptr);
5128 
5129  nadir_frame_solar_azimuth =
5130  L1B_Scan_Meta->Nadir_Frame_Solar_Azimuth[S];
5131  PACK_MEMBER(nadir_frame_solar_azimuth, buffer_ptr);
5132 
5133  nadir_frame_solar_zenith =
5134  L1B_Scan_Meta->Nadir_Frame_Solar_Zenith[S];
5135  PACK_MEMBER(nadir_frame_solar_zenith, buffer_ptr);
5136 
5137  BB_thermistor_outliers =
5138  (int32) QA->QA_emiss.num_thermistor_outliers[S];
5139  PACK_MEMBER(BB_thermistor_outliers, buffer_ptr);
5140 
5141  bit_QA_flags =
5142  L1B_Scan_Meta->Bit_QA_Flags[S];
5143  PACK_MEMBER(bit_QA_flags, buffer_ptr);
5144 
5145  sector_rotation_angle =
5146  (180.0/8192.0)*(float32)sector_rotation_dn[S];
5147  PACK_MEMBER(sector_rotation_angle, buffer_ptr);
5148 
5149  if (VSwrite(vd_id,
5150  (unsigned char *)buffer,
5151  1,
5152  FULL_INTERLACE) == FAIL)
5153  {
5154  returnStatus = MODIS_F_WRITE_ERROR;
5155  L1BErrorMsg(location, returnStatus, NULL,
5156  "VSwrite", evfile_luns[f], NULL, True);
5157  return returnStatus;
5158  }
5159 
5160  } /* S */
5161 
5162  free(list);
5163 
5164  VSdetach(vd_id);
5165 
5166  }/* f */
5167 
5168  /*
5169  * Convert logical ID to physical file name.
5170  */
5171 
5172  returnStatus = PGS_PC_GetReference (L1B_OBC_FILE, &Version, file_name);
5173  if (returnStatus != PGS_S_SUCCESS)
5174  {
5175  returnStatus = MODIS_F_FILE_NOT_FOUND;
5176  L1BErrorMsg(location, returnStatus,
5177  "Could not retrieve file name from PCF.",
5178  "PGS_PC_GetReference", L1B_OBC_FILE, NULL, True);
5179  return returnStatus;
5180  }
5181 
5182  /*
5183  * Open file for Write. The file should already exist since most of the
5184  * data was written in the Preprocess module (the file was closed there).
5185  */
5186 
5187  obc_file_id = SDstart (file_name, DFACC_RDWR); /* for SD interfaces */
5188  if (obc_file_id == FAIL)
5189  {
5190  returnStatus = MODIS_F_FILE_NOT_OPENED;
5191  L1BErrorMsg(location, returnStatus,
5192  "Could not open file for SD read/write access.",
5193  "SDstart", L1B_OBC_FILE,
5194  "The file may be missing, corrupted or "
5195  "not an HDF-4 file.", True);
5196  return returnStatus;
5197  }
5198 
5199  /*
5200  * Write the Bit_QA_Flags as a 1D SDS to the OBC file.
5201  */
5202 
5203  returnStatus = write_sds_rank1(obc_file_id,
5204  "Bit QA Flags",
5206  L1B_Scan_Meta->num_scans,
5207  "uint32",
5208  L1B_Scan_Meta->Bit_QA_Flags);
5209  if (returnStatus != MODIS_S_OK)
5210  {
5211  L1BErrorMsg(location, returnStatus, NULL, "write_sds_rank1",
5212  L1B_OBC_FILE, NULL, True);
5213  return returnStatus;
5214  }
5215 
5216  /*
5217  * Close the file.
5218  */
5219 
5220  hdf_return = SDend(obc_file_id);
5221  if (hdf_return == FAIL)
5222  {
5223  returnStatus = MODIS_F_HDF_ERROR;
5224  L1BErrorMsg(location, returnStatus, NULL, "SDend", L1B_OBC_FILE,
5225  "Memory or the disk file must have become corrupted.",
5226  True);
5227  return returnStatus;
5228  }
5229 
5230  return(MODIS_S_OK);
5231 }
5232 
5233 
5235  L1A_granule_t *L1A_Gran)
5236 /*
5237 !C**************************************************************************
5238 !Description:
5239  This function examines validity of certain L1A data and, based on options
5240  defined in the LUTs, determines additional scans to be treated as
5241  completely missing (meaning that data will not be calibrated for any
5242  band of the scan).
5243 
5244 !Input Parameters:
5245  lookup_tables_t *tables Pointer to all L1B LUTs. The common
5246  QA LUT "control_options" is used.
5247  L1A_granule_t *L1A_Gran All members are filled, including
5248  structure member "missing_scan", based
5249  on normal values of L1A data.
5250 
5251 !Output Parameters:
5252  L1A_granule_t *L1A_Gran structure member "missing_scans" may
5253  be adjusted based on the data.
5254 
5255 !Revision History:
5256  (continue at top of the file)
5257 
5258  Revision 01.00 October 29, 2000
5259  Initial development.
5260  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
5261 
5262 !Team-unique Header:
5263  This software is developed by the MODIS Science Data Support
5264  Team for the National Aeronautics and Space Administration,
5265  Goddard Space Flight Center, under contract NAS5-32373.
5266 
5267 !References and Credits
5268  HDF portions developed at the National Center for Supercomputing
5269  Applications at the University of Illinois at Urbana-Champaign.
5270 
5271 !Design Notes:
5272 
5273 !END********************************************************************
5274 */
5275 {
5276  PGSt_SMF_status returnStatus = MODIS_S_OK;
5277  boolean split_scan[MAX_NUM_SCANS];
5278  boolean bad_scan_quality[MAX_NUM_SCANS];
5279  int32 S;
5280  char *location = "Determine_Other_Missing_Scans";
5281  common_QA_tables_t *common_QA_LUT = &tables->QA.common_QA_tables;
5282 
5283  /*
5284  * Set all elements of the array "split_scan" to True or False.
5285  */
5286 
5287  if (common_QA_LUT->control_options[SPLIT_SCAN_CONTROL] == ON)
5288  {
5289  returnStatus = Determine_Split_Scans(L1A_Gran, split_scan);
5290  if (returnStatus != MODIS_S_OK) {
5291  L1BErrorMsg(location, returnStatus, NULL,
5292  "Determine_Split_Scans", 0, NULL, True);
5293  }
5294  }
5295  else {
5296  for (S = 0; S < L1A_Gran->num_scans; S++)
5297  split_scan[S] = False;
5298  }
5299 
5300  /*
5301  * Set all elements of the array "bad_scan_quality" to True or False.
5302  */
5303 
5304  if (common_QA_LUT->control_options[BAD_SCAN_QUALITY_CONTROL] == ON)
5305  {
5306  for (S = 0; S < L1A_Gran->num_scans; S++) {
5307  if ((L1A_Gran->scan_quality[S][0] != 0 &&
5308  L1A_Gran->scan_quality[S][0] != 1) ||
5309  L1A_Gran->scan_quality[S][1] < 0 ||
5310  L1A_Gran->scan_quality[S][2] < 0 ||
5311  L1A_Gran->scan_quality[S][3] < 0)
5312  bad_scan_quality[S] = True;
5313  else
5314  bad_scan_quality[S] = False;
5315  }
5316  }
5317  else
5318  {
5319  for (S = 0; S < L1A_Gran->num_scans; S++)
5320  bad_scan_quality[S] = False;
5321  }
5322 
5323  /*
5324  * adjust the values of "missing_scan", if necessary.
5325  */
5326 
5327  for (S = 0; S < L1A_Gran->num_scans; S++)
5328  {
5329  if (split_scan[S] || bad_scan_quality[S])
5330  L1A_Gran->missing_scan[S] = True;
5331  }
5332 
5333 
5334  /*
5335  * Check the mirror side flags. So far, there has not been a
5336  * situation where the mirror side flag was not valid but there were
5337  * data on the scan. However, just in case this happens, this will
5338  * allow the scan to be skipped rather than causing the code to error
5339  * out.
5340  */
5341 
5342 
5343  for (S = 0; S < L1A_Gran->num_scans; S++)
5344  {
5345  if (!(L1A_Gran->MirrorSide[S] == 0 || L1A_Gran->MirrorSide[S] == 1))
5346  L1A_Gran->missing_scan[S] = True;
5347  }
5348 
5349 
5350  return MODIS_S_OK;
5351 }
5352 
5353 PGSt_SMF_status Determine_Split_Scans(L1A_granule_t *L1A_Gran,
5354  boolean *split_scan)
5355 /*
5356 !C**************************************************************************
5357 !Description:
5358  This function determines scan indices of "split scans". A split scan
5359  arises from a bit flip in the scan time of a packet. The L1A code takes
5360  the out-of-order packet and starts a new scan in the granule. Thus, the
5361  original scan is split into two parts. A split scan causes the number
5362  of scans in the granule to exceed the normal 203 or 204 scans.
5363 
5364  See the design notes for comments on the algorithm for detecting a split
5365  scan.
5366 
5367 !Input parameters:
5368 
5369  L1A_granule_t *L1A_Gran contains L1A variables for SD start
5370  time, scan quality and mirror side
5371 
5372 !Output parameters:
5373 
5374  boolean split_scan array which defines if a scan
5375 
5376 !Revision History:
5377  (continue at top of the file)
5378 
5379  Revision 01.02, October 29, 2000
5380  Moved from L1B.c and removed adjusting the QA counters. (issue 142)
5381  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
5382 
5383  Revision 01.01 September 20, 2000
5384  Correct logic errors which led to PGE02 failures (see Razor issue 136).
5385  Call new function, Get_Split_Scan_Indexes.
5386  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
5387 
5388  Revision 01.00 May 2, 2000
5389  Initial development
5390  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
5391 
5392 !Team-unique Header:
5393  This software is developed by the MODIS Science Data Support
5394  Team for the National Aeronautics and Space Administration,
5395  Goddard Space Flight Center, under contract NAS5-32373.
5396 
5397 !References and Credits:
5398  HDF portions developed at the National Center for Supercomputing
5399  Applications at the University of Illinois at Urbana-Champaign.
5400 
5401 !Design Notes:
5402 
5403  The algorithm for finding the two parts of a split scan begins by
5404  finding an abnormally short time interval between two scans. The
5405  "SD start time" is used for this because in examining many cases of
5406  split scans, it appeared to be the most reliable time among the
5407  various sector start times ("EV start time" was the least reliable).
5408 
5409  The two scans with the abnormally short time interval are not
5410  necessarily the two parts of the split scan. If there are no
5411  repeated mirror side indexes or no missing packets, then the
5412  abnormal time interval is assumed to not be a marker for a split
5413  scan.
5414 
5415  If the short time interval does correspond to a split scan, then at
5416  least one of the two scans will be part of the split scan. To find
5417  the other part, we expand the range of scan indexes by 1 in each
5418  direction and look at "Mirror side" and "Scan quality array". A
5419  repeated mirror side index is the next most reliable indicator.
5420  However, occasionally, one part of the split scan will have a mirror
5421  side index of -1. In this case, we then turn to the number of
5422  missing packets (recorded in the second element of the scan quality
5423  array). The two adjacent scans with large numbers of missing packets
5424  are the next most reliable indicator.
5425 
5426  There is no attempt to find the two parts of a split scan if they
5427  reside in different granules.
5428 
5429 !END********************************************************************
5430 */
5431 {
5432 #define SCAN_INTERVAL 1.4771
5433  PGSt_SMF_status returnStatus;
5434  int32 i; /* scan index in loop through scans */
5435  int32 j; /* used for scan interval */
5436  int32 S_split_1; /* scan index of 1st part of split scan */
5437  int32 S_split_2; /* scan index of 2nd part of split scan */
5438  float64 SD_start_time[MAX_NUM_SCANS];
5439  char *location = "Determine_Split_Scans";
5440 
5441  for (i = 0; i < L1A_Gran->num_scans; i++)
5442  {
5443  split_scan[i] = False;
5444  }
5445 
5446  /* Read SD start time */
5447 
5448  returnStatus = read_sds_rank1 (L1A_Gran->sd_id, "SD start time",
5449  L1A_Gran->num_scans,
5450  (void *)SD_start_time);
5451  if (returnStatus != MODIS_S_OK)
5452  {
5453  L1BErrorMsg(location, returnStatus,
5454  "Could not read SD start time.",
5455  "read_sds_rank1",
5457  return returnStatus;
5458  }
5459 
5460  /* Loop through all scans looking for potential split scans */
5461 
5462  for (i = 1; i < L1A_Gran->num_scans; i++)
5463  {
5464 
5465  /*
5466  * Look at the time interval between scans i-1 and i. If the time
5467  * interval is smaller than 1/2 the normal time interval between
5468  * MODIS scans, then define this to be "abnormally short".
5469  */
5470 
5471  j = (int32)((SD_start_time[i] - SD_start_time[i-1])/SCAN_INTERVAL + 0.5);
5472  if (j <= 0)
5473  {
5474 
5475  /*
5476  * An abnormally short time interval was detected between scans
5477  * i-1 and i. Get the two indexes of the split scan. If the
5478  * indexes return as invalid indexes, assume that the abnormally
5479  * short time interval does not correspond to a split scan.
5480  */
5481 
5482  returnStatus = Get_Split_Scan_Indexes(i-1,
5483  L1A_Gran->num_scans,
5484  L1A_Gran->MirrorSide,
5485  L1A_Gran->scan_quality,
5486  &S_split_1,
5487  &S_split_2);
5488  if (returnStatus != MODIS_S_OK)
5489  {
5490  L1BErrorMsg(location, returnStatus, NULL,
5491  "Get_Split_Scan_Indexes", 0, NULL, False);
5492  return MODIS_S_OK;
5493  }
5494 
5495  if (S_split_1 >= 0 && S_split_1 < L1A_Gran->num_scans)
5496  split_scan[S_split_1] = True;
5497  if (S_split_2 >= 0 && S_split_2 < L1A_Gran->num_scans)
5498  split_scan[S_split_2] = True;
5499 
5500  }
5501  }
5502 
5503  return MODIS_S_OK;
5504 }
5505 
5506 PGSt_SMF_status Get_Split_Scan_Indexes
5507  (int32 S1,
5508  int32 num_scans,
5509  int16 mirror_side[],
5510  int32 scan_quality[]
5512  int32 *S_split_1,
5513  int32 *S_split_2)
5514 /*
5515 !C**************************************************************************
5516 !Description:
5517  Given a pair of scans with an abnormally short time interval,
5518  examine the mirror side and scan quality array indexes to find the
5519  actual split scan indexes. If the split scan indexes cannot be
5520  determined, return invalid values (-1) for the indexes.
5521 
5522 !Input parameters:
5523  int32 S1 1st scan index of the pair of scans with an
5524  abnormally short time interval
5525  int32 num_scans Number of scans in the granule
5526  int32 mirror_side[] mirror side indexes
5527  int32 scan_quality[][] Scan quality array
5528 
5529 !Output parameters:
5530  int32 *S_split_1 Index of 1st part of split scan (or -1
5531  if there is no split scan)
5532  int32 *S_split_2 Index of 2nd part of split scan (or -1
5533  if there is no split scan)
5534 
5535 !Revision History:
5536  (continue at top of the file)
5537 
5538  Revision 01.01 October 16, 2004 Razor Issue #200
5539  Casted Int32 variables in sprintf calls to "long" with the
5540  format specifier "%ld" for better code portability.
5541  Liqin Tan, SAIC GSO (ltan@saicmodis.com)
5542 
5543  Revision 01.00 September 20, 2000
5544  Initial development
5545  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
5546 
5547 !Team-unique Header:
5548  This software is developed by the MODIS Science Data Support
5549  Team for the National Aeronautics and Space Administration,
5550  Goddard Space Flight Center, under contract NAS5-32373.
5551 
5552 !References and Credits:
5553  HDF portions developed at the National Center for Supercomputing
5554  Applications at the University of Illinois at Urbana-Champaign.
5555 
5556 !Design Notes:
5557 
5558 !END********************************************************************
5559 */
5560 {
5561  int32 S, S_begin, S_end;
5562  int32 num_invalid_ms, n, max_n;
5563  char *location = "Get_Split_Scan_Indexes";
5564 
5565  /*
5566  * Check S1 and num_scans
5567  */
5568 
5569  if (S1 < 0 || S1 >= num_scans || num_scans <= 0)
5570  {
5571  char errmsg[256];
5572  sprintf (errmsg,
5573  "Input error in S1 or num_scans:\nS1 = %ld\nnum_scans = %ld\n",
5574  (long)S1, (long)num_scans);
5575  L1BErrorMsg(location, MODIS_F_INVALID_ARGUMENT, errmsg,
5576  NULL, 0, NULL, True);
5577  return MODIS_F_INVALID_ARGUMENT;
5578  }
5579 
5580  /*
5581  * Initialize the return indexes to invalid values.
5582  */
5583 
5584  *S_split_1 = -1;
5585  *S_split_2 = -1;
5586 
5587  /*
5588  * Find the begin and end scan indexes of the range of scans
5589  * to look through. The normal range is a set of 4 scans, starting
5590  * at the scan just before S1.
5591  */
5592 
5593  S_begin = S1 - 1;
5594  if (S_begin < 0) S_begin = 0;
5595  S_end = S1 + 2;
5596  if (S_end >= num_scans) S_end = num_scans - 1;
5597 
5598  /*
5599  * determine if any of the scans has an invalid mirror side index.
5600  */
5601 
5602  num_invalid_ms = 0;
5603  for (S = S_begin; S <= S_end; S++) {
5604  if (!(mirror_side[S] == 0 || mirror_side[S] == 1))
5605  num_invalid_ms++;
5606  }
5607 
5608  /*
5609  * If all the mirror side indexes are valid, base the determination
5610  * on mirror side. Otherwise, base the determination on the pair
5611  * with the largest number of missing packets.
5612  */
5613 
5614  if (num_invalid_ms == 0) {
5615  for (S = S_begin; S < S_end; S++) {
5616  if (mirror_side[S] == mirror_side[S+1]) {
5617  *S_split_1 = S;
5618  *S_split_2 = S+1;
5619  break;
5620  }
5621  }
5622  }
5623  else {
5624  max_n = 0;
5625  for (S = S_begin; S < S_end; S++) {
5626  n = 0;
5627  if (scan_quality[S][1] > 0)
5628  n+= scan_quality[S][1];
5629  if (scan_quality[S+1][1] > 0)
5630  n+= scan_quality[S+1][1];
5631  if (n > max_n) {
5632  max_n = n;
5633  if (scan_quality[S][0] == 0) {
5634  *S_split_1 = S; /* extra scan, blank */
5635  *S_split_2 = -1; /* assume this one is OK */
5636  }
5637  else if (scan_quality[S+1][0] == 0) {
5638  *S_split_1 = -1; /* assume this one is OK */
5639  *S_split_2 = S+1; /* extra scan, blank */
5640  }
5641  else {
5642  *S_split_1 = S;
5643  *S_split_2 = S+1;
5644  }
5645  }
5646  }
5647  if (max_n < 2800) {
5648  *S_split_1 = -1;
5649  *S_split_2 = -1;
5650  }
5651  }
5652 
5653  return MODIS_S_OK;
5654 }
5655 
5656 
5657 PGSt_SMF_status Set_UI_ConvertToPercent_Attrs
5659  L1B_Scan_t *L1B_Scan,
5660  boolean skip_night_hi_res)
5661 /*
5662 !C****************************************************************************
5663 !Description:
5664  Add attributes to all EV UI SDSs which allow conversion of UI to
5665  percent uncertainty. These attributes are: "specified_uncertainty",
5666  "scaling_factor" and "uncertainty_units".
5667 
5668 !Input Parameters:
5669  lookup_tables_t *tables Contains values for the attributes in LUTs
5670  L1B_Scan_t *L1B_Scan Contains the UI SDS IDs (opened)
5671  boolean skip_night_hi_res True if and only if all scans are
5672  night mode scans and writing of 250m
5673  and 500m night mode granules has been
5674  turned off
5675 
5676 !Output Parameters:
5677  (none -- the HDF files themselves are modified)
5678 
5679 !Revision History:
5680  (continue at top of the file)
5681 
5682  Revision 01.02 January 17, 2002 Razor Issue #171
5683  Improve portability of code to 64-bit mode.
5684  Cast strlen returns to int32 in calls to SDSetattr.
5685  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
5686 
5687  Revision 01.01, November 16, 2001, Razor Issue #169
5688  Added input parameter skip_night_hi_res and changed logic so that
5689  250m and 500m data are not written when granule has no day mode
5690  scans and runtime parameter Write_Night_Mode_HiRes_Data is False.
5691  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
5692 
5693  Revision 01.00 Nov. 29, 2000
5694  Initial development
5695  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
5696 
5697 !Team-unique Header:
5698  This software is developed by the MODIS Science Data Support
5699  Team for the National Aeronautics and Space Administration,
5700  Goddard Space Flight Center, under contract NAS5-32373.
5701 
5702 !References and Credits:
5703  HDF portions developed at the National Center for Supercomputing
5704  Applications at the University of Illinois at Urbana-Champaign.
5705 
5706 !Design Notes:
5707  The arrays contained in the LUTs are for all emissive bands (TEB LUTs)
5708  and all reflective bands (RSB LUTs). Within these linear arrays, the
5709  numbers to be set in the attributes are consecutive. Thus, use a macro
5710  where the beginning index and number of values define which subset of
5711  the arrays to write into the attributes.
5712 
5713 !END**************************************************************************
5714 */
5715 {
5716  PGSt_SMF_status returnStatus;
5717  char *units_attr_value = "percent";
5718  char *location = "Set_UI_ConvertToPercent_Attrs";
5719 
5720 #define REFL_250M_START_INDEX 0
5721 #define REFL_500M_START_INDEX 2
5722 #define REFL_1000M_START_INDEX 7
5723 #define REFL_BAND26_START_INDEX 21
5724 
5725 /* Macro: SET_UI_SDS_CONV_ATTRS
5726  * sds_id = opened SDS ID for the SDS to set attributes for
5727  * spec_uncert = variable containing specified uncertainty float array
5728  * scale_factor = variable containing scaling factor float array
5729  * indx = the starting element index in the arrays
5730  * numval = number of values in the attribute
5731  */
5732 #define SET_UI_SDS_CONV_ATTRS(sds_id, spec_uncert, scale_factor, indx, \
5733  numval, lun) \
5734  if (SDsetattr(sds_id, "specified_uncertainty", DFNT_FLOAT32, \
5735  numval, &(spec_uncert[indx])) == FAIL) { \
5736  returnStatus = MODIS_F_WRITE_ERROR; \
5737  L1BErrorMsg(location, returnStatus, \
5738  "Could not write UI SDS attribute" \
5739  "\"specified_uncertainty\".", \
5740  "SDsetattr", lun, NULL, True); \
5741  return returnStatus; \
5742  } \
5743  if (SDsetattr(sds_id, "scaling_factor", DFNT_FLOAT32, \
5744  numval, &(scale_factor[indx])) == FAIL) { \
5745  returnStatus = MODIS_F_WRITE_ERROR; \
5746  L1BErrorMsg(location, returnStatus, \
5747  "Could not write UI SDS attribute \"scaling_factor\".", \
5748  "SDsetattr", lun, NULL, True); \
5749  return returnStatus; \
5750  } \
5751  if (SDsetattr(sds_id, "uncertainty_units", DFNT_CHAR8, \
5752  (int32)strlen(units_attr_value), units_attr_value) == FAIL) { \
5753  returnStatus = MODIS_F_WRITE_ERROR; \
5754  L1BErrorMsg(location, returnStatus, \
5755  "Could not write UI SDS attribute \"uncertainty_units\".", \
5756  "SDsetattr", lun, NULL, True); \
5757  return returnStatus; \
5758  }
5759 
5760  if (skip_night_hi_res == False)
5761  {
5763  tables->refl.RSB_specified_uncertainty,
5764  tables->refl.RSB_UI_scaling_factor,
5767 
5769  tables->refl.RSB_specified_uncertainty,
5770  tables->refl.RSB_UI_scaling_factor,
5773 
5775  tables->refl.RSB_specified_uncertainty,
5776  tables->refl.RSB_UI_scaling_factor,
5779  }
5780 
5782  tables->refl.RSB_specified_uncertainty,
5783  tables->refl.RSB_UI_scaling_factor,
5786 
5788  tables->emiss.TEB_specified_uncertainty,
5789  tables->emiss.TEB_UI_scaling_factor,
5790  0, NUM_EMISSIVE_BANDS,
5792 
5794  tables->refl.RSB_specified_uncertainty,
5795  tables->refl.RSB_UI_scaling_factor,
5798 
5800  tables->refl.RSB_specified_uncertainty,
5801  tables->refl.RSB_UI_scaling_factor,
5804 
5805 /************************* Begin Band 26 Section **************************/
5806 #ifdef WRITE_BAND_26_SDS
5807 
5809  tables->refl.RSB_specified_uncertainty,
5810  tables->refl.RSB_UI_scaling_factor,
5813 
5814 #endif /* WRITE_BAND_26_SDS */
5815 /************************** End Band 26 Section ***************************/
5816 
5817  return MODIS_S_OK;
5818 }
5819 
5820 PGSt_SMF_status Calculate_B26_B5_Correction
5821  (float32 *original_correction,
5822  float32 *scaled_correction,
5823  L1B_ScaleOffset_t *ScaleOffset)
5824 
5825 /*
5826 !C****************************************************************************
5827 !Description:
5828  This function scales crosstalk correction factors which are used to adjust
5829  Band 26 data by crosstalk from Band 5. The scaling factor is the Band 5
5830  radiance scale divided by the Band 26 radiance scale.
5831 
5832 !Input Parameters:
5833  float32 *original_correction Lookup table correction values
5834  L1B_ScaleOffset_t *ScaleOffset Granule-specific scales and offsets
5835 
5836 !Output Parameters:
5837  float32 *scaled_correction Correction values scaled by the
5838  granule-specific scales and offsets
5839 
5840 !Revision History:
5841  (continue at top of the file)
5842 
5843  Initial development March 19, 2002 Razor Issue #182
5844  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
5845 
5846 !Team-unique Header:
5847  This software is developed by the MODIS Characterization Support
5848  Team (MCST)for the National Aeronautics and Space Administration,
5849  Goddard Space Flight Center, under contract NAS5-32373.
5850 
5851 !References and Credits:
5852  HDF portions developed at the National Center for Supercomputing
5853  Applications at the University of Illinois at Urbana-Champaign.
5854 
5855 !Design Notes:
5856 
5857 !END**************************************************************************
5858 */
5859 
5860 {
5861  PGSt_SMF_status returnStatus = MODIS_S_OK;
5862  int16 D = 0; /* Detector */
5863  float32 scale_factor = 1.; /* Scaling factor */
5864 
5865 
5866  scale_factor = ScaleOffset->rad_scale_RefSB[MODIS_BAND5_INDEX]/
5867  ScaleOffset->rad_scale_RefSB[BAND_26_REFL_INDEX];
5868  for (D = 0; D < DETECTORS_PER_1KM_BAND; D++)
5869  scaled_correction[D] = scale_factor*original_correction[D];
5870 
5871  return returnStatus;
5872 }
GEO_SDS
Definition: l1_hmodis_hdf.c:56
float32 rad_scale_RefSB[NUM_REFLECTIVE_BANDS]
Definition: Granule.h:800
PGSt_SMF_status Determine_Split_Scans(L1A_granule_t *L1A_Gran, boolean *split_scan)
Definition: L1B_Setup.c:5361
#define BAND_26_UI_SDS_NAME
Definition: Granule.h:942
#define MODIS_BAND5_INDEX
Definition: Granule.h:445
#define MODIS_S_OK
#define MODIS_F_FILE_NOT_FOUND
PGSt_SMF_status Calculate_Earth_Sun_Distance(L1A_granule_t *L1A_Gran, float32 *Earth_Sun_Dist)
Definition: L1B_Setup.c:504
boolean missing_scan[MAX_NUM_SCANS]
Definition: Granule.h:769
integer, parameter int16
Definition: cubeio.f90:3
float32 Nadir_Frame_Solar_Zenith[MAX_NUM_SCANS]
Definition: L1B_Setup.h:69
int32 v_id[NUM_L1B_EV_FILES]
Definition: Granule.h:858
int32 num_bad_dn_star_star_RSB_EV_data[NUM_DETECTORS]
Definition: Granule.h:1086
#define NADIR_1km_FRAME_NUM
Definition: Granule.h:473
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
#define SCAN_QUALITY_ARRAY_NUM_ELEMENTS
Definition: Granule.h:488
@ SI_500to1km
Definition: L1B_Setup.c:102
boolean leading_granule_scan_gap
Definition: Granule.h:1072
#define MAX_SAMPLES_PER_BAND
Definition: Granule.h:475
#define MODIS_F_WRITE_ERROR
int j
Definition: decode_rs.h:73
QA_Common_t QA_common
Definition: Granule.h:1097
uint32 dead_subframe_pixels[NUM_BANDS]
Definition: Granule.h:883
float32 refl_scale_RefSB[NUM_REFLECTIVE_BANDS]
Definition: Granule.h:802
float32 m1_des_sq[NUM_REFLECTIVE_BANDS][MAX_DETECTORS_PER_BAND][MAX_SAMPLES_PER_BAND][NUM_MIRROR_SIDES]
Definition: Granule.h:818
uint32 interpolated_pixels[NUM_BANDS]
Definition: Granule.h:881
list(APPEND LIBS ${PGSTK_LIBRARIES}) add_executable(atteph_info_modis atteph_info_modis.c) target_link_libraries(atteph_info_modis $
Definition: CMakeLists.txt:7
boolean missing_trailing_granule
Definition: Granule.h:1071
#define CREATE_EV_SDS(sd_id, SI_name, UI_name, SI_longName, UI_longName, SI_id, UI_id)
L1B_ScaleOffset_t SO
Definition: Granule.h:865
uint32 valid_pixels[NUM_BANDS]
Definition: Granule.h:878
int16 MirrorSide[MAX_NUM_SCANS]
Definition: L1B_Setup.h:70
#define REFL_1000M_START_INDEX
#define REFL_250M_START_INDEX
int32 num_sector_rotation_EV_data[NUM_DETECTORS]
Definition: Granule.h:1082
int8 all_BB_DN_bad[MAX_NUM_SCANS]
Definition: Granule.h:1064
float32 Nadir_Frame_Solar_Azimuth[MAX_NUM_SCANS]
Definition: L1B_Setup.h:68
@ SPLIT_SCAN_CONTROL
Definition: L1B_Tables.h:873
int32 UI_sds_id[NUM_L1A_RESOLUTIONS]
Definition: Granule.h:966
PGSt_SMF_status Open_L1A_EV_SDS(L1A_granule_t *L1A_Gran, L1A_Scan_t *L1A_Scan)
Definition: L1B_Setup.c:419
#define SCAN_INTERVAL
@ INDEX_LATITUDE
Definition: L1B_SetupP.h:100
#define BAND_26_UI_SDS_LONG_NAME
Definition: Granule.h:944
#define MAX_ATTR_NAME_SIZE2
int32 num_nadir_door_closed_EV_data[NUM_DETECTORS]
Definition: Granule.h:1088
#define GEO_OFFSET
Definition: L1B_SetupP.h:95
#define FAIL
Definition: ObpgReadGrid.h:18
int32 num_saturated_EV_data[NUM_DETECTORS]
Definition: Granule.h:1083
#define MODIS_F_OUT_OF_MEMORY
@ INDEX_500M
Definition: Granule.h:570
char * L1B_EV_DIM_NAME[NUM_L1A_RESOLUTIONS][L1B_EV_SDS_RANK]
Definition: L1B_Setup.c:164
#define REFL_500M_START_INDEX
#define NULL
Definition: decode_rs.h:63
float32 dn_star_Min[NUM_REFLECTIVE_BANDS]
Definition: Granule.h:798
#define MODIS_BAND26_INDEX
Definition: Granule.h:446
int32 EV_500m_Aggr1km_RefSB_sds_id
Definition: Granule.h:965
#define FIRST_L1A_GRANULE
Definition: FNames.h:79
#define PGS_PI
Definition: GEO_geo.h:172
#define L1B_EV_SDS_RANK
Definition: L1B_Setup.c:166
@ SI_1km_EMISS
Definition: L1B_Setup.c:99
Band_26_t Band26
Definition: Granule.h:1022
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
@ UI_500to1km
Definition: L1B_Setup.c:102
#define MAX_ATTR_NAME_SIZE
float64 EVStartTime_TAIsecond[MAX_NUM_SCANS]
Definition: L1B_Setup.h:72
@ SI_250m
Definition: L1B_Setup.c:96
int32 EV_250m_Aggr500m_RefSB_SU_sds_id
Definition: Granule.h:970
PGSt_SMF_status Set_UI_ConvertToPercent_Attrs(lookup_tables_t *tables, L1B_Scan_t *L1B_Scan, boolean skip_night_hi_res)
Definition: L1B_Setup.c:5666
int32 EV_500m_Aggr1km_RefSB_SU_sds_id
Definition: Granule.h:972
#define NUM_500M_BANDS
Definition: Granule.h:431
#define PACK_MEMBER(member, buffer_ptr)
int32 SI_sds_id
Definition: Granule.h:947
#define MODIS_F_OUT_OF_RANGE
int32 num_exceed_max_for_scaling[NUM_DETECTORS]
Definition: Granule.h:1087
int32 num_scans
Definition: Granule.h:749
#define MODIS_BAND26_INDEX_AT_RES
Definition: Granule.h:447
int8 change_dc_restore[MAX_NUM_SCANS][NUM_EMISSIVE_BANDS][DETECTORS_PER_1KM_BAND]
Definition: Granule.h:1046
uint8 * counts
Definition: l1_czcs_hdf.c:30
boolean Sector_Rotation[MAX_NUM_SCANS]
Definition: Granule.h:1075
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_INT32
@ INDEX_250M
Definition: Granule.h:569
int8 all_SV_DN_bad[MAX_NUM_SCANS]
Definition: Granule.h:1063
#define ON
Definition: l1.h:43
const int NUM_MIRROR_SIDES
#define DETECTORS_PER_500M_BAND
Definition: Granule.h:439
int32 num_moon_in_SVP_TEB_EV_data[NUM_DETECTORS]
Definition: Granule.h:1085
int16 BAND_RATIO_AT_RES[NUM_L1A_RESOLUTIONS]
Definition: Granule.c:73
float32 m1_des_sq_max[NUM_REFLECTIVE_BANDS]
Definition: Granule.h:820
int8 moon_in_SV_KOB_TEB[MAX_NUM_SCANS]
Definition: Granule.h:1048
@ NUM_GEO_SDS
Definition: L1B_SetupP.h:109
#define DETECTORS_PER_1KM_BAND
Definition: Granule.h:438
PGSt_SMF_status Copy_Geo_SDS(L1B_granule_t *L1B_Gran, boolean skip_night_hi_res)
Definition: L1B_Setup.c:3243
#define MODIS_BAND20_INDEX
Definition: Granule.h:448
PGSt_SMF_status Determine_Other_Missing_Scans(lookup_tables_t *tables, L1A_granule_t *L1A_Gran)
Definition: L1B_Setup.c:5242
int32 num_missing_scans
Definition: Granule.h:1077
@ SI_250to500m
Definition: L1B_Setup.c:100
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
@ SU_500to1km
Definition: L1B_Setup.c:102
float32 rad_offset_RefSB[NUM_REFLECTIVE_BANDS]
Definition: Granule.h:801
#define L1B_EV_500M_FILE
Definition: FNames.h:70
@ SU_250to500m
Definition: L1B_Setup.c:100
#define DN15_SAT
Definition: Granule.h:1103
@ INDEX_L1B_250m
Definition: Granule.h:587
PGSt_SMF_status Open_L1B_EV_SDS(L1B_granule_t *L1B_Gran, L1B_Scan_t *L1B_Scan, boolean skip_night_hi_res)
Definition: L1B_Setup.c:1726
#define MODIS_F_FILE_NOT_CREATED
uint32 total_pixels[NUM_BANDS]
Definition: Granule.h:877
int32 num_day_scans
Definition: Granule.h:750
PGSt_SMF_status read_sds_rank1(int32 file_id, char *sds_name, int32 dim, void *data)
Definition: HDF_Lib.c:359
int32 num_negative_b1[NUM_DETECTORS]
Definition: Granule.h:1089
#define LEADING_L1A_GRANULE
Definition: FNames.h:78
QA_Refl_t QA_refl
Definition: Granule.h:1099
PGSt_SMF_status Scan_Meta_Cal(lookup_tables_t *tables, L1A_granule_t *L1A_Gran, L1B_granule_t *L1B_Gran, L1B_Scan_Metadata_t *L1B_Scan_Meta, QA_Data_t *QA)
Definition: L1B_Setup.c:3766
#define GEOLOCATION_FILE
Definition: FNames.h:82
boolean Electronic_Anomaly[MAX_NUM_SCANS]
Definition: Granule.h:1076
uint32 saturated_pixels[NUM_BANDS]
Definition: Granule.h:879
int32 L1B_EV_DIM_OFFSET[NUM_L1A_RESOLUTIONS][L1B_EV_SDS_RANK-1]
Definition: L1B_Setup.c:173
int32 v_id
Definition: Granule.h:746
const int NUM_BANDS
int32 sds_id[NUM_L1A_RESOLUTIONS]
Definition: Granule.h:775
const int NUM_DETECTORS
#define L1B_EV_250M_FILE
Definition: FNames.h:69
float32 counts_scale_RefSB[NUM_REFLECTIVE_BANDS]
Definition: Granule.h:805
@ NUM_L1B_EV_FILES
Definition: Granule.h:590
double precision function f(R1)
Definition: tmd.lp.f:1454
#define SAME
Definition: Granule.h:494
#define GEO_STRIDE
Definition: L1B_SetupP.h:94
int16 L1A_BANDS_AT_RES[NUM_L1A_RESOLUTIONS]
Definition: Granule.c:63
@ BAND26
Definition: Granule.h:643
@ UI_250to1km
Definition: L1B_Setup.c:101
#define NUM_SCANS_DIM_NAME
Definition: Granule.h:416
PGSt_SMF_status Create_Band_Subsetting_SDS(L1B_granule_t *L1B_Gran, boolean skip_night_hi_res)
Definition: L1B_Setup.c:3055
#define BAND_26_SI_SDS_LONG_NAME
Definition: Granule.h:943
float32 Earth_Sun_Dist
Definition: Granule.h:886
int8 moon_in_SV_KOB_RSB[MAX_NUM_SCANS]
Definition: Granule.h:1062
float32 rad_offset_Emiss[NUM_EMISSIVE_BANDS]
Definition: Granule.h:809
#define SOLAR_AZIMUTH_ZENITH_SCALE_FACTOR
Definition: L1B_SetupP.h:136
#define MODIS_F_READ_ERROR
@ UI_500m
Definition: L1B_Setup.c:97
#define SET_UI_SDS_CONV_ATTRS(sds_id, spec_uncert, scale_factor, indx, numval, lun)
geo_sds_index_t
Definition: L1B_SetupP.h:99
int32 SI_sds_id[NUM_L1A_RESOLUTIONS]
Definition: Granule.h:962
#define EV_1km_FRAMES
Definition: Granule.h:469
const int NUM_REFLECTIVE_BANDS
PGSt_SMF_status Open_W_L1B_Granule(lookup_tables_t *tables, L1B_granule_t *L1B_Gran, L1B_Scan_t *L1B_Scan, boolean skip_night_hi_res)
Definition: L1B_Setup.c:894
int32 EV_250m_Aggr500m_RefSB_UI_sds_id
Definition: Granule.h:967
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
#define MAX_ATTR_BUFFER_SIZE
int32 scan_quality[MAX_NUM_SCANS][SCAN_QUALITY_ARRAY_NUM_ELEMENTS]
Definition: Granule.h:754
float32 dn_star_Max[NUM_REFLECTIVE_BANDS]
Definition: Granule.h:797
uint32 Bit_QA_Flags[MAX_NUM_SCANS]
Definition: L1B_Setup.h:73
PGSt_SMF_status Set_SDS_Attributes(int32 *sds_id, char **BandNames, float32 **scale, float32 **offset, char *rad_units, char *refl_units, char *counts_units, int32 num_sds)
Definition: L1B_Setup.c:2871
#define INDEX_1000M_EMISS
Definition: Granule.h:576
#define SW_DEF_EV_SDS(SI_name, UI_name, str)
void SMF_ERROR(PGSt_SMF_code code, char *messagestring)
Definition: Granule.c:1345
PGSt_SMF_status Init_QA_Parameters(L1A_granule_t *L1A_Gran, L1B_granule_t *L1B_Gran, QA_Data_t *QA)
Definition: L1B_Setup.c:4617
char ScanType[MAX_NUM_SCANS][SCAN_TYPE_TEXT_SIZE]
Definition: Granule.h:752
PGSt_SMF_status L1B_Setup(lookup_tables_t *tables, L1A_granule_t *L1A_Gran, L1B_granule_t *L1B_Gran, L1A_Scan_t *L1A_Scan, L1B_Scan_t *L1B_Scan, QA_Data_t *QA, L1B_Scan_Metadata_t *L1B_Scan_Meta, boolean skip_night_hi_res)
Definition: L1B_Setup.c:218
PGSt_SMF_status Create_L1B_Swath(L1B_granule_t *L1B_Gran, boolean skip_night_hi_res)
Definition: L1B_Setup.c:1059
int32 num_day_scans
Definition: Granule.h:861
int32 num_missing_data_in_scans[NUM_DETECTORS]
Definition: Granule.h:1079
int32 EV_250m_Aggr1km_RefSB_SU_sds_id
Definition: Granule.h:971
int32 EV_250m_Aggr500m_RefSB_sds_id
Definition: Granule.h:963
int8 change_dc_restore_500m[MAX_NUM_SCANS][NUM_500M_BANDS][DETECTORS_PER_500M_BAND]
Definition: Granule.h:1058
#define NUM_HIGH_RESOLUTION_DETECTORS
Definition: Granule.h:425
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_INT16
float32 L1B_EV_DIM_FRAC_OFFSET[NUM_L1A_RESOLUTIONS][L1B_EV_SDS_RANK-1]
Definition: L1B_Setup.c:179
PGSt_SMF_status read_attribute(int32 s_id, char *attr_name, int32 TypeID, void *buffer)
Definition: HDF_Lib.c:33
char * L1B_EV_SDS_NAME[NUM_L1B_EV_SDS]
Definition: L1B_Setup.c:106
@ UI_250to500m
Definition: L1B_Setup.c:100
#define MODIS_F_NOK
instead the metadata field ProcessingEnvinronment is filled in from the output of a call to the POSIX compliant function uname from within the L1B code A small bug in L1B_Tables an incorrect comparison of RVS coefficients for TEBs to RVS coefficients for RSBs was being made This was replaced with a comparison between TEB coefficients This error never resulted in an incorrect RVS correction but did lead to recalculating the coefficients for each detector in a thermal band even if the coefficients were the same for all detectors To reduce to overall size of the reflective LUT HDF fill values were eliminated from all LUTs previously dimensioned where and where NUM_TIMES is the number of time dependent table pieces In Preprocess a small error where the trailing dropped scan counter was incremented when the leading dropped scan counter should have been was fixed This counter is internal only and is not yet used for any chiefly to casting of were added to make it LINUX compatible Output of code run on LINUX machines displays differences of at most scaled sector incalculable values of the Emissive calibration factor and incalculable values of SV or BB averages was moved outside the loop over frames in Emissive_Cal c since none of these quantities are frame dependent Initialization of b1 and XMS values in Preprocess c routine Process_OBCENG_Emiss was moved inside the detector loops The code was altered so that if up to five scans are dropped between the leading middle or middle trailing the leading or trailing granule will still be used in emissive calibration to form a cross granule average QA bits and are set for a gap between the leading middle and middle trailing granules respectively This may in rare instances lead to a change in emissive calibration coefficients for scans at the beginning or end of a granule A small bug in the Band correction algorithm was corrected an uncertainty value was being checked against an upper bound whereas the proper quantity to be checked was the corresponding SI
Definition: HISTORY.txt:595
uint8 num_thermistor_outliers[MAX_NUM_SCANS]
Definition: Granule.h:1043
PGSt_SMF_status Set_Unit_Range_Fillvalue(L1B_Scan_t *L1B_Scan, boolean skip_night_hi_res)
Definition: L1B_Setup.c:2439
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude data
Definition: HISTORY.txt:356
@ BAD_SCAN_QUALITY_CONTROL
Definition: L1B_Tables.h:874
#define L1B_EV_1000M_FILE
Definition: FNames.h:71
PGSt_SMF_status Get_Split_Scan_Indexes(int32 S1, int32 num_scans, int16 mirror_side[], int32 scan_quality[][SCAN_QUALITY_ARRAY_NUM_ELEMENTS], int32 *S_split_1, int32 *S_split_2)
Definition: L1B_Setup.c:5515
int32 num_scans
Definition: Granule.h:860
@ INDEX_GFLAGS
Definition: L1B_SetupP.h:108
PGSt_SMF_status Write_L1B_ScanMeta(L1B_Scan_Metadata_t *L1B_Scan_Meta, L1A_granule_t *L1A_Gran, QA_Data_t *QA, boolean skip_night_hi_res)
Definition: L1B_Setup.c:4810
#define True
Definition: Granule.h:537
@ SI_1km
Definition: L1B_Setup.c:98
char ScanType[MAX_NUM_SCANS][SCAN_TYPE_TEXT_SIZE]
Definition: L1B_Setup.h:71
int32 sd_id[NUM_L1B_EV_FILES]
Definition: Granule.h:859
#define MAX_NUM_SCANS
Definition: Granule.h:422
@ SU_250to1km
Definition: L1B_Setup.c:101
int32 num_dead_detector_EV_data[NUM_DETECTORS]
Definition: Granule.h:1080
uint32 missing_pixels[NUM_BANDS]
Definition: Granule.h:880
data_t loc[NROOTS]
Definition: decode_rs.h:78
@ INDEX_L1B_1km
Definition: Granule.h:589
@ NUM_L1B_EV_SDS
Definition: L1B_Setup.c:103
float32 b26_fr_b5_scaled_corr[DETECTORS_PER_1KM_BAND]
Definition: Granule.h:867
int16 RFLAG
Definition: Granule.c:75
L1B_EV_SDS_index_t
Definition: L1B_Setup.c:94
@ SI_500m
Definition: L1B_Setup.c:97
PGSt_SMF_status read_sds_rank2(int32 file_id, char *sds_name, int32 dim1, int32 dim2, void *data)
Definition: HDF_Lib.c:449
int32 Nadir_Frame_Number
Definition: L1B_Setup.h:67
#define CREATE_EV_Aggr_SDS(sd_id, SI_name, UI_name, SU_name, SI_LName, UI_LName, SU_LName, SI_id, UI_id, SU_id)
@ UI_250m
Definition: L1B_Setup.c:96
float32 counts_offset_RefSB[NUM_REFLECTIVE_BANDS]
Definition: Granule.h:806
int32 num_rsb_at_night_scans
Definition: Granule.h:1078
#define REFLECTIVE_TABLES_FILE
Definition: FNames.h:74
#define SW_DEF_EV_Aggr_SDS(SI_name, UI_name, SU_name, str)
#define COPY_ATTR(attr_name)
int32 num_dead_subframe_EV_data[NUM_HIGH_RESOLUTION_DETECTORS]
Definition: Granule.h:1081
int32 sw_f_id[NUM_L1B_EV_FILES]
Definition: Granule.h:857
#define fabs(a)
Definition: misc.h:93
boolean trailing_granule_scan_gap
Definition: Granule.h:1073
float32 rad_scale_Emiss[NUM_EMISSIVE_BANDS]
Definition: Granule.h:808
int16 RSCL_FLAG
Definition: Granule.c:76
#define NUM_DCR_VALUE
Definition: Metadata.h:67
#define NUM_ATTITUDE_ANGLES
Definition: L1B_Tables.h:434
PGSt_SMF_status Set_L1B_EV_SDS_Attrs(lookup_tables_t *tables, L1B_granule_t *L1B_Gran, L1B_Scan_t *L1B_Scan, boolean skip_night_hi_res)
Definition: L1B_Setup.c:2055
int16 bad_data_flag[NUM_BANDS]
Definition: Granule.h:885
@ INDEX_HEIGHT
Definition: L1B_SetupP.h:102
int32 num_no_bg_DN_EV_data[NUM_DETECTORS]
Definition: Granule.h:1084
PGSt_SMF_status Calculate_B26_B5_Correction(float32 *original_correction, float32 *scaled_correction, L1B_ScaleOffset_t *ScaleOffset)
Definition: L1B_Setup.c:5829
QA_Emiss_t QA_emiss
Definition: Granule.h:1098
#define NUM_REFLECTIVE_DETECTORS
Definition: Granule.h:427
#define BAND_26_REFL_INDEX
Definition: L1B_SetupP.h:91
RSB_Cal_Coeff_t RSB_Cal_Coeff
Definition: Granule.h:863
int32 sd_id
Definition: Granule.h:747
float32 Nadir_Frame_Latitude[MAX_NUM_SCANS]
Definition: L1B_Setup.h:65
int32 v_id[NUM_L1B_EV_FILES]
Definition: L1B_Setup.h:60
#define NUM_250M_BANDS
Definition: Granule.h:430
boolean missing_leading_granule
Definition: Granule.h:1070
int16 L1B_BANDS_AT_RES[NUM_L1A_RESOLUTIONS]
Definition: Granule.c:58
#define MODIS_F_HDF_ERROR
int32 EV_250m_Aggr1km_RefSB_sds_id
Definition: Granule.h:964
l2prod offset
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_FLOAT32
@ UI_1km_EMISS
Definition: L1B_Setup.c:99
#define L1B_OBC_FILE
Definition: FNames.h:72
#define MAX_DETECTORS_PER_BAND
Definition: Granule.h:474
int16 DETECT_PER_BAND_AT_RES[NUM_L1A_RESOLUTIONS]
Definition: Granule.c:68
int8 change_dc_restore_1km[MAX_NUM_SCANS][NUM_1000M_REFL_BANDS][DETECTORS_PER_1KM_BAND]
Definition: Granule.h:1060
#define R
Definition: make_L3_v1.1.c:96
void L1BErrorMsg(char *L1B_location, PGSt_SMF_code code, char *input_message, char *assoc_function, int32 lun, char *other_msg, boolean error_out)
Definition: Granule.c:918
char Invalid_MOD01_Msg[]
Definition: Granule.c:913
#define MODIS_F_FILE_NOT_OPENED
@ INDEX_L1B_500m
Definition: Granule.h:588
@ NUM_L1A_RESOLUTIONS
Definition: Granule.h:573
char * Band_subsetting_names[NUM_L1A_RESOLUTIONS]
Definition: L1B_Setup.c:155
int32 EV_250m_Aggr1km_RefSB_UI_sds_id
Definition: Granule.h:968
char * L1A_EV_SDS_NAME[NUM_L1A_RESOLUTIONS]
Definition: L1B_Setup.c:81
GNU GENERAL PUBLIC LICENSE Version
Definition: LICENSE.txt:2
PGSt_SMF_status Write_Swath_Band_Number(int32 file_index, L1B_granule_t *L1B_Gran)
Definition: L1B_Setup.c:1581
#define NUM_1000M_REFL_BANDS
Definition: Granule.h:432
int8 change_dc_restore_250m[MAX_NUM_SCANS][NUM_250M_BANDS][DETECTORS_PER_250M_BAND]
Definition: Granule.h:1056
@ BAND31
Definition: Granule.h:644
#define REFL_BAND26_START_INDEX
const int NUM_EMISSIVE_BANDS
#define NADIR_FRAME_GEO_VALS(geoname, var, scalefactor, buf)
char * L1B_EV_SDS_LONG_NAME[NUM_L1B_EV_SDS]
Definition: L1B_Setup.c:120
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 MODIS_F_INVALID_ARGUMENT
uint32 dead_detector_pixels[NUM_BANDS]
Definition: Granule.h:882
const int MOON_INSIDE_SV_KOB
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
#define BAND_26_SI_SDS_NAME
Definition: Granule.h:941
int16 MirrorSide[MAX_NUM_SCANS]
Definition: Granule.h:751
uint8 control_options[NUM_CONTROL_OPTIONS]
Definition: L1B_Tables.h:902
float32 Nadir_Frame_Longitude[MAX_NUM_SCANS]
Definition: L1B_Setup.h:66
int32 EV_500m_Aggr1km_RefSB_UI_sds_id
Definition: Granule.h:969
@ SI_250to1km
Definition: L1B_Setup.c:101
PGSt_SMF_status read_part_sds_rank2(int32 sd_id, char *sds_name, int32 start0, int32 start1, int32 edge0, int32 edge1, void *data)
Definition: HDF_Lib.c:150
int16 band_X
Definition: Granule.h:1026
PGSt_SMF_status Calculate_RSB_Cal_Coeff(lookup_tables_t *tables, float32 E_S_Dist, RSB_Cal_Coeff_t *RSB_Cal_Coeff)
Definition: L1B_Setup.c:615
boolean NAD_Door_Open[MAX_NUM_SCANS]
Definition: Granule.h:1074
float64 EVStartTime_TAIsecond[MAX_NUM_SCANS]
Definition: Granule.h:753
#define DETECTORS_PER_250M_BAND
Definition: Granule.h:440
@ UI_1km
Definition: L1B_Setup.c:98
int32 UI_sds_id
Definition: Granule.h:948
version
Definition: setup.py:15
PGSt_SMF_status Get_SDS_id(int32 f, L1B_Scan_t *L1B_Scan, int16 *num_sds, int32 *sds_id)
Definition: L1B_Setup.c:2787
uint32 negative_value_below_noise_pixels[NUM_BANDS]
Definition: Granule.h:884
#define False
Definition: Granule.h:538
PGSt_SMF_status Calculate_DCR_Change(L1A_granule_t *L1A_Gran, QA_Data_t *QA, L1B_Scan_Metadata_t *L1B_Scan_Meta)
Definition: L1B_Setup.c:4339
#define INDEX_1000M_REFL
Definition: Granule.h:575
float32 refl_offset_RefSB[NUM_REFLECTIVE_BANDS]
Definition: Granule.h:803
PGSt_SMF_status Init_L1B_ScaleOffset(L1B_ScaleOffset_t *SO, RSB_Cal_Coeff_t *RSB_Cal_Coeff, float E_S_Dist, lookup_tables_t *tables)
Definition: L1B_Setup.c:736