ocssw  1.0
/disk01/web/ocssw/build/src/l1bgen_modist/Granule.c (r8084/r6631)
Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003 File: Granule.c
00004 
00005 External functions:
00006    Aggregate_L1B
00007    Close_L1A_Granule
00008    Close_L1B_Granule
00009    Read_L1A_EV_Scan
00010    safe_strcat
00011    L1BErrorMsg
00012    SMF_ERROR
00013    Bad_L1A_Error_Out
00014    Write_L1B_EV_Scan
00015    Fill_Dead_Detector_SI
00016    Open_and_Read_L1A
00017    Get_Satellite_ID
00018    Read_Run_Time_Parameters
00019 
00020 Other functions:
00021    Compute_Aggregates
00022    Write_L1B_SI_UI
00023 
00024 Revision History:
00025    $Log: Granule.c,v $
00026    Revision 1.26  2008-01-31 16:45:17-05  ltan
00027    Relax the RVS correction limit range. Removed the ScanType of "Mixed" from the code.
00028 
00029    Revision 1.24  2006/10/30 14:53:59  ltan
00030    Changed to write PGEVersion value extracted from the PCF file (LUN 800500). Also check to make sure the PGE Version from the PCF matchs code macro PGE02_VERSION.
00031 
00032    Revision 1.22  2005/01/18 19:34:42  ltan
00033    Added new file attributes prefixed with HDFEOS_FractionalOffset
00034 
00035 *****************************************************************************/
00036 
00037 #include    "L1B_Tables.h"
00038 #include    "GranuleP.h"
00039 #include    "HDF_Lib.h"
00040 #include    "PGS_PC.h"
00041 #include    "PGS_TD.h"
00042 #include    "PGS_MET.h"
00043 #include    "PGS_Error_Codes.h"
00044 #include    "FNames.h"
00045 #include    <string.h>
00046 #include    <math.h>
00047 #include    <time.h>
00048 
00049 /* MOD_PR02 exit code */
00050 
00051 int32 MOD_PR02_Failure_Exit_Code = 1;
00052 
00053 /*----------------------------------------------------------------------------
00054      The following are external variables used by other modules
00055  ---------------------------------------------------------------------------*/
00056 
00057 int16 L1B_BANDS_AT_RES[NUM_L1A_RESOLUTIONS] = {
00058   NUM_250M_BANDS,       NUM_500M_BANDS,
00059   NUM_1000M_REFL_BANDS, NUM_1000M_EMISS_BANDS
00060 };
00061 
00062 int16 L1A_BANDS_AT_RES[NUM_L1A_RESOLUTIONS] = {
00063   NUM_250M_BANDS,       NUM_500M_BANDS,
00064   NUM_1000M_DAY_BANDS,  NUM_1000M_NIGHT_BANDS
00065 };
00066 
00067 int16 DETECT_PER_BAND_AT_RES [NUM_L1A_RESOLUTIONS] = {
00068   DETECTORS_PER_1KM_BAND * 4, DETECTORS_PER_1KM_BAND * 2,
00069   DETECTORS_PER_1KM_BAND    , DETECTORS_PER_1KM_BAND
00070 };
00071 
00072 int16 BAND_RATIO_AT_RES[NUM_L1A_RESOLUTIONS] = {4,2,1,1};
00073 
00074 int16 RFLAG;
00075 int16 RSCL_FLAG;
00076 
00077 PGSt_SMF_status  Aggregate_L1B (L1B_Scan_t  *L1B_Scan)
00078 /*
00079 !C**********************************************************************
00080 !Description:
00081   For one scan of calibrated earth-view data, this routine performs
00082   spatial integration (or aggregation) of each of the higher
00083   resolution bands (250m or 500m) so that they appear at a lower
00084   resolution appropriate for the 500m or 1km L1B granule products.
00085 
00086 !Input Parameters:
00087       L1B_Scan_t  *L1B_Scan   (->SI, ->UI)
00088 
00089 !Output Parameters:
00090       L1B_Scan_t  *L1B_Scan   (->SI_aggr, ->UI_aggr, ->SU_aggr)
00091 
00092 !Revision History:
00093  (continue at top of the file)
00094 
00095  Revision 02.11 July 1998
00096  Modified the routine to match the change of L1B_Scant_t change.
00097  Zhenying Gu (zgu@ltpmail.gsfc.nasa.gov)
00098 
00099  Revision 01.00 April 1997
00100  Initial development
00101  (based on the routine Compute_Aggregates, which 
00102  is a C translation of the FORTRAN code written 
00103  by Vicky Lin & Rich Hucek)
00104  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
00105 
00106 !Team-unique Header:
00107  This software is developed by the MODIS Characterization Support
00108  Team (MCST)for the National Aeronautics and Space Administration,
00109  Goddard Space Flight Center, under contract NAS5-32373.
00110 
00111 !References and Credits:
00112  HDF portions developed at the National Center for Supercomputing
00113  Applications at the University of Illinois at Urbana-Champaign.
00114 
00115 !Design Notes:
00116 
00117 !END********************************************************************
00118 */ 
00119 {
00120   PGSt_SMF_status returnStatus = MODIS_S_OK;
00121   int16   B         = 0;
00122   int16   line_dim  = 0;
00123   int16   pixel_dim = 0;
00124 
00125   /*------------------
00126     250_to_500m
00127   -------------------*/
00128   line_dim = DETECT_PER_BAND_AT_RES[INDEX_500M];
00129   pixel_dim = BAND_RATIO_AT_RES[INDEX_500M] * EV_1km_FRAMES;
00130 
00131   for (B = 0; B < L1B_BANDS_AT_RES[INDEX_250M]; B++)
00132   {
00133     returnStatus = Compute_Aggregates 
00134                      (2, line_dim, pixel_dim,
00135                       (VOIDP)L1B_Scan->SI.EV_250m_RefSB[B],
00136                       (VOIDP)L1B_Scan->UI.EV_250m_RefSB_UI[B],
00137                       (VOIDP)L1B_Scan->EV_250m_Aggr500m_RefSB[B],
00138                       (VOIDP)L1B_Scan->EV_250m_Aggr500m_RefSB_UI[B],
00139                       (VOIDP)L1B_Scan->EV_250m_Aggr500m_RefSB_SU[B]);
00140     if (returnStatus != MODIS_S_OK)
00141       SMF_ERROR(returnStatus, 
00142                 "Compute_Aggregates(250_to_500m) in "
00143                 "Aggregate_L1B(), Granule.c");
00144   }
00145 
00146 
00147   /*---------------------------
00148     250_to_1km & 500_to_1km
00149   ---------------------------*/
00150   line_dim = DETECT_PER_BAND_AT_RES[INDEX_1000M_REFL];
00151   pixel_dim = EV_1km_FRAMES;
00152   
00153   if ((RFLAG & 1) == 0) {
00154   for (B = 0; B < L1B_BANDS_AT_RES[INDEX_250M]; B++)
00155   {
00156     returnStatus = Compute_Aggregates 
00157                     (4, line_dim, pixel_dim,
00158                      (VOIDP)L1B_Scan->SI.EV_250m_RefSB[B],
00159                      (VOIDP)L1B_Scan->UI.EV_250m_RefSB_UI[B],
00160                      (VOIDP)L1B_Scan->EV_250m_Aggr1km_RefSB[B],
00161                      (VOIDP)L1B_Scan->EV_250m_Aggr1km_RefSB_UI[B],
00162                      (VOIDP)L1B_Scan->EV_250m_Aggr1km_RefSB_SU[B]);
00163     if (returnStatus != MODIS_S_OK)
00164       SMF_ERROR(returnStatus,
00165                 "Compute_Aggregates(250_to_1km) in "
00166                 "Aggregate_L1B(), Granule.c");
00167   }
00168   }
00169 
00170   if ((RFLAG & 2) == 0) {
00171   for (B = 0; B < L1B_BANDS_AT_RES[INDEX_500M]; B++)
00172   {
00173     returnStatus = Compute_Aggregates 
00174                     (2, line_dim, pixel_dim,
00175                      (VOIDP)L1B_Scan->SI.EV_500m_RefSB[B],
00176                      (VOIDP)L1B_Scan->UI.EV_500m_RefSB_UI[B],
00177                      (VOIDP)L1B_Scan->EV_500m_Aggr1km_RefSB[B],
00178                      (VOIDP)L1B_Scan->EV_500m_Aggr1km_RefSB_UI[B],
00179                      (VOIDP)L1B_Scan->EV_500m_Aggr1km_RefSB_SU[B]);
00180     if (returnStatus != MODIS_S_OK)
00181       SMF_ERROR(returnStatus,
00182                 "Compute_Aggregates(500_to_1km) in "
00183                 "Aggregate_L1B(), Granule.c");
00184   }
00185   }
00186 
00187   return(MODIS_S_OK);
00188 }
00189 
00190 
00191 PGSt_SMF_status Close_L1A_Granule (L1A_granule_t *L1A_Gran,
00192                                    L1A_Scan_t    *L1A_Scan)
00193 /*
00194 !C**********************************************************************
00195 !Description:
00196     This routine ends access to all L1A SDSs and ends the SD and Vdata
00197     interfaces to the L1A middle granule file.
00198 
00199 !Input Parameters:
00200       L1A_granule_t *L1A_Gran
00201       L1A_Scan_t    *L1A_Scan
00202 
00203 !Output Parameters:
00204       L1A_granule_t *L1A_Gran
00205       L1A_Scan_t    *L1A_Scan
00206 
00207 !Revision History:
00208  (continue at top of the file)
00209 
00210  Revision 02.11 July 1998
00211  Removed Cleanup_L1A_Granule ( the arrays are changed to static allocated )
00212  Zhenying Gu (zgu@ltpmail.gsfc.nasa.gov)
00213 
00214  Revision 02.00 March 1997
00215  Modified to match changes in L1A_granule_t & L1A_Scan_t.
00216  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
00217 
00218  (Neal's version between 01.01 & 02.00 ......???)
00219 
00220  Revision 01.01 1996/04/05
00221  Updated to match Version Design Document.
00222  John Hannon(hannon@highwire.gsfc.nasa.gov)
00223  Joan Baden (baden@highwire.gsfc.nasa.gov)
00224 
00225  Revision 01.00 1993
00226  Initial development
00227  Geir E. Kvaran(geir@highwire.gsfc.nasa.gov)
00228 
00229 !Team-unique Header:
00230 
00231 !References and Credits:
00232    This software is developed by the MODIS Characterization Support
00233    Team (MCST)for the National Aeronautics and Space Administration,
00234    Goddard Space Flight Center, under contract NAS5-32373.
00235 
00236    HDF portions developed at the National Center for Supercomputing
00237    Applications at the University of Illinois at Urbana-Champaign.
00238 
00239 !Design Notes:
00240 
00241 !END********************************************************************
00242 */
00243 {
00244   PGSt_SMF_status returnStatus = MODIS_S_OK;
00245   int16     R   = 0;
00246  
00247   /*Close L1A EV SDS's*/
00248   for (R = 0; R < NUM_L1A_RESOLUTIONS; R++) {
00249     if ((RFLAG & (1 << R)) != 0) continue;
00250     if (SDendaccess(L1A_Scan->sds_id[R]) == FAIL)
00251       return(MODIS_F_NOK);
00252   }
00253 
00254   /*Clode L1A file*/
00255   if (SDend(L1A_Gran->sd_id) == FAIL) /* close the SD interface */
00256     return(MODIS_F_NOK);
00257 
00258   if (Vend(L1A_Gran->v_id) == FAIL) 
00259     return(MODIS_F_NOK);
00260 
00261   if (Hclose(L1A_Gran->v_id) == FAIL) /* close the Vdata interface */
00262     return(MODIS_F_NOK);
00263 
00264   return(returnStatus);
00265 }
00266 
00267 PGSt_SMF_status Close_L1B_Granule (L1B_granule_t         *L1B_Gran,
00268                                    L1B_Scan_t            *L1B_Scan,
00269                                    boolean               skip_night_hi_res)
00270 /*
00271 !C**********************************************************************
00272 !Description:
00273     This routine ends SDS access to all open EV SDSs and ends swath interface
00274     to all L1B EV granule files.
00275 
00276 !Input Parameters:
00277      L1B_granule_t         *L1B_Gran
00278      L1B_Scan_t            *L1B_Scan
00279      Run_Time_Parameters_t *runtime_params    Values read from PCF file.
00280      boolean               skip_night_hi_res  Logical; TRUE if and only 
00281                                               if all scans in the granule 
00282                                               are in NIGHT mode.                        
00283 
00284 !Output Parameters:
00285      L1B_granule_t *L1B_Gran
00286      L1B_Scan_t    *L1B_Scan
00287 
00288 !Revision History:
00289  (continue at top of the file)
00290 
00291  Revision 02.21  November 13, 2001 (Razor Issue #169)
00292   Added skip_night_hi_res to input variables. 
00293   Changed logic so that 250m and 500m data are not written when granule
00294   has no day mode scans and runtime parameter
00295   Write_Night_Mode_HiRes_Data is False.
00296  Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov) 
00297 
00298  Revision 02.20 May   1999
00299  Added band 26 section.
00300  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
00301 
00302  Revision 02.11 July  1998
00303  Removed Cleanup_L1B_Granule(), because all arrays are changed to 
00304     static allocated.
00305  Zhenying Gu (zgu@ltpmail.gsfc.nasa.gov)
00306 
00307  Revision 02.00 March 1997
00308  Modified to match changes in L1B_granule_t & L1B_Scan_t.
00309  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
00310 
00311  (Neal's version between 01.01 & 02.00 ......???)
00312 
00313  Revision 01.01 1996/04/05
00314  Uppdated to match Version 1 Design Document.
00315  John Hannon(hannon@highwire.gsfc.nasa.gov)
00316  Joan Baden (baden@highwire.gsfc.nasa.gov)
00317 
00318  Revision 01.00 1993
00319  Initial development
00320  Geir E. Kvaran(geir@highwire.gsfc.nasa.gov)
00321 
00322 !Team-unique Header:
00323 
00324 !References and Credits:
00325    This software is developed by the MODIS Characterization Support
00326    Team (MCST)for the National Aeronautics and Space Administration,
00327    Goddard Space Flight Center, under contract NAS5-32373.
00328 
00329    HDF portions developed at the National Center for Supercomputing
00330    Applications at the University of Illinois at Urbana-Champaign.
00331 
00332 !Design Notes:
00333    Code to make Vgroup has been removed.  It is not currently implemented 
00334    in SDS_Services, although it could be.
00335 !END********************************************************************
00336 */
00337 {
00338   PGSt_SMF_status returnStatus = MODIS_S_OK;
00339   int16     R                  = 0;
00340   int16     f                  = 0;
00341   int16     start_output_index = 0;
00342   
00343   if (skip_night_hi_res == True)
00344     start_output_index = INDEX_L1B_1km;
00345   else
00346     start_output_index = INDEX_L1B_250m;
00347 
00348   /*Close L1B EV SDS's*/
00349     
00350   for (R = start_output_index; R < NUM_L1A_RESOLUTIONS; R++)
00351   {
00352     if ((RFLAG & (1 << R)) != 0) continue;
00353     if (SDendaccess(L1B_Scan->SI_sds_id[R]) == FAIL) return(MODIS_F_NOK);
00354     if (SDendaccess(L1B_Scan->UI_sds_id[R]) == FAIL) return(MODIS_F_NOK);
00355   }
00356   if (skip_night_hi_res == False)
00357   {
00358     if (SDendaccess(L1B_Scan->EV_250m_Aggr500m_RefSB_sds_id) == FAIL) 
00359       return(MODIS_F_NOK);
00360     if (SDendaccess(L1B_Scan->EV_250m_Aggr500m_RefSB_UI_sds_id) == FAIL) 
00361       return(MODIS_F_NOK);
00362     if (SDendaccess(L1B_Scan->EV_250m_Aggr500m_RefSB_SU_sds_id) == FAIL) 
00363       return(MODIS_F_NOK);
00364   }
00365 
00366   if (SDendaccess(L1B_Scan->EV_250m_Aggr1km_RefSB_sds_id) == FAIL) 
00367     return(MODIS_F_NOK);
00368   if (SDendaccess(L1B_Scan->EV_250m_Aggr1km_RefSB_UI_sds_id) == FAIL) 
00369     return(MODIS_F_NOK);
00370   if (SDendaccess(L1B_Scan->EV_250m_Aggr1km_RefSB_SU_sds_id) == FAIL) 
00371     return(MODIS_F_NOK);
00372   if (SDendaccess(L1B_Scan->EV_500m_Aggr1km_RefSB_sds_id) == FAIL) 
00373     return(MODIS_F_NOK);
00374   if (SDendaccess(L1B_Scan->EV_500m_Aggr1km_RefSB_UI_sds_id) == FAIL) 
00375     return(MODIS_F_NOK);
00376   if (SDendaccess(L1B_Scan->EV_500m_Aggr1km_RefSB_SU_sds_id) == FAIL) 
00377     return(MODIS_F_NOK);
00378 
00379 /************************* Begin Band 26 Section **************************/
00380 #ifdef WRITE_BAND_26_SDS
00381 /*
00382  * Close SDS access to the band 26 SDSs.
00383  */
00384   if (SDendaccess(L1B_Scan->Band26.SI_sds_id) == FAIL)
00385     return(MODIS_F_NOK);
00386   if (SDendaccess(L1B_Scan->Band26.UI_sds_id) == FAIL)
00387     return(MODIS_F_NOK);
00388 #endif /* WRITE_BAND_26_SDS */
00389 /************************** End Band 26 Section ***************************/
00390 
00391   /*
00392    * If this granule has no day mode scans and the runtime parameter
00393    * Write_Night_Mode_HiRes_Data is False, the 250m and 500m
00394    * resolution files were not written, and so start with output 
00395    * file number 2, not 0.
00396    */
00397    
00398   if (skip_night_hi_res == True)
00399     start_output_index = INDEX_L1B_1km;
00400   else
00401     start_output_index = INDEX_L1B_250m;
00402   
00403 
00404   /*Close L1B EV files*/
00405   for (f = start_output_index; f < NUM_L1B_EV_FILES; f++)
00406     if (SWclose(L1B_Gran->sw_f_id[f]) == FAIL) return(MODIS_F_NOK);
00407 
00408   return(returnStatus);
00409 }
00410 
00411 
00412 PGSt_SMF_status  Compute_Aggregates (int16     scale,
00413                                      int16     line_dim_lower,
00414                                      int16     frame_dim_lower,
00415                                      uint16    *SI_in,
00416                                      uint8     *UI_in,
00417                                      uint16    *SI_out,
00418                                      uint8     *UI_out,
00419                                      int8      *SU_out)
00420 /*
00421 !C****************************************************************************
00422 !Description:
00423    Perform spatial integration (aggregation) of higher resolution L1B data to
00424    appear as lower resolution data. This function computes the aggregated
00425    scaled integer, the aggregated uncertainty index and the number of samples
00426    used in aggregation.
00427 
00428 !Input Parameters:
00429    int16  scale           spatial integration factor, in both the along track
00430                           and along scan directions of the data. (there are
00431                           limited valid values -- see the local variables)
00432    int16  line_dim_lower  line dimension (along track) of lower resolution data
00433    int16  frame_dim_lower frame dimension (along scan) of lower resolution data
00434    uint16 *SI_in          scaled integer data of higher resolution
00435                           (size = line_dim_lower * scale * frame_dim_lower * scale)
00436    uint8  *UI_in          uncertainty index data of higher resolution
00437                           (size = line_dim_lower * scale * frame_dim_lower * scale)
00438 
00439 !Output Parameters:
00440    uint16 *SI_out         aggregated scaled integer data at lower resolution
00441                           (array size = line_dim_lower * frame_dim_lower).
00442    uint8  *UI_out         aggregated uncertainty index data at lower resolution
00443                           (array size = line_dim_lower * frame_dim_lower).
00444    int8   *SU_out         number of samples used in each aggregation
00445                           (array size = line_dim_lower * frame_dim_lower).
00446 
00447 !Revision History:
00448  (continue at top of the file)
00449 
00450    Revision 01.01, January 9, 2001, Razor issue 149
00451    The assumption on how the first samples of different resolution data are
00452    registered was corrected. Also added design notes, made variable names more
00453    meaningful, improved efficiency slightly and added comments.
00454    Jim Rogers (rogers@mcst.gsfc.nasa.gov)
00455 
00456    Revision 01.00 April 1997
00457    Initial development
00458    (this is a translation of the FORTRAN code, 
00459    Aggregate_L1B, of Vicky Lin & Richard Hucek)
00460    Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
00461 
00462 !Team-unique Header:
00463    This software is developed by the MODIS Characterization Support
00464    Team (MCST)for the National Aeronautics and Space Administration,
00465    Goddard Space Flight Center, under contract NAS5-32373.
00466 
00467 !References and Credits:
00468    This code is translated from the FORTRAN code written by 
00469         Vicky Lin     (vlin@ltpmail.gsfc.nasa.gov)
00470         Richard Hucek (rhucek@ltpmail.gsfc.nasa.gov)
00471    HDF portions developed at the National Center for Supercomputing
00472    Applications at the University of Illinois at Urbana-Champaign.
00473 
00474 !Design Notes:
00475    1. For the input and output arrays of data, each array represents a
00476       2D array, similar to:
00477          A[line_dim_lower][frame_dim_lower]               (lower resolution)
00478          A[line_dim_lower*scale][frame_dim_lower*scale]   (higher resolution)
00479       Thus, each higher resolution array has scale^2 times the values of
00480       a lower resolution array.
00481    2. In the line dimension (along track), each set of scale lines of the
00482       higher resolution are averaged (using uniform weighting) to form
00483       one aggregated line at the lower resolution.
00484    3. In the frame dimension (along scan), the effective response of a
00485       detector of either resolution is a triangle function, with the peak of
00486       the triangle at the effective location of the frame, and the base
00487       of the triangle having a total width of 2 times the frame width.  The
00488       triangular responses are overlapping by 1/2 the frame width
00489       (see the Geolocation ATBD for an explanation and diagram).
00490    4. The frames of different resolutions are registered such that the 1st
00491       frame of any line at one resolution is aligned with the first frame
00492       in a line of a different resolution.
00493    5. To aggregate in the frame dimension, (2*scale-1) consecutive values
00494       are chosen with triangular weighting to form the aggregated response.
00495       Because of the assumption in item 4 above, the first (scale-1) frames
00496       are missing from the first aggregate in any given line.
00497 
00498 !END**************************************************************************
00499 */
00500 {
00501   int16    lines_to_aggregate;   /* number of lines of higher resolution data
00502                                   * to aggregate to one line of lower resolution
00503                                   * data (same as input value of "scale").
00504                                   */
00505   int16    frames_to_aggregate;  /* number of frames (triangle functions) of
00506                                   * higher resolution data to aggregate to one
00507                                   * frame of lower resolution data (2*scale-1).
00508                                   */
00509   int16    line_offset;          /* essentially this is the index of the first
00510                                   * line of higher resolution data to use in
00511                                   * one aggregation across the set of lines.
00512                                   */
00513   int16    frame_offset;         /* essentially this is the index of the first
00514                                   * frame of higher resolution data to use in
00515                                   * one aggregation across the set of frames.
00516                                   */
00517   int16    frame_dim_higher;     /* number of higher resolution frames in each
00518                                   * line of higher resolution data (must be
00519                                   * frame_dim_lower * scale).
00520                                   */
00521   int16    L1;                   /* line index in lower resolution data */
00522   int16    F1;                   /* frame index in lower resolution data */
00523   int16    L2;                   /* line index in higher resolution data */
00524   int16    L;                    /* line index in one set of higher resolution
00525                                   * lines to aggregate.
00526                                   */
00527   int16    F;                    /* frame index in one set of higher resolution
00528                                   * frames to aggregate.
00529                                   */
00530   int16    F_start;              /* starting frame index within one set of
00531                                   * higher resolution frames to aggregate.
00532                                   * (not necessarily 0 because of design note 4).
00533                                   */
00534   int16    scale_index;          /* index in 1st dimension of W and SqW arrays */
00535   int32    index_higher;         /* array index within any higher resolution
00536                                   * array (must be int32).
00537                                   */
00538   int32    index_lower;          /* array index within any lower resolution
00539                                   * array (must be int32).
00540                                   */
00541   int8     samples;              /* used to count number of valid samples used
00542                                   * in one aggregation.
00543                                   */
00544   float32  sum_W;                /* accumulates the weight factors */
00545   float32  sum_WSI;              /* accumulates the weighted scaled integer */
00546   float32  sum_SqW;              /* accumulates the square of the weight factors */
00547   float32  sum_SqWUI;            /* accumulates the square of the weighted UI */
00548 
00549   /*
00550    * The following define how many valid scale factors are handled by this
00551    * function and the maximum number of frames for triangle weighting.
00552    */
00553 
00554 #define NUM_SCALE_FACTORS  2
00555 #define MAX_AGGR_FRAMES    7
00556 
00557   /*
00558    * The following arrays hold the valid scale factors and the associated
00559    * weighting factors, for aggregating along the frame (scan) dimension.
00560    *   W   = weight
00561    *   SqW = square of weight.
00562    * The number of frames to aggregate is (2 * scale - 1).
00563    */
00564 
00565   int16 valid_scale_values[NUM_SCALE_FACTORS] = {2, 4};
00566 
00567   float32  W[NUM_SCALE_FACTORS][MAX_AGGR_FRAMES] = {
00568     {1,  2,  1,  0,  0,  0,  0}, 
00569     {1,  2,  3,  4,  3,  2,  1}
00570   };
00571 
00572   float32  SqW[NUM_SCALE_FACTORS][MAX_AGGR_FRAMES] = {
00573     {1,  4,  1,  0,  0,  0,  0}, 
00574     {1,  4,  9, 16,  9,  4,  1}
00575   };
00576 
00577   /*************************************************************************/
00578 
00579   /*
00580    * Determine the "scale_index", the index in the W and SqW arrays.
00581    * This checks the value of "scale" in the process.
00582    */
00583 
00584   for (scale_index = 0; scale_index < NUM_SCALE_FACTORS; scale_index++)
00585   {
00586     if (scale == valid_scale_values[scale_index])
00587       break;
00588   }
00589   if (scale_index == NUM_SCALE_FACTORS)
00590   {
00591     char errmsg[512];
00592     sprintf (errmsg, "Input argument (scale = %d) is invalid.", scale);
00593     L1BErrorMsg("Compute_Aggregates", MODIS_F_INVALID_ARGUMENT, errmsg, NULL, 0,
00594                 NULL, True);
00595   }
00596 
00597 
00598   lines_to_aggregate  = scale;
00599   frames_to_aggregate = 2 * scale - 1;
00600   frame_dim_higher    = frame_dim_lower * scale; 
00601 
00602   line_offset = 0;
00603   for (L1 = 0; L1 < line_dim_lower; L1++, line_offset += scale)
00604   {
00605 
00606     /*
00607      * frame_offset starts negative.  For the first aggregation of a line,
00608      * we will start at the peak of the triangle weight to compensate.
00609      */
00610 
00611     frame_offset = - (scale - 1);
00612     for (F1 = 0; F1 < frame_dim_lower; F1++, frame_offset += scale)
00613     {
00614 
00615       /*
00616        * Because the first frames of different resolutions align, for the
00617        * first aggregate of a line we are missing some frames on the left side
00618        * of the triangle weighting function.  Set F_start so that we will
00619        * have a valid frame index later.
00620        */
00621 
00622       if (F1 == 0)
00623         F_start = scale - 1;    /* start at the peak of triangle weighting */
00624       else
00625         F_start = 0;            /* start at beginning of triangle weighting */
00626 
00627       samples   = 0;
00628       sum_W     = 0;
00629       sum_WSI   = 0;
00630       sum_SqW   = 0;
00631       sum_SqWUI = 0;
00632 
00633       for (L = 0; L < lines_to_aggregate; L++)
00634       {
00635         L2 = line_offset + L;
00636 
00637         index_higher = L2 * frame_dim_higher + frame_offset + F_start;
00638         for (F = F_start; F < frames_to_aggregate; F++, index_higher++)
00639         {
00640           if (SI_in[index_higher] <= DN15_SAT)
00641           {
00642             samples++;
00643             sum_W     += W[scale_index][F];
00644             sum_WSI   += W[scale_index][F] * SI_in[index_higher];
00645             sum_SqW   += SqW[scale_index][F];
00646             sum_SqWUI += SqW[scale_index][F] * UI_in[index_higher] * UI_in[index_higher];
00647           }
00648         }
00649       }
00650 
00651       index_lower = L1 * frame_dim_lower + F1; 
00652       if (samples > 0)
00653       {
00654         SI_out[index_lower] = (uint16)(sum_WSI / sum_W + 0.5);
00655         UI_out[index_lower] = (uint8)(sqrt((double)(sum_SqWUI / sum_SqW)) + 0.5);
00656         SU_out[index_lower] = samples;
00657       }
00658       else
00659       {
00660         SI_out[index_lower] = AGGREGATION_FAIL_SI;
00661         UI_out[index_lower] = BAD_DATA_UI;
00662         SU_out[index_lower] = 0;
00663       }
00664     }
00665   }
00666 
00667   return(MODIS_S_OK);
00668 }
00669 
00670 PGSt_SMF_status Read_L1A_EV_Scan (int16            S,
00671                                   L1A_granule_t    *L1A_Gran,
00672                                   L1A_Scan_t       *L1A_Scan)
00673 /*
00674 !C**************************************************************************
00675 !Description:
00676    For the input scan index, S, this routine reads earth-view (EV) scaled
00677    integer data for each of the four L1A EV SDSs: EV_250m, EV_500m,
00678    EV_1km_day, and EV_1km_night.  If the scan is not a "Day" mode scan,
00679    then only the data from the EV_1km_night SDS is read.
00680 
00681 !Input Parameters:
00682    int16            S           current scan index
00683    L1A_granule_t    *L1A_Gran   contains day-night flag, number of scans
00684                                 and valid SDS ids for each L1A EV SDS.
00685 
00686 !Output Parameters:
00687    L1A_Scan_t       *L1A_Scan   filled SDS data for all resolutions of 1 scan
00688 
00689 !Revision History:
00690  (continue at top of the file)
00691 
00692    Revision 02.1.2, January 22, 2001
00693    Corrected variable names and simplified the logic within this function
00694    to remove unnecessary lines. Added design notes.
00695    Jim Rogers (rogers@mcst.gsfc.nasa.gov)
00696 
00697    Revision 02.1.1 July 1997
00698    Modified to match change in L1A_Scan_t;
00699    Zhenying Gu (zgu@ltpmail.gsfc.nasa.gov)
00700 
00701    Revision 02.00 March 1997
00702    Modified to match change in L1A_Scan_t;
00703    limited processing to EV data.
00704    Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
00705 
00706    (Neal's version between 01.01 & 02.00......???)
00707 
00708    Revision 01.01 1996/04/05
00709    Update to match Version 1 Design Document
00710    John Hannon(hannon@highwire.gsfc.nasa.gov)
00711    Joan Baden (baden@highwire.gsfc.nasa.gov)
00712 
00713    Revision 01.00 1993
00714    Initial development
00715    Geir E. Kvaran(geir@highwire.gsfc.nasa.gov)
00716 
00717 !Team-unique Header:
00718    This software is developed by the MODIS Characterization Support
00719    Team (MCST)for the National Aeronautics and Space Administration,
00720    Goddard Space Flight Center, under contract NAS5-32373.
00721 
00722 !References and Credits:
00723    HDF portions developed at the National Center for Supercomputing
00724    Applications at the University of Illinois at Urbana-Champaign.
00725 
00726 !Design Notes:
00727    1.  We only need to read the 250m, 500m and 1km_day SDS data if the scan
00728        is a "Day" scan, according to the day-night flag.  We always read the
00729        1km_night data.
00730    2.  The L1A SDSs are oversized in terms of the number of frames.  We
00731        read the full set of data for 1 scan to make the internal read
00732        more efficient (each call will read one stream of data from the file
00733        rather than having to read many disjointed streams of data).
00734 !END************************************************************************
00735 */
00736 {
00737   int16  R;                     /* L1A resolution index */
00738   int16  D;                     /* Detector index */
00739   int16  B;                     /* Band index */
00740   int32  start[3] = {0, 0, 0};  /* starting indices, each dimension */
00741                                 /* (must be initialized to zero) */
00742   int32  edge[3];               /* # of elements to read, each dimension */
00743   intn   hdf_return;
00744   char   *location = "Read_L1A_EV_Scan";    /* This function name */
00745   int16  *ev_data_p[NUM_L1A_RESOLUTIONS];   /* pointers to each SDS data */
00746   int32 offset;
00747 
00748   /*
00749    * Check gross validity of inputs.
00750    */
00751 
00752   if (S < 0 || S >= L1A_Gran->num_scans || !L1A_Scan || !L1A_Gran) {
00753     L1BErrorMsg(location, MODIS_F_INVALID_ARGUMENT,
00754                 "Scan index (S), L1A_Gran or L1A_Scan value is invalid.",
00755                 NULL, FIRST_L1A_GRANULE, NULL, True);
00756     return MODIS_F_INVALID_ARGUMENT;
00757   }
00758 
00759   /*
00760    * Assign data pointers.
00761    */
00762 
00763   ev_data_p[INDEX_250M]        = (int16 *) L1A_Scan->EV_250m;
00764   ev_data_p[INDEX_500M]        = (int16 *) L1A_Scan->EV_500m;
00765   ev_data_p[INDEX_1000M_DAY]   = (int16 *) L1A_Scan->EV_1km_day;
00766   ev_data_p[INDEX_1000M_NIGHT] = (int16 *) L1A_Scan->EV_1km_night;
00767 
00768   /*
00769    * Loop through L1A resolutions and read one scan of L1A data.
00770    * (see design notes regarding which SDSs to read).
00771    */
00772 
00773   for (R = 0; R < NUM_L1A_RESOLUTIONS; R++)
00774   {
00775     if ((RFLAG & (1 << R)) != 0) continue;
00776 
00777     if (strcmp(L1A_Gran->ScanType[S],"Day") == SAME ||
00778         R == INDEX_1000M_EMISS)
00779     {
00780 
00781       if (L1A_Gran->Extract_Pixel_Offset == -1 && 
00782           L1A_Gran->Extract_Pixel_Count == -1) {
00783 
00784       start[0] = S * DETECT_PER_BAND_AT_RES[R];
00785       edge[0]  = DETECT_PER_BAND_AT_RES[R];
00786       edge[1]  = L1A_BANDS_AT_RES[R];
00787       edge[2]  = EV_1km_FRAMES * BAND_RATIO_AT_RES[R];
00788 
00789       hdf_return = SDreaddata (L1A_Scan->sds_id[R], start, NULL, edge,
00790                                ev_data_p[R]);
00791       if (hdf_return == FAIL) {
00792         char errmsg[256];
00793         char *resnames[NUM_L1A_RESOLUTIONS] = {
00794           "250m", "500m", "1km_day", "1km_night"
00795         };
00796         sprintf (errmsg, "Could not read L1A SDS: EV_%s.", resnames[R]);
00797         L1BErrorMsg(location, MODIS_F_READ_ERROR, errmsg,
00798                     "SDreaddata", FIRST_L1A_GRANULE, NULL, True);
00799         return MODIS_F_READ_ERROR;
00800       }
00801       } else {
00802 
00803         /* Clear buffer */
00804         memset(ev_data_p[R], 0, DETECT_PER_BAND_AT_RES[R] * L1A_BANDS_AT_RES[R] *
00805                EV_1km_FRAMES * BAND_RATIO_AT_RES[R]);
00806 
00807         for (D = 0; D < DETECT_PER_BAND_AT_RES[R]; D++)
00808 
00809           for (B = 0; B < L1A_BANDS_AT_RES[R]; B++) {
00810             start[0] = S*DETECT_PER_BAND_AT_RES[R] + D;
00811             start[1] = B;
00812             start[2] = 0;
00813             edge[0]  = 1;
00814             edge[1]  = 1;
00815             edge[2]  = L1A_Gran->Extract_Pixel_Count * BAND_RATIO_AT_RES[R];
00816 
00817             offset = (D*L1A_BANDS_AT_RES[R]*EV_1km_FRAMES +
00818                       B*EV_1km_FRAMES + L1A_Gran->Extract_Pixel_Offset) *
00819                       BAND_RATIO_AT_RES[R];
00820 
00821             hdf_return = SDreaddata (L1A_Scan->sds_id[R], start, NULL, edge,
00822                                      &ev_data_p[R][offset]);
00823           }
00824       }
00825     }
00826   }
00827 
00828   return MODIS_S_OK;
00829 }
00830 
00831 
00832 #include <string.h>  /* for the strcat function */
00833 
00834 int safe_strcat(char *buf, char *str, int buflen)
00835 /*
00836 !C*****************************************************************************
00837 !Description:
00838    Safely concatenate a string onto a buffer.  If neccessary, truncate the
00839    string to fit onto the end of the buffer, allowing a null to be at the end.
00840    Return values:
00841      0: the string was completely and successfully concatenated onto the end
00842         of the buffer.
00843      1: the buffer did not exist, the string did not exist or the buffer was
00844         to small to hold the entire string -- in which case as many characters
00845         as possible from the string are concatenated onto the end of the buffer.
00846 
00847 !Input Parameters:
00848    char *buf       Buffer holding characters to which we are concatenating
00849                    a string onto the end of.
00850    char *str       The string to be placed at the end of the buffer.
00851    int  buflen     The memory length of the buffer (not the string length).
00852 
00853 !Output Parameters:
00854    (none)
00855 
00856 !Revision History:
00857  (continue at top of the file)
00858 
00859    Revision 1.0.1  January 17, 2002   Razor Issue #172
00860    Improve portability of code to 64-bit mode.
00861    Change variables j, nb, and ns to type size_t.
00862    Alice Isaacman, SAIC GSO  (Alice.R.Isaacman.1@gsfc.nasa.gov)
00863    
00864    Revision 1.0 Nov. 1, 1999
00865    Initial development.
00866    Jim Rogers (rogers@mcst.gsfc.nasa.gov)
00867 
00868 !Team-unique Header:
00869    This software is developed by the MODIS Characterization Support
00870    Team (MCST)for the National Aeronautics and Space Administration,
00871    Goddard Space Flight Center, under contract NAS5-32373.
00872 
00873 !References and Credits:
00874    HDF portions developed at the National Center for Supercomputing
00875    Applications at the University of Illinois at Urbana-Champaign.
00876 
00877 !Design Notes:
00878 
00879 
00880 !END******************************************************************************
00881 */
00882 {
00883   int i;           /* indexes */
00884   size_t j;
00885   size_t nb;       /* string length of buf */
00886   size_t ns;       /* string length of str */
00887   int mx;          /* maximum number of non-null chars allowed in buffer */
00888 
00889   if (!buf || !str || buflen <= 0) return 1;
00890 
00891     /* Compute total length of required memory. */
00892 
00893   nb = strlen(buf);
00894   ns = strlen(str);
00895   if ((nb + ns) < buflen) {
00896     strcat(buf, str);
00897     return 0;
00898   }
00899   else {
00900     mx = buflen - 1;
00901     for (i = 0, j = nb; j < mx; i++, j++) buf[j] = str[i];
00902     buf[mx] = '\0';
00903     return 1;
00904   }
00905 }
00906 
00907 
00908 /*
00909  * The following are global values to use for the "other_msg" input to
00910  * L1BErrorMsg. These errors may occur many times.
00911  */
00912 
00913 char Invalid_MOD01_Msg[] = "\
00914 The MOD01 granule appears to be invalid.  Data values are present\n\
00915 that are not allowed by the MOD01 file specifications.";
00916 
00917 
00918 void L1BErrorMsg(
00919   char *L1B_location,    /* name of L1B function that error occurred in */
00920   PGSt_SMF_code code,    /* associated error code for this error */
00921   char *input_message,   /* short (usually 1-line) description of error */
00922   char *assoc_function,  /* name of an associated function that failed */
00923   int32 lun,             /* associated LUN for the file being accessed */
00924   char *other_msg,       /* other message to add such as probable cause */
00925   boolean error_out      /* flag to tell whether or not to call SMF_ERROR */
00926 )
00927 /*
00928 !C**********************************************************************
00929 !Description:
00930    Format an error message and write it to the LogReport and LogStatus
00931    files. If the flag "error_out" is True, then also call SMF_ERROR.
00932    Otherwise, this function will simply return to continue processing.
00933    The general form of the message created is:
00934 
00935    ERROR in [L1B_location]():
00936    [input_message]
00937    Call to [assoc_function]() failed.
00938    File LUN: [lun] ([type of file for this LUN])
00939    [other_msg]
00940 
00941    If an input is NULL (for char *) or zero (for int32), then that part of
00942    the message is not included.
00943 
00944 !Input Parameters:
00945    char *L1B_location    name of L1B function that error occurred in
00946    PGSt_SMF_code code    associated error code for this error
00947    char *input_message   short (usually 1-line) description of error
00948    char *assoc_function  name of an associated function that failed
00949    int32 LUN             associated LUN for the file being accessed
00950    char *other_msg       other message to add such as probable cause
00951    boolean error_out     flag to tell whether or not to call SMF_ERROR 
00952 
00953 !Output Parameters:
00954    (none)
00955 
00956 !Revision History:
00957  (continue at top of the file)
00958 
00959    Revision 1.02  October 16, 2004  Razor Issue #200
00960    Casted Int32 variables in sprintf calls to "long" with the
00961    format specifier "%ld" for better code portability.
00962    Liqin Tan, SAIC GSO  (ltan@saicmodis.com)
00963 
00964    Revision 1.01  August 15, 2002
00965    Add messages regarding "ProcessingEnvironment", "MCST LUT Version", 
00966    and "Write_Night_Mode_HiRes_Data".
00967    Alice Isaacman, SAIC GSO   (Alice.R.Isaacman.1@gsfc.nasa.gov)
00968 
00969    Revision 1.0 Nov. 4, 1999
00970    Initial development.
00971    Jim Rogers (rogers@mcst.gsfc.nasa.gov)
00972 
00973 !Team-unique Header:
00974    This software is developed by the MODIS Characterization Support
00975    Team (MCST)for the National Aeronautics and Space Administration,
00976    Goddard Space Flight Center, under contract NAS5-32373.
00977 
00978 !References and Credits:
00979    HDF portions developed at the National Center for Supercomputing
00980    Applications at the University of Illinois at Urbana-Champaign.
00981 
00982 !Design Notes:
00983    The messages going to the LogStatus and LogReport are formatted to 
00984    look similar to each other.
00985 
00986    The message size should be smaller than PGS_SMF_MAX_MSGBUF_SIZE
00987    due to internal limits in PGS_SMF_SetDynamicMsg.  This routine will
00988    fill up the message buffer until there is no more room and then
00989    call PGS_SMF_SetDynamicMsg.  Thus, a message may appear truncated.
00990 
00991    The same size message buffer is assumed for the LogReport message.
00992    This could result in the LogReport message being truncated from the
00993    message written to the log status file (since the L1B_location is added
00994    at the beginning of the LogReport file).
00995 
00996    This restriction may not be necessary.  The source code for
00997    PGS_SMF_GenerateStatusReport does not appear to have any string
00998    length restrictions.
00999 
01000    The lun (if one of the list of L1B LUNs) is used to determine the
01001    the category of the file (e.g., QA_Lookup_Tables_file).
01002 
01003    All "Concatenate" operations will use the "safe_strcat" function that
01004    ensures that the string can be concatenated onto the end and that flags
01005    when a message is truncated.
01006 
01007 !END********************************************************************
01008 */
01009 {
01010   PGSt_SMF_status returnStatus;           /* Return value for some PGS functs */
01011   char msg[PGS_SMF_MAX_MSGBUF_SIZE];      /* Buffer for LogStatus message */
01012   char report[PGS_SMF_MAX_MSGBUF_SIZE];   /* Buffer for LogReport message */
01013   char lunstr[PGS_SMF_MAX_MSGBUF_SIZE];   /* Buffer for LUN string */
01014   char category[PGS_SMF_MAX_MSGBUF_SIZE]; /* Buffer for file category */
01015   PGSt_SMF_boolean internal_failure;      /* Flags internal function failure. */
01016 
01017   /*
01018    * First, format the message to be written to the LogStatus file.
01019    * The L1B function name is not needed for that message (it is an argument
01020    * to the PGS_SMF_SetDynamicMsg function).
01021    */
01022 
01023   /* initialize the message buffer */
01024 
01025   strcpy(msg, "");
01026 
01027     /* Add the specific input message */
01028 
01029   if (input_message) {
01030     safe_strcat(msg, input_message, PGS_SMF_MAX_MSGBUF_SIZE);
01031     if (msg[strlen(msg)-1] != '\n')
01032       safe_strcat(msg, "\n", PGS_SMF_MAX_MSGBUF_SIZE);
01033   }
01034 
01035     /* Add the associated function name */
01036 
01037   if (assoc_function) {
01038     safe_strcat(msg, "Call to ", PGS_SMF_MAX_MSGBUF_SIZE);
01039     safe_strcat(msg, assoc_function, PGS_SMF_MAX_MSGBUF_SIZE);
01040     safe_strcat(msg, "() failed.\n", PGS_SMF_MAX_MSGBUF_SIZE);
01041   }
01042 
01043     /* Add the LUN information */
01044 
01045   if (lun != 0) {
01046     sprintf(lunstr, "File LUN:  %ld\nFile type: ", (long)lun);
01047     safe_strcat(msg, lunstr, PGS_SMF_MAX_MSGBUF_SIZE);
01048     switch (lun) {
01049       case MCF_FILE_QKM:           
01050         strcpy(category, "MOD02QKM MCF\n");                         break;
01051       case MCF_FILE_HKM:           
01052         strcpy(category, "MOD02HKM MCF\n");                         break;
01053       case MCF_FILE_1KM:           
01054         strcpy(category, "MOD021KM MCF\n");                         break;
01055       case MCF_FILE_OBC:           
01056         strcpy(category, "MOD02OBC MCF\n");                         break;
01057       case L1B_EV_250M_FILE:       
01058         strcpy(category, "MOD02QKM output granule\n");              break;
01059       case L1B_EV_500M_FILE:       
01060         strcpy(category, "MOD02HKM output granule\n");              break;
01061       case L1B_EV_1000M_FILE:      
01062         strcpy(category, "MOD021KM output granule\n");              break;
01063       case L1B_OBC_FILE:           
01064         strcpy(category, "MOD02OBC output granule\n");              break;
01065       case REFLECTIVE_TABLES_FILE: 
01066         strcpy(category, "Reflective_Lookup_Tables_file\n");        break;
01067       case EMISSIVE_TABLES_FILE:   
01068         strcpy(category, "Emissive_Lookup_Tables_file\n");          break;
01069       case QA_TABLES_FILE:         
01070         strcpy(category, "QA_Lookup_Tables_file\n");                break;
01071       case LEADING_L1A_GRANULE:    
01072         strcpy(category, "previous MOD01 input granule\n");         break;
01073       case FIRST_L1A_GRANULE:      
01074         strcpy(category, "current MOD01 input granule\n");          break;
01075       case TRAILING_L1A_GRANULE:   
01076         strcpy(category, "following MOD01 input granule\n");        break;
01077       case GEOLOCATION_FILE:       
01078         strcpy(category, "MOD03 input granule\n");                  break;
01079       case PROCESSING_ENVIRONMENT_LUN: strcpy(category, 
01080           "PCF File; ProcessingEnvironment; not required.\n");      break;      
01081       case MCST_LUT_VERSION_LUN: strcpy(category, 
01082           "PCF File; invalid MCSTLUTVersion value\n");              break;
01083       case WRITE_NIGHT_HIRES_LUN: strcpy(category, 
01084           "PCF File; invalid Write_Night_Mode_HiRes_Data value\n"); break;
01085       default:                     
01086         strcpy(category, "invalid value, L1B defect\n");            break;
01087     }
01088     safe_strcat(msg, category, PGS_SMF_MAX_MSGBUF_SIZE);
01089     
01090   }
01091 
01092   /*
01093    * Add the other message
01094    */
01095 
01096   if (other_msg) {
01097     safe_strcat(msg, other_msg, PGS_SMF_MAX_MSGBUF_SIZE);
01098   }
01099 
01100   /*
01101    * Write the message to the LogStatus file.
01102    */
01103 
01104   internal_failure = PGS_FALSE;
01105   returnStatus = PGS_SMF_SetDynamicMsg(code, msg, L1B_location);
01106   if (returnStatus != PGS_S_SUCCESS)
01107     internal_failure = PGS_TRUE;
01108 
01109   /*
01110    * Now format the same message to be written to the LogReport file.
01111    * Make the appearance of the message similar in the LogReport file.
01112    */
01113 
01114   strcpy(report, "");
01115 
01116     /* Add the L1B location */
01117 
01118   if (L1B_location) 
01119   {
01120     safe_strcat(report, L1B_location, PGS_SMF_MAX_MSGBUF_SIZE);
01121     safe_strcat(report, "():", PGS_SMF_MAX_MSGBUF_SIZE);
01122   }
01123   else 
01124   {
01125     safe_strcat(report, ":", PGS_SMF_MAX_MSGBUF_SIZE);
01126   }
01127 
01128   /* Add the textual and numerical equivalents of the exit code. */
01129 
01130   switch (code) {
01131     case MODIS_F_OUT_OF_MEMORY:
01132       safe_strcat(report, "MODIS_F_OUT_OF_MEMORY:", 
01133           PGS_SMF_MAX_MSGBUF_SIZE); break;
01134     case MODIS_F_MEM_FREE_FAIL:
01135       safe_strcat(report, "MODIS_F_MEM_FREE_FAIL:", 
01136           PGS_SMF_MAX_MSGBUF_SIZE); break;
01137     case MODIS_F_FILE_NOT_FOUND:
01138       safe_strcat(report, "MODIS_F_FILE_NOT_FOUND:", 
01139           PGS_SMF_MAX_MSGBUF_SIZE); break;
01140     case MODIS_F_READ_ERROR:
01141       safe_strcat(report, "MODIS_F_READ_ERROR:", 
01142           PGS_SMF_MAX_MSGBUF_SIZE); break;
01143     case MODIS_F_WRITE_ERROR:
01144       safe_strcat(report, "MODIS_F_WRITE_ERROR:", 
01145           PGS_SMF_MAX_MSGBUF_SIZE); break;
01146     case MODIS_F_OUT_OF_RANGE:
01147       safe_strcat(report, "MODIS_F_OUT_OF_RANGE:", 
01148           PGS_SMF_MAX_MSGBUF_SIZE); break;
01149     case MODIS_W_OUT_OF_RANGE:
01150       safe_strcat(report, "MODIS_W_OUT_OF_RANGE:", 
01151           PGS_SMF_MAX_MSGBUF_SIZE); break;
01152     case MODIS_W_TIME_INCORRECT:
01153       safe_strcat(report, "MODIS_W_TIME_INCORRECT:", 
01154           PGS_SMF_MAX_MSGBUF_SIZE); break;
01155     case MODIS_F_NOK:
01156       safe_strcat(report, "MODIS_F_NOK:", 
01157           PGS_SMF_MAX_MSGBUF_SIZE); break;
01158     case MODIS_F_HDF_ERROR:
01159       safe_strcat(report, "MODIS_F_HDF_ERROR:", 
01160           PGS_SMF_MAX_MSGBUF_SIZE); break;
01161     case MODIS_F_NO_MORE:
01162       safe_strcat(report, "MODIS_F_NO_MORE:", 
01163           PGS_SMF_MAX_MSGBUF_SIZE); break;
01164     case MODIS_S_NO_MORE:
01165       safe_strcat(report, "MODIS_S_NO_MORE:", 
01166           PGS_SMF_MAX_MSGBUF_SIZE); break;
01167     case MODIS_F_FILE_NOT_OPENED:
01168       safe_strcat(report, "MODIS_F_FILE_NOT_OPENED:", 
01169           PGS_SMF_MAX_MSGBUF_SIZE); break;
01170     case MODIS_F_FILE_NOT_CREATED:
01171       safe_strcat(report, "MODIS_F_FILE_NOT_CREATED:", 
01172           PGS_SMF_MAX_MSGBUF_SIZE); break;
01173     case MODIS_F_INVALID_ARGUMENT:
01174       safe_strcat(report, "MODIS_F_INVALID_ARGUMENT:", 
01175           PGS_SMF_MAX_MSGBUF_SIZE); break;
01176     case MODIS_E_TESTING:
01177       safe_strcat(report, "MODIS_E_TESTING:", 
01178           PGS_SMF_MAX_MSGBUF_SIZE); break;
01179     case MODIS_S_OK:
01180       safe_strcat(report, "MODIS_S_OK:", 
01181           PGS_SMF_MAX_MSGBUF_SIZE); break;
01182     default:
01183       safe_strcat(report, "UNKNOWN_CODE:", 
01184           PGS_SMF_MAX_MSGBUF_SIZE); break;
01185   }
01186   sprintf(lunstr, "%d\n", code);
01187   safe_strcat(report, lunstr, PGS_SMF_MAX_MSGBUF_SIZE);
01188 
01189   /*
01190    * Add the previously formatted message written to LogStatus file.
01191    * Write the total message to the LogReport file.
01192    */
01193 
01194   safe_strcat(report, msg, PGS_SMF_MAX_MSGBUF_SIZE);
01195   returnStatus = PGS_SMF_GenerateStatusReport(report);
01196   if (returnStatus != PGS_S_SUCCESS)
01197     internal_failure = PGS_TRUE;
01198 
01199   /*
01200    * If there is an internal failure, write fatal error message and
01201    * error out.  (The way that SMF_ERROR is designed, the error message
01202    * will probably not get written anyway.)
01203    */
01204 
01205   if (internal_failure == PGS_TRUE) 
01206   {
01207     SMF_ERROR(MODIS_F_NOK,
01208       "Fatal error in HDFFuncErrorMsg:  Failed to write to\n"
01209       "PGS_SMF_SetDynamicMsg or to PGS_SMF_GenerateStatusReport");
01210   }
01211 
01212   /*
01213    * Call SMF_ERROR to error out if the flag is set to True.
01214    */
01215 
01216   if (error_out == True)
01217     SMF_ERROR(code, NULL);
01218 }
01219 
01220 
01221 /*
01222  * The following variable contains error message information used in
01223  * SMF_ERROR.  The first entry in the variable is the
01224  * default (in case of input error) and the last entry in the table
01225  * must be NULL.
01226  */
01227 
01228   static struct 
01229   {
01230     char *name;         /* macro name of the error code */
01231     int32 value;        /* numerical value of the code */
01232     char *actions;      /* operator actions to take */
01233   } err_msg_info[] = 
01234   {
01235 
01236     { "MODIS_F_NOK",              MODIS_F_NOK, "\
01237   Operator Actions:\n\
01238   Contact MCST.\n"
01239     },
01240 
01241     { "MODIS_F_OUT_OF_MEMORY",    MODIS_F_OUT_OF_MEMORY, "\
01242   Operator Actions:\n\
01243   Check the system health to see if it is overloaded.\n\
01244   Try re-running the PGE with system loading reduced.\n\
01245   Contact MCST.\n"
01246     },
01247 
01248     { "MODIS_F_MEM_FREE_FAIL",    MODIS_F_MEM_FREE_FAIL, "\
01249   Operator Actions:\n\
01250   Contact MCST.\n"
01251     },
01252 
01253     { "MODIS_F_FILE_NOT_FOUND",   MODIS_F_FILE_NOT_FOUND, "\
01254   Operator Actions:\n\
01255   Check previous messages to identify LUN of the file and other possible causes.\n\
01256   Check the PCF file to ensure that UR exists and PCF format is correct.\n\
01257   Check the PCF file to ensure that file names and directories are correct.\n\
01258   Contact MCST.\n"
01259     },
01260 
01261     { "MODIS_F_READ_ERROR",       MODIS_F_READ_ERROR, "\
01262   Operator Actions:\n\
01263   Check previous messages to identify LUN of the file and other possible causes.\n\
01264   Check the PCF file to ensure that file names and directories are correct.\n\
01265   Check the file type and size to see if it is consistent with file category.\n\
01266   Contact MCST.\n"
01267     },
01268 
01269     { "MODIS_F_WRITE_ERROR",      MODIS_F_WRITE_ERROR, "\
01270   Operator Actions:\n\
01271   Check previous messages to identify LUN of the file and other possible causes.\n\
01272   Check the PCF file to ensure that file names and directories are correct.\n\
01273   Check available system disk space.\n\
01274   Check to see if file has been moved or corrupted during execution.\n\
01275   Contact MCST.\n"
01276     },
01277 
01278     { "MODIS_F_OUT_OF_RANGE",     MODIS_F_OUT_OF_RANGE, "\
01279   Operator Actions:\n\
01280   Check previous messages to identify LUN of the file and other possible causes.\n\
01281   Contact MCST.\n\
01282   Also contact SDST if the LUN corresponds to a MOD01 or MOD03 granule.\n"
01283     },
01284 
01285     { "MODIS_W_OUT_OF_RANGE",     MODIS_W_OUT_OF_RANGE, "\
01286   Operator Actions:\n\
01287   Contact MCST.\n"
01288     },
01289 
01290     { "MODIS_W_TIME_INCORRECT",   MODIS_W_TIME_INCORRECT, "\
01291   Operator Actions:\n\
01292   Check Leap Seconds and other toolkit files and environment variables.\n\
01293   Notify L1B product users that time in product may be incorrect.\n\
01294   Contact MCST.\n"
01295     },
01296 
01297     { "MODIS_F_HDF_ERROR",        MODIS_F_HDF_ERROR, "\
01298   Operator Actions:\n\
01299   Check previous messages to identify LUN of the file and other possible causes.\n\
01300   Contact MCST.\n"
01301     },
01302 
01303     { "MODIS_F_NO_MORE",          MODIS_F_NO_MORE, "\
01304   Operator Actions:\n\
01305   Contact MCST.\n"
01306     },
01307 
01308     { "MODIS_S_NO_MORE",          MODIS_S_NO_MORE, NULL },
01309 
01310     { "MODIS_F_FILE_NOT_OPENED",  MODIS_F_FILE_NOT_OPENED, "\
01311   Operator Actions:\n\
01312   Check previous messages to identify LUN of the file and other possible causes.\n\
01313   Check the PCF file to ensure that file names and directories are correct.\n\
01314   Contact MCST.\n"
01315     },
01316 
01317     { "MODIS_F_FILE_NOT_CREATED", MODIS_F_FILE_NOT_CREATED, "\
01318   Operator Actions:\n\
01319   Check previous messages to identify LUN of the file and other possible causes.\n\
01320   Check the PCF file to ensure that file names and directories are correct.\n\
01321   Check file permissions of the system.\n\
01322   Contact MCST.\n"
01323     },
01324 
01325     { "MODIS_F_INVALID_ARGUMENT", MODIS_F_INVALID_ARGUMENT, "\
01326   Operator Actions:\n\
01327   Contact MCST.\n"
01328     },
01329 
01330     { "MODIS_E_TESTING",          MODIS_E_TESTING, "\
01331   Operator Actions:\n\
01332   Contact MCST.\n"
01333     },
01334 
01335     { "MODIS_S_OK",               MODIS_S_OK, NULL },
01336 
01337     { NULL, 0, NULL }       /*** Must be NULL terminated ***/
01338   };
01339 
01340 
01341 void SMF_ERROR (PGSt_SMF_code code, char *messagestring)
01342 /*
01343 !C**************************************************************************
01344 !Description:
01345    Provides the interface to the Status Message Facility in the SDP Toolkit.
01346    A message is formed using the format string from the L1B "seed" file,
01347    the input message string and the local time.  The message is written to
01348    both the LogStatus file and the LogReport file.  Additionally, operator
01349    actions are written as the last messages to the files.
01350 
01351    IMPORTANT: This function will invoke "exit" for fatal error codes or
01352    internal failures that should not occur (such as the environment or
01353    seed messages do not function).  See other comments in design notes.
01354 
01355 !Input Parameters:
01356    PGSt_SMF_code code          One of the L1B message codes defined in
01357                                PGS_Error_Codes.h" and in the seed file.
01358    char *       messagestring  A string which contains a specific error
01359                                message.  The function name should be already
01360                                part of the string, if appropriate.
01361 
01362 !Output Parameters:
01363    (none)
01364 
01365 !Revision History:
01366  (continue at top of the file)
01367 
01368    Revision 2.0.1  January 17, 2002   Razor Issue #172
01369    Improve portability of code to 64-bit mode.
01370    Change variable n to type size_t.  Use n instead of i in strlen operations.
01371    Alice Isaacman, SAIC GSO  (Alice.R.Isaacman.1@gsfc.nasa.gov)
01372 
01373    Revision 02.00 Oct. 27, 1999
01374    Added checks on input validity (NULL, string length).  Reformatted
01375    message so that it does not appear all on one line.  Added "MOD_PR02"
01376    to the beginning to distinguish the source from other processes that
01377    may write to the same Log files.  Added additional error messages and
01378    warnings.  Function was completely restructured. Added design notes.
01379    Jim Rogers (rogers@mcst.gsfc.nasa.gov)
01380 
01381    Revision 01.00 199604/05
01382    Initial development, new function for Version 1.
01383    John Hannon(hannon@highwire.gsfc.nasa.gov)
01384 
01385 !Team-unique Header:
01386    This software is developed by the MODIS Characterization Support
01387    Team (MCST)for the National Aeronautics and Space Administration,
01388    Goddard Space Flight Center, under contract NAS5-32373.
01389 
01390 !References and Credits:
01391    This routine is based on the CHECK_ERR function used by Geir Kvaran
01392    in the Beta version of the code.
01393    HDF portions developed at the National Center for Supercomputing
01394    Applications at the University of Illinois at Urbana-Champaign.
01395 
01396 !Design Notes:
01397 
01398  The final form of the message consists of three parts, concatenated together:
01399  1. leading part: string from the seed file associated with this code
01400  2. middle part:  the input "messagestring"
01401  3. last part:    the local time that the error occurred
01402  Note that the string from the seed file actually is the format string for the
01403  sprintf function (it has two "%s" fields for the middle and trailing parts).
01404 
01405  If the total message is too large to fit into the maximum size allowed by the
01406  Toolkit (PGS_SMF_MAX_MSGBUF_SIZE - 1), then the user supplied message is
01407  truncated so that it will fit.  In this case, the process will exit only if the
01408  original message code was fatal.
01409 
01410  Side effect:  The input messagestring may be modified by this function if the
01411  string length is too long.  Thus, the calling function should not plan on using
01412  the string afterward.
01413 
01414  For a NULL or zero-length messagestring, assume that the seed file message is
01415  the complete message.
01416 
01417  Note: The following conditions could cause an exit invocation:
01418  1.  The input "code" corresponds to a fatal error, or
01419  2.  There is an internal failure inside this function.
01420  An internal failure is a failure of one of the PGS toolkit functions.  Other
01421  errors that occur may generate warnings, but will not halt the process
01422  in and of themselves. 
01423 
01424  Depending on the internal failure, there may be no error messages written.
01425  If absolutely no message of any kind comes out, perhaps the LogStatus and
01426  LogReport files are not set properly in the PCF.
01427 
01428 !END***************************************************************************
01429 */
01430 {
01431   PGSt_SMF_status returnStatus;          /* Return value for some PGS functs */
01432   char msgfmt[PGS_SMF_MAX_MSGBUF_SIZE];  /* Holds the format retrieved from
01433                                           * the seed file (format associated with
01434                                           * the particular input error code).
01435                                           */
01436 #define ASCTIMEBUF 26
01437   char timestr[ASCTIMEBUF];              /* Holds the local time in a string.
01438                                           * The time function "asctime_r" sets a
01439                                           * null-terminated string of length 25.
01440                                           */
01441   char msgstr[PGS_SMF_MAX_MSGBUF_SIZE];  /* Holds the modified input message (could
01442                                           * be truncated or have newlines added)
01443                                           */
01444   char buf[PGS_SMF_MAX_MSGBUF_SIZE];     /* Holds the final concatenated message. */
01445   struct tm *tptr;                       /* used in getting time string */
01446   time_t local;                          /* used in getting time string */
01447   PGSt_SMF_boolean internal_failure;     /* Flags any internal function failure. */
01448   size_t n;                               /* temporary variable */
01449 
01450   char *defaultmsgfmt = "Error running...%sTIME:%s";  /* backup value */
01451   PGSt_SMF_code internal_failure_code = MODIS_F_NOK;  /* value to use for internal
01452                                                        * failure.
01453                                                        */
01454   char *s;                               /* temporary variable */
01455   int32 i;                               /* loop index */
01456   int32 imsg;                            /* index in "err_mgs_info" for this code */
01457 
01458 /*************************** MACRO WRITE_MSG(c,m) *********************************
01459  Writes a string to both the LogStatus and LogReport.  For writing to the
01460  LogStatus, the function name is not input (set to NULL).  Note that if either
01461  call fails, then we probably will not get any messages at all.  There is one
01462  final check on the string length, although this should be OK.
01463     c = SMF message code
01464     m = message string to be written
01465 **********************************************************************************/
01466 #define WRITE_MSG(c,m)                               \
01467   if (strlen(m) > (PGS_SMF_MAX_MSGBUF_SIZE - 1)) {   \
01468     m[strlen(m)-1] = '\0';                           \
01469   }                                                  \
01470   returnStatus = PGS_SMF_SetDynamicMsg(c, m, NULL);  \
01471   if (returnStatus != PGS_S_SUCCESS)                 \
01472     internal_failure = PGS_TRUE;                     \
01473   returnStatus = PGS_SMF_GenerateStatusReport(m);    \
01474   if (returnStatus != PGS_S_SUCCESS)                 \
01475     internal_failure = PGS_TRUE;
01476 
01477   /******************* Begin code ***************/
01478 
01479   /*
01480    * Initialize flag to false.
01481    */
01482 
01483   internal_failure = PGS_FALSE;
01484 
01485   /*
01486    * Get the seed file message format string for this error code.
01487    */
01488 
01489   returnStatus = PGS_SMF_GetMsgByCode(code, msgfmt);
01490   if (returnStatus != PGS_S_SUCCESS)
01491   {
01492     char errmsg[] = "MOD_PR02 Warning in SMF_ERROR: Call to PGS_SMF_GetMsgByCode failed.\n"
01493                     "Seed file may not be set up properly or code is invalid.\n"
01494                     "The input message will be printed below and process will exit.\n";
01495     WRITE_MSG(internal_failure_code,errmsg);
01496     internal_failure = PGS_TRUE;
01497     strcpy(msgfmt, defaultmsgfmt);
01498   }
01499 
01500   /*
01501    * Form the local time and copy the time string into the timestr.
01502    * If the time functions fail, copy a small error message into the timestr.
01503    */
01504 
01505   local = time(NULL);
01506   tptr = localtime(&local);
01507   s = asctime(tptr);
01508   if (s)
01509   {
01510     strcpy(timestr, s);
01511   }
01512   else
01513   {
01514     strcpy(timestr,"WARNING: asctime failed");  /* this string must be < 26 chars! */
01515   }
01516   if (strlen(timestr) > (ASCTIMEBUF-1))
01517   {
01518     strcpy(timestr,"WARNING: asctime failed");  /* this string must be < 26 chars! */
01519   }
01520 
01521   /*
01522    * Put the input message into the msgstr.  Truncate if necessary.
01523    */
01524 
01525   if (!messagestring)
01526   {
01527     strcpy(msgstr, "MOD_PR02. ");
01528   }
01529   else if (!strlen(messagestring))
01530   {
01531     strcpy(msgstr, "MOD_PR02. ");
01532   }
01533   else
01534   {
01535     strcpy(msgstr, "MOD_PR02:");
01536     if (messagestring[0] != '\n')
01537       strcat(msgstr, "\n");
01538     n = PGS_SMF_MAX_MSGBUF_SIZE - 1 - strlen(msgfmt) - 
01539         strlen(timestr) - strlen(msgstr);
01540     if (strlen(messagestring) > n)
01541       messagestring[n] = '\0';
01542     strcat(msgstr, messagestring);
01543     n = strlen(msgstr);
01544     if (msgstr[n-1] != '\n')
01545       strcat(msgstr, "\n");
01546   }
01547 
01548   /*
01549    * Form the final message string.
01550    */
01551 
01552   sprintf(buf, msgfmt, msgstr, timestr);
01553 
01554   /*
01555    * Determine index of operator actions, based on exit code.
01556    */
01557 
01558   i = 0; imsg = 0;
01559   while (err_msg_info[i].name)
01560   {
01561     if (code == err_msg_info[i].value)
01562     {
01563       imsg = i;
01564       break;
01565     }
01566     i++;
01567   }
01568 
01569   /*
01570    * Determine string length of operator actions.
01571    */
01572 
01573   if (err_msg_info[imsg].actions)
01574     n = strlen(err_msg_info[imsg].actions);
01575   else
01576     n = 0;
01577 
01578   /*
01579    * If there is room, append the operator actions to the end of the message
01580    * buffer to be written.  Otherwise, write the message buffer and the write
01581    * the operator actions separately.
01582    */
01583 
01584   if (n == 0)
01585   {
01586     WRITE_MSG(code,buf);
01587   }
01588   else if ((strlen(buf)+n) < PGS_SMF_MAX_MSGBUF_SIZE)
01589   {
01590     strcat(buf, err_msg_info[imsg].actions);
01591     WRITE_MSG(code,buf);
01592   }
01593   else
01594   {
01595     WRITE_MSG(code,buf);
01596     WRITE_MSG(code,err_msg_info[imsg].actions);
01597   }
01598 
01599   /*
01600    * Test to see if the code corresponds to a fatal error or if there was any
01601    * internal failure and then exit.
01602    */
01603 
01604   if ((PGS_SMF_TestFatalLevel(code)) == PGS_TRUE || internal_failure == PGS_TRUE)
01605   {
01606 
01607     exit (MOD_PR02_Failure_Exit_Code);
01608 
01609   }
01610 }
01611 
01612 void Bad_L1A_Error_Out(char *name, char *message)
01613 /*
01614 !C*******************************************************************
01615 !Description:   This function posts a error message to log file including
01616                 the name of the data and the description of the problem
01617                 when bad L1A data are read.
01618 
01619 !Input Parameters:
01620      char *    name      the name of the data being read
01621      char *    message   error message
01622 
01623 !Output Parameters:
01624 
01625 !Revision History:
01626  (continue at top of the file)
01627 
01628  Revision 01.00 August 27, 1999
01629  Initial development
01630  Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
01631  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
01632 
01633 !Team-unique Header:
01634 
01635 !References and Credits:
01636    This software is developed by the MODIS Characterization Support
01637    Team (MCST)for the National Aeronautics and Space Administration,
01638    Goddard Space Flight Center, under contract NAS5-32373.
01639 
01640    HDF portions developed at the National Center for Supercomputing
01641    Applications at the University of Illinois at Urbana-Champaign.
01642 
01643 !Design Notes:
01644  
01645 
01646 !END********************************************************************
01647 */
01648 {
01649   char buffer [MAX_ERROR_MESSAGE_LENGTH];
01650   char *default_message = "Bad L1A data.\n";
01651   char *fmt = "\
01652 ERROR READING DATA FROM ONE OF THE MOD01 FILES INPUT TO PGE02.\n\
01653    Name of MOD01 data: %s\n\
01654    Error:              %s\n\
01655 This error is due to:\n\
01656 (1) the MOD01 file is corrupted,\n\
01657 (2) the process MOD_PR01 (in PGE01) has a bug in it, or\n\
01658 (3) there is an address bug in MOD_PR02.";
01659 
01660   if (strlen(fmt) + strlen(name) + strlen(message) < MAX_ERROR_MESSAGE_LENGTH)
01661     sprintf(buffer, fmt, name, message);
01662   else
01663     sprintf(buffer, "%s", default_message);
01664 
01665   SMF_ERROR(MODIS_F_NOK, buffer);
01666 }
01667 
01668 
01669 PGSt_SMF_status Write_L1B_EV_Scan (int16            S,
01670                                    L1B_granule_t    *L1B_Gran,
01671                                    L1B_Scan_t       *L1B_Scan,
01672                                    boolean          isdaymode)
01673 /*
01674 !C**********************************************************************
01675 !Description:
01676     This routine writes one scan of L1B EV data, including scaled integers,
01677     uncertainty indices and samples used, as appropriate.  For a day-mode
01678     scan, all resolutions are written.  For a night mode scan, only data
01679     for the emissive bands are written.
01680 
01681 !Input Parameters:
01682       int16            S              current scan index
01683       L1B_granule_t    *L1B_Gran
01684       L1B_Scan_t       *L1B_Scan
01685       boolean          isdaymode      Flag denoting that scan is a day mode scan
01686                                       (if True)
01687 !Output Parameters:
01688       
01689 !Revision History:
01690  (continue at top of the file)
01691 
01692  Revision 03.10 May 13, 1999
01693  Added band 26 section.
01694  Jim Rogers (rogers@mcst.gsfc.nasa.gov)
01695 
01696  Revision 03.00 March 1997
01697  Modified to match changes in L1B_Scan_t and in file spec; 
01698  limited processing to EV data. 
01699  Zhidong Hao (hao@barebackride.gsfc.nasa.gov)
01700 
01701  Revision 02.00 1996/06/28
01702  New version using SDS_Services           Currently corresponds to version 1 specification
01703  Neal Devine(neal.devine@gsfc.nasa.gov)
01704 
01705  Revision 01.01 1996/04/05
01706  Updated to match Version q Design Document
01707  Joan Baden(baden@highwire.gsfc.nasa.gov)
01708  John Hannon(hannon@highwire.gsfc.nasa.gov)
01709 
01710  Revision 01.00 1993
01711  Initial development
01712  Geir E. Kvaran(geir@highwire.gsfc.nasa.gov)
01713 
01714 !Team-unique Header:
01715 
01716 !References and Credits:
01717    This software is developed by the MODIS Characterization Support
01718    Team (MCST)for the National Aeronautics and Space Administration,
01719    Goddard Space Flight Center, under contract NAS5-32373.
01720 
01721    HDF portions developed at the National Center for Supercomputing
01722    Applications at the University of Illinois at Urbana-Champaign.
01723 
01724 !Design Notes:
01725    New version subsumes version 1 functions Write_L1B_PixelQuality, 
01726    Write_L1B_EngMem, and Write_L1B_Slice, which are no longer needed.
01727 
01728 !END********************************************************************
01729 */
01730 {
01731   PGSt_SMF_status returnStatus;
01732   int16    R            = 0;
01733   int32    start[3]     = {0, 0, 0};
01734   int32    edge[3]      = {0, 0, 0};
01735 
01736 /*------------------------------------------------------------------------------
01737   This macro writes a set of three EV_Aggr SDS's (SI & UI & SU)
01738 ------------------------------------------------------------------------------*/
01739 #define  WRITE_EV_Aggr_SDS(SI_id, SI, UI_id, UI, SU_id, SU)                    \
01740     if(SDwritedata(SI_id,start,NULL,edge,SI) == FAIL)         \
01741       return(MODIS_F_WRITE_ERROR);                                              \
01742     if(SDwritedata(UI_id,start,NULL,edge,UI) == FAIL)         \
01743       return(MODIS_F_WRITE_ERROR);                                              \
01744     if(SDwritedata(SU_id,start,NULL,edge,SU) == FAIL)         \
01745       return(MODIS_F_WRITE_ERROR)
01746 /*----------------------------------------------------------------------------*/
01747 
01748   if (S >= L1B_Gran->num_scans)
01749     return(MODIS_F_NO_MORE);
01750 
01751 /************************* Begin Band 26 Section **************************/
01752 #ifdef WRITE_BAND_26_SDS
01753       /*
01754        * Write this scan's worth of Band 26 data.  These are always written,
01755        * regardless of day or night.  Note that since these are 2D SDSs,
01756        * we pass in the address of start[1] and edge[1], since the last
01757        * two dimensions of the 3D EV SDSs are the same as the two 
01758        * dimensions for these SDSs.
01759        */
01760   start[1] = S * DETECT_PER_BAND_AT_RES[INDEX_1000M_REFL];
01761   edge[1]  = DETECT_PER_BAND_AT_RES[INDEX_1000M_REFL];
01762   edge[2]  = EV_1km_FRAMES * BAND_RATIO_AT_RES[INDEX_1000M_REFL];
01763   if (SDwritedata(L1B_Scan->Band26.SI_sds_id, &start[1], NULL, &edge[1],
01764                   (VOIDP)L1B_Scan->Band26.SI) == FAIL)
01765      return(MODIS_F_WRITE_ERROR);
01766   if (SDwritedata(L1B_Scan->Band26.UI_sds_id, &start[1], NULL, &edge[1],
01767                   (VOIDP)L1B_Scan->Band26.UI) == FAIL)
01768      return(MODIS_F_WRITE_ERROR);
01769 
01770 #endif /* WRITE_BAND_26_SDS */
01771 /************************** End Band 26 Section ***************************/
01772 
01773   for (R = 0; R < NUM_L1A_RESOLUTIONS; R++)
01774   {
01775     start[1] = S * DETECT_PER_BAND_AT_RES[R];
01776     edge[0]  = L1B_BANDS_AT_RES[R];
01777     edge[1]  = DETECT_PER_BAND_AT_RES[R];
01778     edge[2]  = EV_1km_FRAMES * BAND_RATIO_AT_RES[R];
01779     if (!isdaymode && R != INDEX_1000M_EMISS)
01780       continue;
01781 
01782     returnStatus = Write_L1B_SI_UI(S, L1B_Scan, R);
01783     if (returnStatus != MODIS_S_OK)
01784        SMF_ERROR(returnStatus, "Write_L1B_SI_UI() in Write_L1B_EV_Scan(), Granule.c"); 
01785 
01786     switch(R)
01787     {
01788       case INDEX_250M:
01789         break;
01790 
01791       case INDEX_500M:
01792         edge[0] = L1B_BANDS_AT_RES[INDEX_250M];
01793         WRITE_EV_Aggr_SDS (L1B_Scan->EV_250m_Aggr500m_RefSB_sds_id, 
01794                              L1B_Scan->EV_250m_Aggr500m_RefSB,
01795                            L1B_Scan->EV_250m_Aggr500m_RefSB_UI_sds_id, 
01796                              L1B_Scan->EV_250m_Aggr500m_RefSB_UI,
01797                            L1B_Scan->EV_250m_Aggr500m_RefSB_SU_sds_id, 
01798                              L1B_Scan->EV_250m_Aggr500m_RefSB_SU);
01799         break;
01800 
01801       case INDEX_1000M_REFL:
01802         edge[0] = L1B_BANDS_AT_RES[INDEX_250M];
01803         WRITE_EV_Aggr_SDS (L1B_Scan->EV_250m_Aggr1km_RefSB_sds_id, 
01804                              L1B_Scan->EV_250m_Aggr1km_RefSB,
01805                            L1B_Scan->EV_250m_Aggr1km_RefSB_UI_sds_id, 
01806                              L1B_Scan->EV_250m_Aggr1km_RefSB_UI,
01807                            L1B_Scan->EV_250m_Aggr1km_RefSB_SU_sds_id, 
01808                              L1B_Scan->EV_250m_Aggr1km_RefSB_SU);
01809 
01810         edge[0] = L1B_BANDS_AT_RES[INDEX_500M];
01811         WRITE_EV_Aggr_SDS (L1B_Scan->EV_500m_Aggr1km_RefSB_sds_id, 
01812                              L1B_Scan->EV_500m_Aggr1km_RefSB,
01813                            L1B_Scan->EV_500m_Aggr1km_RefSB_UI_sds_id, 
01814                              L1B_Scan->EV_500m_Aggr1km_RefSB_UI,
01815                            L1B_Scan->EV_500m_Aggr1km_RefSB_SU_sds_id, 
01816                              L1B_Scan->EV_500m_Aggr1km_RefSB_SU);
01817         break;
01818 
01819       case INDEX_1000M_EMISS:
01820         ;
01821     }/*End of switch*/
01822   }/*End of loop over R: L1A_resolution*/
01823 
01824   return(MODIS_S_OK);
01825 }
01826 
01827 
01828 PGSt_SMF_status Write_L1B_SI_UI (int16 S, L1B_Scan_t *L1B_Scan, int16 R)
01829 /*
01830 !C**********************************************************************
01831 !Description:
01832     For a given resolution, this routine writes one scan of L1B EV scaled
01833     integer and uncertainty index data to the appropriate L1B granule.
01834 
01835 !Input Parameters:
01836       int16            S              current scan index
01837       L1B_Scan_t       *L1B_Scan
01838       int16            R
01839 !Output Parameters:
01840       
01841 !Revision History:
01842  (continue at top of the file)
01843 
01844  Revision 01.00 1998
01845  Initial development
01846  Zhenying Gu(zgu@ltpmail.gsfc.nasa.gov)
01847 
01848 !Team-unique Header:
01849 
01850 !References and Credits:
01851    This software is developed by the MODIS Characterization Support
01852    Team (MCST)for the National Aeronautics and Space Administration,
01853    Goddard Space Flight Center, under contract NAS5-32373.
01854 
01855    HDF portions developed at the National Center for Supercomputing
01856    Applications at the University of Illinois at Urbana-Champaign.
01857 
01858 !Design Notes:
01859 
01860 !END********************************************************************
01861 */
01862 {
01863   int32    start[3]     = {0, 0, 0};
01864   int32    edge[3]      = {0, 0, 0};
01865   start[1] = S * DETECT_PER_BAND_AT_RES[R];
01866   edge[0]  = L1B_BANDS_AT_RES[R];
01867   edge[1]  = DETECT_PER_BAND_AT_RES[R];
01868   edge[2]  = EV_1km_FRAMES * BAND_RATIO_AT_RES[R];
01869   
01870   if ((RFLAG & (1 << R)) != 0) return(MODIS_S_OK);
01871   
01872   switch (R){
01873     case 0:
01874       if (SDwritedata(L1B_Scan->SI_sds_id[R], start, NULL, edge, 
01875                                (VOIDP)L1B_Scan->SI.EV_250m_RefSB) == FAIL)
01876          return(MODIS_F_WRITE_ERROR);
01877       if (SDwritedata(L1B_Scan->UI_sds_id[R], start, NULL, edge, 
01878                                (VOIDP)L1B_Scan->UI.EV_250m_RefSB_UI) == FAIL)
01879          return(MODIS_F_WRITE_ERROR);
01880       break;
01881     
01882     case 1:
01883       if (SDwritedata(L1B_Scan->SI_sds_id[R], start, NULL, edge, 
01884                                (VOIDP)L1B_Scan->SI.EV_500m_RefSB) == FAIL)
01885          return(MODIS_F_WRITE_ERROR);
01886       if (SDwritedata(L1B_Scan->UI_sds_id[R], start, NULL, edge, 
01887                                (VOIDP)L1B_Scan->UI.EV_500m_RefSB_UI) == FAIL)
01888          return(MODIS_F_WRITE_ERROR);
01889       break;
01890     
01891     case 2:
01892       if (SDwritedata(L1B_Scan->SI_sds_id[R], start, NULL, edge, 
01893                                (VOIDP)L1B_Scan->SI.EV_1km_RefSB) == FAIL)
01894          return(MODIS_F_WRITE_ERROR);
01895       if (SDwritedata(L1B_Scan->UI_sds_id[R], start, NULL, edge, 
01896                                (VOIDP)L1B_Scan->UI.EV_1km_RefSB_UI) == FAIL)
01897          return(MODIS_F_WRITE_ERROR);
01898       break;
01899 
01900     case 3: 
01901       if (SDwritedata(L1B_Scan->SI_sds_id[R], start, NULL, edge, 
01902                                (VOIDP)L1B_Scan->SI.EV_1km_Emissive) == FAIL)
01903          return(MODIS_F_WRITE_ERROR);
01904       if (SDwritedata(L1B_Scan->UI_sds_id[R], start, NULL, edge, 
01905                                (VOIDP)L1B_Scan->UI.EV_1km_Emissive_UI) == FAIL)
01906          return(MODIS_F_WRITE_ERROR);
01907       break;
01908 
01909     default: break;
01910   }
01911   
01912   return(MODIS_S_OK);
01913 } 
01914 
01915 PGSt_SMF_status Fill_Dead_Detector_SI (boolean isdaymode,
01916                                        int8 *dead_detector,
01917                                        L1B_Scan_t *L1B_Scan,
01918                                        L1B_granule_t *L1B_Gran,
01919                                        QA_Common_t *QA_Common)
01920 /*
01921 !C************************************************************************
01922 !Description:
01923   This function fills in reasonable pixel values in one Level 1B EV
01924   product file SDSs, for pixels that correspond to dead detectors.
01925   Values from adjacent (live) detectors are used to determine the values
01926   to assign to the dead-detector pixels.  If possible, a linear average
01927   from adjacent pixels is calculated.  This operation is applied only to
01928   the native resolution L1B data sets, not aggregated data sets.
01929 
01930 !Input Parameters:
01931   boolean isdaymode      A flag that denotes that the scan is a
01932                          day-mode scan.  Some RSB SDSs are computed only
01933                          if the scan is a day-mode scan.
01934   int8 *dead_detector    Array spanning 490 MODIS detectors which
01935                          identifies a non-functional detector (if = 1).
01936   L1B_Scan_t *L1B_Scan   Scan data to be written to the EV products.
01937                          Includes the scaled integers that may be
01938                          modified.
01939 
01940 !Output Parameters:
01941   L1B_Scan_t *L1B_Scan   SI pixel values corresponding to dead detectors
01942                          may be changed.  Other values should be unchanged.
01943   L1B_granule_t *L1B_Gran  Contains interpolated pixel values for each band.
01944   QA_Common_t *QA_Common   Contains number of dead detector EV data for each
01945                            detector.
01946 
01947 !Revision History:
01948  (continue at top of the file)
01949 
01950   Revision 01.01 March 2003, Razor Issue #173
01951   Initialized SI, SI_prev,and SI_subs to 0 for ANSI-C compliance.
01952   Liqin Tan, SAIC GSO (ltan@saicmodis.com)
01953 
01954   Revision 01.00 June 15, 2000
01955   Initial development
01956   Jim Rogers (rogers@mcst.gfsc.nasa.gov)
01957 
01958 !Team-unique Header:
01959   This software is developed by the MODIS Science Data Support
01960   Team for the National Aeronautics and Space Administration,
01961   Goddard Space Flight Center, under contract NAS5-32373.
01962 
01963 !References and Credits:
01964   HDF portions developed at the National Center for Supercomputing
01965   Applications at the University of Illinois at Urbana-Champaign.
01966 
01967 !Design Notes:
01968 
01969   The change is accomplished on a scan-by-scan basis on the native-resolution
01970   SDSs only.  No artificial values are used in forming aggregated SI values.
01971   There is no "cross-over" of information between scans.  The logic is as
01972   follows.  If a detector is flagged as "dead" by the detector quality flag
01973   LUT, then the SI values of nearest "live" detectors in the same frame and
01974   subsample are used to form a linear average value for the dead detector SI
01975   value.  This linear average is accomplished independently for each frame and
01976   subsample of the scan line of the dead detector.  There are conditions
01977   checked for:
01978 
01979   1)  if the dead detector is either the first or last detector in the set,
01980   then the second or next-to-last value is simply copied (no linear average).
01981 
01982   2)  if an adjacent value to be used in either averaging or copying is an
01983   "unusable" value (>32767), then it is not used to form the artificial value.
01984   For example, if we started off with two values to form a linear average but
01985   one of the values is unusable, then the remaining valid value is simply
01986   copied.
01987 
01988   3)  If there are no usable values available to form the artificial value,
01989   then the pixel value remains at 65533 (the "dead detector" SI value).
01990 
01991   In the product, users may read the "Dead Detector List" attribute to
01992   determine which detectors were classified as dead and thus which scan lines
01993   may have the artificial values filled in.
01994 
01995 !END**********************************************************************
01996 */
01997 {
01998         /* Define order and number of SDSs that may need to be modified.
01999          * These are in different multi-dimensional arrays.
02000          */
02001 
02002 typedef enum {
02003 #ifdef WRITE_BAND_26_SDS
02004   FDD_RSB_BAND26,
02005 #endif /* WRITE_BAND_26_SDS */
02006   FDD_RSB_250M,
02007   FDD_RSB_500M,
02008   FDD_RSB_1KM_DAY,
02009   FDD_TEB_1KM,
02010   NUM_FDD_DATA_SETS
02011 } data_set_enum_t;
02012 #define MAX_BANDS_PER_FDD_SET 16
02013 
02014         /* Declare arrays which describe features (such as dimensions)
02015          * of the SDSs.
02016          */
02017 
02018   int32 num_bands_per_set[NUM_FDD_DATA_SETS] = 
02019   {
02020 #ifdef WRITE_BAND_26_SDS
02021     1,
02022 #endif /* WRITE_BAND_26_SDS */
02023     NUM_250M_BANDS,
02024     NUM_500M_BANDS,
02025     NUM_1000M_REFL_BANDS,
02026     NUM_1000M_EMISS_BANDS
02027   };
02028 
02029   int32 num_dets_per_set[NUM_FDD_DATA_SETS] = 
02030   {
02031 #ifdef WRITE_BAND_26_SDS
02032     DETECTORS_PER_1KM_BAND,
02033 #endif /* WRITE_BAND_26_SDS */
02034     DETECTORS_PER_250M_BAND,
02035     DETECTORS_PER_500M_BAND,
02036     DETECTORS_PER_1KM_BAND,
02037     DETECTORS_PER_1KM_BAND
02038   };
02039 
02040   int32 num_frames_per_set[NUM_FDD_DATA_SETS] = 
02041   {
02042 #ifdef WRITE_BAND_26_SDS
02043     EV_1km_FRAMES,
02044 #endif /* WRITE_BAND_26_SDS */
02045     EV_250m_FRAMES,
02046     EV_500m_FRAMES,
02047     EV_1km_FRAMES,
02048     EV_1km_FRAMES
02049   };
02050 
02051         /* The following denotes whether the data set is "Day" only */
02052 
02053   boolean isdayonly[NUM_FDD_DATA_SETS] = 
02054   {
02055 #ifdef WRITE_BAND_26_SDS
02056     False,
02057 #endif /* WRITE_BAND_26_SDS */
02058     True,
02059     True,
02060     True,
02061     False
02062   };
02063     
02064   boolean qa_flag; /* to check if the qa parameter values for band 26 is
02065                     * already adjusted.
02066                     */
02067 
02068         /* We will use dead_detector to fill the array below.
02069          * This is static because values are determined one time
02070          * and then saved for subsequent scans.
02071          */
02072 
02073   static int8 dead_det_array [NUM_FDD_DATA_SETS][MAX_BANDS_PER_FDD_SET]
02074                              [MAX_DETECTORS_PER_BAND];
02075 
02076         /* The following static variable is used to determine if we have
02077          * already defined the above array (we only need to fill it for
02078          * one scan -- it is the same for all scans).
02079          */
02080 
02081   static boolean dead_det_array_is_filled = False;
02082 
02083         /* The following static variables is used to map the index of
02084          * bands through all bands to the index of bands within each L1A
02085          * resolution.
02086          */
02087 
02088   static int8 band_38[NUM_FDD_DATA_SETS][MAX_BANDS_PER_FDD_SET];
02089 
02090         /* The following static variables is used to map the index of
02091          * detectors through all detectors to the index of detectors within
02092          * each band within each L1A resolution.
02093          */
02094 
02095   static int16 det_490[NUM_FDD_DATA_SETS][MAX_BANDS_PER_FDD_SET]
02096                        [MAX_DETECTORS_PER_BAND];
02097 
02098   int32 R;          /* Index through L1A resolutions */
02099   int32 B;          /* Index through bands within one L1A resolution */
02100   int32 B_38;       /* Index through all bands, in order */
02101   int32 D;          /* Index through detectors within a band */
02102   int32 D_490;      /* Index through all detectors, in order */
02103   int32 B_emiss;    /* Index through L1B emissive bands */
02104   int32 B26_RSB;    /* index of band 26 inside L1B RSB band set */
02105   int32 D_prev;     /* index of previous detector. */
02106   int32 D_subs;     /* index of subsequent detector. */
02107   int32 iset;       /* index of data set being operated on */
02108   int32 F;          /* Frame index (frame and sample) */
02109 
02110   PGSt_SMF_status returnStatus = MODIS_S_OK;
02111   char *location = "Fill_Dead_Detector_SI";
02112 
02113         /* Utility pointers -- to an array of frames */
02114 
02115   uint16 *SI = 0;       /* SI for scan line in question */
02116   uint16 *SI_prev = 0;  /* SI for previous scan line */
02117   uint16 *SI_subs = 0;  /* SI for subsequent scan line */
02118 
02119   /************************* Declarations complete ***********************/
02120 
02121 
02122   if (dead_det_array_is_filled == False) 
02123     {
02124 
02125         /* Assemble new dead detector array having more convenient
02126          * dimensionality.
02127          */
02128 
02129         /* Initialize to a bad value so we can check later */
02130 
02131       for (iset = 0; iset < NUM_FDD_DATA_SETS; iset++) 
02132       {
02133         for (B = 0; B < MAX_BANDS_PER_FDD_SET; B++) 
02134         {
02135           for (D = 0; D < MAX_DETECTORS_PER_BAND; D++) 
02136           {
02137             dead_det_array [iset][B][D] = -1;
02138           }
02139         }
02140       }
02141 
02142           /* Fill the 3D dead detector array. */
02143 
02144       B_38 = 0;
02145       D_490 = 0;
02146       R = INDEX_250M;
02147       for (B = 0; B < L1A_BANDS_AT_RES[R]; B++, B_38++) 
02148       {
02149         band_38[FDD_RSB_250M][B] = B_38;
02150         for (D = 0; D < DETECT_PER_BAND_AT_RES[R]; D++, D_490++) 
02151         {
02152           dead_det_array[FDD_RSB_250M][B][D] = dead_detector[D_490];
02153           det_490[FDD_RSB_250M][B][D] = D_490;
02154         }
02155       }
02156       R = INDEX_500M;
02157       for (B = 0; B < L1A_BANDS_AT_RES[R]; B++, B_38++) 
02158       {
02159         band_38[FDD_RSB_500M][B] = B_38;
02160         for (D = 0; D < DETECT_PER_BAND_AT_RES[R]; D++, D_490++) 
02161         {
02162           dead_det_array[FDD_RSB_500M][B][D] = dead_detector[D_490];
02163           det_490[FDD_RSB_500M][B][D] = D_490;
02164         }
02165       }
02166       R = INDEX_1000M_DAY;
02167       for (B = 0; B < L1A_BANDS_AT_RES[R]; B++, B_38++) 
02168       {
02169         band_38[FDD_RSB_1KM_DAY][B] = B_38;
02170         for (D = 0; D < DETECT_PER_BAND_AT_RES[R]; D++, D_490++) 
02171         {
02172           dead_det_array[FDD_RSB_1KM_DAY][B][D] = dead_detector[D_490];
02173           det_490[FDD_RSB_1KM_DAY][B][D] = D_490;
02174         }
02175       }
02176       R = INDEX_1000M_NIGHT;
02177       B_emiss = 0;
02178       B26_RSB = L1B_BANDS_AT_RES[INDEX_1000M_DAY] - 1;
02179       for (B = 0; B < L1A_BANDS_AT_RES[R]; B++, B_38++) 
02180       {
02181         if (B == MODIS_BAND26_INDEX_AT_RES) 
02182         {
02183           band_38[FDD_RSB_1KM_DAY][B26_RSB] = B_38;
02184 #ifdef WRITE_BAND_26_SDS
02185           band_38[FDD_RSB_BAND26][0] = B_38;
02186 #endif /* WRITE_BAND_26_SDS */
02187 
02188           for (D = 0; D < DETECT_PER_BAND_AT_RES[R]; D++, D_490++) 
02189           {
02190             dead_det_array[FDD_RSB_1KM_DAY][B26_RSB][D] = dead_detector[D_490];
02191             det_490[FDD_RSB_1KM_DAY][B26_RSB][D] = D_490;
02192 #ifdef WRITE_BAND_26_SDS
02193             dead_det_array[FDD_RSB_BAND26][0][D] = dead_detector[D_490];
02194             det_490[FDD_RSB_BAND26][0][D] = D_490;
02195 #endif /* WRITE_BAND_26_SDS */
02196           }
02197         }
02198         else 
02199         {
02200           band_38[FDD_TEB_1KM][B_emiss] = B_38;
02201           for (D = 0; D < DETECT_PER_BAND_AT_RES[R]; D++, D_490++) 
02202           {
02203             dead_det_array[FDD_TEB_1KM][B_emiss][D] = dead_detector[D_490];
02204             det_490[FDD_TEB_1KM][B_emiss][D] = D_490;
02205           }
02206           B_emiss++;
02207         }
02208       }
02209 
02210           /* Check for a bad value -- make sure we assigned each one. */
02211 
02212       for (iset = 0; iset < NUM_FDD_DATA_SETS; iset++) 
02213       {
02214         for (B = 0; B < num_bands_per_set[iset]; B++) 
02215         {
02216           for (D = 0; D < num_dets_per_set[iset]; D++) 
02217           {
02218             if (dead_det_array [iset][B][D] == -1)
02219             {
02220               returnStatus = MODIS_F_NOK;
02221               L1BErrorMsg(location, returnStatus,
02222                           "Dead detector array values not properly assigned.",
02223                           NULL, 0,  NULL, True);
02224               return returnStatus;
02225             }
02226           }
02227         }
02228       }
02229 
02230       dead_det_array_is_filled = True;
02231     }
02232 
02233         /* Main loop through all data sets. */
02234 
02235     for (iset = 0; iset < NUM_FDD_DATA_SETS; iset++) 
02236       {
02237 
02238         /* Skip this set if it is day only and scan is not day */
02239 
02240         if (isdaymode == False && isdayonly[iset] == True)
02241           continue;
02242 
02243         /* Loop through bands in this data set */
02244 
02245         for (B = 0; B < num_bands_per_set[iset]; B++) 
02246           {
02247             B_38 = band_38[iset][B];
02248 
02249             qa_flag = True;
02250 
02251 #ifdef WRITE_BAND_26_SDS
02252             if (iset != FDD_RSB_BAND26 && B_38 == MODIS_BAND26_INDEX)
02253               qa_flag = False;
02254 #endif /* WRITE_BAND_26_SDS */
02255 
02256             /* Loop through detectors */
02257 
02258             for (D = 0; D < num_dets_per_set[iset]; D++) 
02259               {
02260 
02261                 /* If this detector is not "dead", skip it.
02262                  * (leave pixels as they are).
02263                  */
02264 
02265                 if (dead_det_array[iset][B][D] == 0)
02266                   continue;
02267 
02268                         /* Determine D_prev by going back
02269                          * and finding the 1st non-dead detector.
02270                          */
02271 
02272                 D_prev = D - 1;
02273                 while (D_prev >= 0) 
02274                   {
02275                     if (dead_det_array[iset][B][D_prev] == 0)
02276                       break;
02277                     D_prev--;
02278                   }
02279 
02280                         /* Determine D_subs in a similar way. */
02281 
02282                 D_subs = D + 1;
02283                 while (D_subs < num_dets_per_set[iset]) 
02284                   {
02285                     if (dead_det_array[iset][B][D_subs] == 0)
02286                       break;
02287                     D_subs++;
02288                   }
02289 
02290                 if (D_subs == num_dets_per_set[iset])
02291                   D_subs = -1;
02292 
02293                         /* If both D_prev and D_subs are invalid, continue
02294                          * (omit this detector)
02295                          */
02296 
02297                 if (D_prev == -1 && D_subs == -1)
02298                   continue;
02299 
02300                 if (D_prev == D_subs)       /*** Should not happen ***/
02301                   continue;
02302 
02303               /* Assign the data to be used for filling in values */
02304 
02305 #ifdef WRITE_BAND_26_SDS
02306                 if (iset == FDD_RSB_BAND26) 
02307                   {
02308                     SI = L1B_Scan->Band26.SI[D];
02309                     if (D_prev >= 0)
02310                       SI_prev = L1B_Scan->Band26.SI[D_prev];
02311                     if (D_subs >= 0)
02312                       SI_subs = L1B_Scan->Band26.SI[D_subs];
02313                   } 
02314 
02315                   else
02316 #endif /* WRITE_BAND_26_SDS */
02317                   if (iset == FDD_RSB_250M) 
02318                     {
02319                       SI = L1B_Scan->SI.EV_250m_RefSB[B][D];
02320                       if (D_prev >= 0)
02321                         SI_prev = L1B_Scan->SI.EV_250m_RefSB[B][D_prev];
02322                       if (D_subs >= 0)
02323                         SI_subs = L1B_Scan->SI.EV_250m_RefSB[B][D_subs];
02324                     }
02325 
02326                   else if (iset == FDD_RSB_500M) 
02327                     {
02328                       SI = L1B_Scan->SI.EV_500m_RefSB[B][D];
02329                       if (D_prev >= 0)
02330                         SI_prev = L1B_Scan->SI.EV_500m_RefSB[B][D_prev];
02331                       if (D_subs >= 0)
02332                         SI_subs = L1B_Scan->SI.EV_500m_RefSB[B][D_subs];
02333                     }
02334 
02335                   else if (iset == FDD_RSB_1KM_DAY) 
02336                     {
02337                       SI = L1B_Scan->SI.EV_1km_RefSB[B][D];
02338                       if (D_prev >= 0)
02339                         SI_prev = L1B_Scan->SI.EV_1km_RefSB[B][D_prev];
02340                       if (D_subs >= 0)
02341                         SI_subs = L1B_Scan->SI.EV_1km_RefSB[B][D_subs];
02342                     }
02343 
02344                   else if (iset == FDD_TEB_1KM) 
02345                     {
02346                       SI = L1B_Scan->SI.EV_1km_Emissive[B][D];
02347                       if (D_prev >= 0)
02348                         SI_prev = L1B_Scan->SI.EV_1km_Emissive[B][D_prev];
02349                       if (D_subs >= 0)
02350                         SI_subs = L1B_Scan->SI.EV_1km_Emissive[B][D_subs];
02351                     }
02352 
02353                 /* At long last, fill the array of values to be written */
02354 
02355                 D_490 = det_490[iset][B][D];
02356 
02357                 if (D_prev == -1) 
02358                   { 
02359                     for (F = 0; F < num_frames_per_set[iset]; F++) 
02360                       {
02361                         if (SI_subs[F] <= DN15_SAT && SI[F] == DEAD_DETECTOR_SI) 
02362                           {
02363                             SI[F] = SI_subs[F];
02364                             if (qa_flag) 
02365                               {
02366                                 L1B_Gran->interpolated_pixels[B_38]++;
02367                                 L1B_Gran->valid_pixels[B_38]++;
02368                                 QA_Common->num_dead_detector_EV_data[D_490]--;
02369                               }
02370                           }
02371                       }
02372                   }
02373 
02374                 else if (D_subs == -1) 
02375                   {
02376                     for (F = 0; F < num_frames_per_set[iset]; F++) 
02377                       {
02378                         if (SI_prev[F] <= DN15_SAT && SI[F] == DEAD_DETECTOR_SI) 
02379                           {
02380                             SI[F] = SI_prev[F];
02381                             if (qa_flag) 
02382                               {
02383                                 L1B_Gran->interpolated_pixels[B_38]++;
02384                                 L1B_Gran->valid_pixels[B_38]++;
02385                                 QA_Common->num_dead_detector_EV_data[D_490]--;
02386                               }
02387                           }
02388                       }
02389                   }
02390 
02391                 else 
02392                   {
02393                     float32 fract = ((float32) (D - D_prev)) /
02394                                         ((float32) (D_subs - D_prev));
02395                     for (F = 0; F < num_frames_per_set[iset]; F++) 
02396                       {
02397                         if (SI_subs[F] <= DN15_SAT && SI_prev[F] <= DN15_SAT &&
02398                             SI[F] == DEAD_DETECTOR_SI) 
02399                           {
02400                             SI[F] = (uint16)((float32)SI_prev[F] +
02401                                     (fract * ((float32)SI_subs[F] - 
02402                                     (float32)SI_prev[F])));
02403                             if (qa_flag) 
02404                               {
02405                                 L1B_Gran->interpolated_pixels[B_38]++;
02406                                 L1B_Gran->valid_pixels[B_38]++;
02407                                 QA_Common->num_dead_detector_EV_data[D_490]--;
02408                               }
02409                           }
02410 
02411                         else if (SI_subs[F] <= DN15_SAT && 
02412                                    SI[F] == DEAD_DETECTOR_SI) 
02413                           {
02414                             SI[F] = SI_subs[F];
02415                             if (qa_flag) 
02416                               {
02417                                 L1B_Gran->interpolated_pixels[B_38]++;
02418                                 L1B_Gran->valid_pixels[B_38]++;
02419                                 QA_Common->num_dead_detector_EV_data[D_490]--;
02420                               }
02421                           }
02422 
02423                         else if (SI_prev[F] <= DN15_SAT && 
02424                              SI[F] == DEAD_DETECTOR_SI) 
02425                           {
02426                             SI[F] = SI_prev[F];
02427                             if (qa_flag) 
02428                               {
02429                                 L1B_Gran->interpolated_pixels[B_38]++;
02430                                 L1B_Gran->valid_pixels[B_38]++;
02431                                 QA_Common->num_dead_detector_EV_data[D_490]--;
02432                               }
02433                           }
02434                       }
02435                   }
02436 
02437               }      /* loop through D */
02438           }          /* loop through B */
02439       }              /* loop through iset */
02440 
02441 
02442   return returnStatus;
02443 }
02444 
02445 PGSt_SMF_status Open_and_Read_L1A 
02446                          (Run_Time_Parameters_t *runtime_params,
02447                           L1A_granule_t         *L1A_Gran,
02448                           boolean               *skip_night_hi_res)
02449     
02450 /*
02451 !C**************************************************************************
02452 !Description: This function opens the L1A granule to be processed and reads
02453               in data for all members of the L1A_granule_t structure. The
02454               file remains open (both SD and Vdata) upon function exit.
02455 
02456 !Input Parameters:
02457    Run_Time_Parameters_t *runtime_params   Values read from PCF file.
02458 
02459 !Output Parameters:
02460      L1A_granule_t *L1A_Gran         contains SD file interface ID, Vdata
02461                                      file interface ID, number of scans and
02462                                      other data relating to the middle
02463                                      granule
02464 
02465 !Revision History:
02466  (continue at top of the file)
02467 
02468    Revision 01.02 June 4, 2002    Razor Issue #169
02469    Changed logic to check whether any scans are in day mode and if so, set 
02470    skip_night_hi_res to False.
02471    Gwyn Fireman & Alice Isaacman, SAIC GSO  (Alice.R.Isaacman.1@gsfc.nasa.gov)
02472    
02473    Revision 01.01 November 12, 2001       (Razor Issue #169)
02474    Added boolean skip_night_hi_res as output variable.
02475    Alice Isaacman (Alice.R.Isaacman.1@gsfc.nasa.gov), SAIC GSO
02476 
02477    Revision 01.00 June 27, 2000
02478    Initial development.
02479    Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
02480 
02481 !Team-unique Header:
02482    This software is developed by the MODIS Science Data Support
02483    Team for the National Aeronautics and Space Administration,
02484    Goddard Space Flight Center, under contract NAS5-32373.
02485 
02486 !References and Credits
02487    HDF portions developed at the National Center for Supercomputing
02488    Applications at the University of Illinois at Urbana-Champaign.
02489 
02490 !Design Notes:
02491 !END********************************************************************
02492 */
02493 {
02494   PGSt_SMF_status    returnStatus = MODIS_S_OK;
02495   intn               hdf_return   = 0;
02496   PGSt_integer       Version      = 1;
02497   char               file_name[PGSd_PC_FILE_PATH_MAX];
02498   int32              S;                  /* scan index */
02499   int32              middle_scan;
02500   int32              geo_satellite_id;
02501   char               *location = "Open_and_Read_L1A";
02502   char               *satelliteInstrument;
02503 
02504       /* 
02505        * Will be set to TRUE by PCF file only if writing 250m and 
02506        * 500m files when in night mode is desired. 
02507        */                        
02508   boolean            write_nightmode_hires = 0;  
02509   boolean            is_nightmode_data     = 0;
02510   
02511   /*
02512    * Prepare for opening file: convert logical ID to physical name
02513    */
02514 
02515   returnStatus = PGS_PC_GetReference (FIRST_L1A_GRANULE, &Version, file_name);
02516   if (returnStatus != PGS_S_SUCCESS)
02517   {
02518     returnStatus = MODIS_F_FILE_NOT_FOUND;
02519     L1BErrorMsg(location, returnStatus, "Could not retrieve file name from PCF.",
02520                 "PGS_PC_GetReference", FIRST_L1A_GRANULE, NULL, True);
02521     return returnStatus;
02522   }
02523 
02524   /*
02525    * Open file for HDF science data (SD) access.
02526    */
02527 
02528   L1A_Gran->sd_id = SDstart(file_name,DFACC_RDONLY); /*for SD interface */
02529   if (L1A_Gran->sd_id == FAIL)
02530   {
02531     returnStatus = MODIS_F_FILE_NOT_OPENED;
02532     L1BErrorMsg(location, returnStatus, "Could not open file for SD read access.",
02533                 "SDstart", FIRST_L1A_GRANULE,
02534                 "The file may be missing, corrupted or not an HDF-4 file.", True);
02535     return returnStatus;
02536   }
02537 
02538   /*
02539    * Open file for HDF Vdata access and initialize Vdata interface.
02540    * Call Hopen() and Vstart() in the same place.
02541    */
02542 
02543   L1A_Gran->v_id = Hopen(file_name,DFACC_RDONLY,0);
02544   if (L1A_Gran->v_id == FAIL)
02545   {
02546     SDend (L1A_Gran->sd_id);
02547     returnStatus = MODIS_F_FILE_NOT_OPENED;
02548     L1BErrorMsg(location, returnStatus, "Could not open file for Vdata read access.",
02549                 "Hopen", FIRST_L1A_GRANULE,
02550                 "The file may be corrupted or not an HDF-4 file.", True);
02551     return returnStatus;
02552   }
02553 
02554   hdf_return = Vstart (L1A_Gran->v_id); /*initialize internal structures*/
02555   if (hdf_return == FAIL)
02556   {
02557     SDend (L1A_Gran->sd_id); Hclose (L1A_Gran->v_id);
02558     returnStatus = MODIS_F_HDF_ERROR;
02559     L1BErrorMsg(location, returnStatus, "Could not initialize Vdata interface.",
02560                 "Vstart", FIRST_L1A_GRANULE,
02561                 "The file may be corrupted or not an HDF-4 file.", True);
02562     return returnStatus;
02563   }
02564 
02565   /*
02566    * Read num_scans
02567    */
02568 
02569   returnStatus = read_attribute (L1A_Gran->sd_id, "Number of Scans",
02570                                  DFNT_INT32, (void *)&L1A_Gran->num_scans);
02571   if (returnStatus != MODIS_S_OK)
02572   {
02573     L1BErrorMsg(location, returnStatus, "Could not read Number of Scans.",
02574                 "read_attribute", FIRST_L1A_GRANULE, Invalid_MOD01_Msg, True);
02575     return returnStatus;
02576   }
02577 
02578   if (L1A_Gran->num_scans <= 0)
02579   {
02580     returnStatus = MODIS_F_OUT_OF_RANGE;
02581     MOD_PR02_Failure_Exit_Code = 233;
02582     L1BErrorMsg(location, returnStatus,
02583                 "Number of Scans in the MOD01 granule is less than "
02584                 "or equal to 0.\n"
02585                 "The MOD01 granule is probably empty (no valid data)",
02586                 NULL, FIRST_L1A_GRANULE, NULL, True);
02587     return returnStatus;
02588   }
02589 
02590   if (L1A_Gran->num_scans > MAX_NUM_SCANS)
02591   {
02592     returnStatus = MODIS_F_OUT_OF_RANGE;
02593     L1BErrorMsg(location, returnStatus,
02594                 "Number of Scans in the MOD01 granule is greater "
02595                 "than MAX_NUM_SCANS.",
02596                 NULL, FIRST_L1A_GRANULE,
02597                 "If the file is valid, the code macro must be increased.", True);
02598     return returnStatus;
02599   }
02600 
02601   /*
02602    * Read num_day_scans
02603    */
02604 
02605   returnStatus = read_attribute (L1A_Gran->sd_id, "Number of Day mode scans",
02606                                  DFNT_INT32, (VOIDP)&L1A_Gran->num_day_scans);
02607   if (returnStatus != MODIS_S_OK)
02608   {
02609     L1BErrorMsg(location, returnStatus, "Could not read Number of Day "
02610                 "mode scans.",
02611                 "read_attribute", FIRST_L1A_GRANULE, Invalid_MOD01_Msg, True);
02612     return returnStatus;
02613   }
02614 
02615   /*
02616    * Set skip_night_hi_res flag
02617    */
02618 
02619   if (strcmp(runtime_params->Write_Night_Mode_HiRes_Data, "0") == 0)
02620     write_nightmode_hires = False;  
02621   else
02622     write_nightmode_hires = True;
02623 
02624   if (L1A_Gran->num_day_scans == 0)
02625     is_nightmode_data =  True;
02626   else
02627     is_nightmode_data =  False;
02628 
02629   if (is_nightmode_data == True && write_nightmode_hires == False) 
02630     *skip_night_hi_res = True;
02631   else
02632     *skip_night_hi_res = False;
02633 
02634   /*
02635    * Read L1A ScanType
02636    */
02637 
02638   returnStatus = read_sds_rank2 (L1A_Gran->sd_id, "Scan Type",
02639                                  L1A_Gran->num_scans, SCAN_TYPE_TEXT_SIZE,
02640                                  (void *)L1A_Gran->ScanType);
02641   if (returnStatus != MODIS_S_OK)
02642   {
02643     L1BErrorMsg(location, returnStatus, "Could not read Scan Type.",
02644                 "read_sds_rank2", FIRST_L1A_GRANULE, Invalid_MOD01_Msg, True);
02645     return returnStatus;
02646   }
02647 
02648   for (S = 0; S < L1A_Gran->num_scans; S++)
02649   {
02650     if (strcmp(L1A_Gran->ScanType[S], "Day") != 0   &&
02651         strcmp(L1A_Gran->ScanType[S], "Night") != 0 &&
02652         strcmp(L1A_Gran->ScanType[S], "Other") != 0)
02653     {
02654       returnStatus = MODIS_F_OUT_OF_RANGE;
02655       L1BErrorMsg(location, returnStatus,
02656                   "Scan Type is not \"Day\", \"Night\", or \"Other\".",
02657                   NULL, FIRST_L1A_GRANULE, Invalid_MOD01_Msg, True);
02658       return returnStatus;
02659     }
02660   }
02661 
02662   /*
02663    * Read L1A EVStartTime_TAIsecond
02664    */
02665 
02666   returnStatus = read_sds_rank1 (L1A_Gran->sd_id, "EV start time",
02667                                  L1A_Gran->num_scans,
02668                                  (void *)L1A_Gran->EVStartTime_TAIsecond);
02669   if (returnStatus != MODIS_S_OK)
02670   {
02671     L1BErrorMsg(location, returnStatus, "Could not read EV start time.",
02672                 "read_sds_rank1", FIRST_L1A_GRANULE, Invalid_MOD01_Msg, True);
02673     return returnStatus;
02674   }
02675 
02676   /* 
02677    * Determine data collection time. The valid EV start time for the scan
02678    * closest to the middle scan is chosen to be the data collection time.
02679    * This time is used for time-dependent look up tables.
02680    */
02681 
02682   middle_scan = L1A_Gran->num_scans/2;
02683   L1A_Gran->data_collection_time = 0;
02684   for (S = 0; middle_scan-S >= 0 && 
02685       middle_scan+S < L1A_Gran->num_scans; S++) {
02686     if (L1A_Gran->EVStartTime_TAIsecond[middle_scan-S] > 0) {
02687       L1A_Gran->data_collection_time = 
02688           L1A_Gran->EVStartTime_TAIsecond[middle_scan-S];
02689       break;
02690     }
02691     else if (L1A_Gran->EVStartTime_TAIsecond[middle_scan+S] > 0) {
02692       L1A_Gran->data_collection_time = 
02693           L1A_Gran->EVStartTime_TAIsecond[middle_scan+S];
02694       break;
02695     }
02696   }
02697 
02698   if (L1A_Gran->data_collection_time == 0) {
02699     returnStatus = MODIS_F_NOK;
02700     L1BErrorMsg(location, returnStatus,
02701                 "No valid or only one valid EV start time in the "
02702                 "array \"EV start time\"",
02703                 NULL, 0, NULL, True);
02704     return returnStatus;
02705   }
02706  
02707   /*
02708    * Read L1A MirrorSide
02709    */
02710 
02711   returnStatus = read_sds_rank1 (L1A_Gran->sd_id, "Mirror side",
02712                                  L1A_Gran->num_scans,
02713                                  (void *)L1A_Gran->MirrorSide);
02714   if ( returnStatus != MODIS_S_OK)
02715   {
02716     L1BErrorMsg(location, returnStatus, "Could not read Mirror side.",
02717                 "read_sds_rank1", FIRST_L1A_GRANULE, Invalid_MOD01_Msg, True);
02718     return returnStatus;
02719   }
02720 
02721   for (S = 0; S < L1A_Gran->num_scans; S++)
02722   {
02723     if (L1A_Gran->MirrorSide[S] != 0 && L1A_Gran->MirrorSide[S] != 1
02724                                      && L1A_Gran->MirrorSide[S] != -1)
02725     {
02726       returnStatus = MODIS_F_OUT_OF_RANGE;
02727       L1BErrorMsg(location, returnStatus, "Mirror side is not [-1, 0, 1].",
02728                   NULL, FIRST_L1A_GRANULE, Invalid_MOD01_Msg, True);
02729       return returnStatus;
02730     }
02731   }
02732 
02733   /*
02734    * Read num_night_scans
02735    */
02736 
02737   returnStatus = read_attribute (L1A_Gran->sd_id, 
02738                                  "Number of Night mode scans",
02739                                  DFNT_INT32, 
02740                                  (VOIDP)&L1A_Gran->num_night_scans);
02741   if (returnStatus != MODIS_S_OK)
02742   {
02743     L1BErrorMsg(location, returnStatus, 
02744                 "Could not read Number of Night mode scans.",
02745                 "read_attribute", FIRST_L1A_GRANULE, Invalid_MOD01_Msg, True);
02746     return returnStatus;
02747   }
02748 
02749   /*
02750    * Read incomplete_scans
02751    */
02752 
02753   returnStatus = read_attribute (L1A_Gran->sd_id, 
02754                                  "Incomplete Scans", DFNT_INT32,
02755                                  (VOIDP)&L1A_Gran->incomplete_scans);
02756   if (returnStatus != MODIS_S_OK)
02757   {
02758     L1BErrorMsg(location, returnStatus, 
02759                 "Could not read number of incomplete scans.",
02760                 "read_attribute", 
02761                 FIRST_L1A_GRANULE, Invalid_MOD01_Msg, True);
02762     return returnStatus;
02763   }
02764 
02765   /*
02766    * Read max_ev_frames
02767    */
02768 
02769   returnStatus = read_attribute (L1A_Gran->sd_id, 
02770                                  "Max Earth Frames", DFNT_INT32,
02771                                  (VOIDP)&L1A_Gran->max_ev_frames);
02772   if (returnStatus != MODIS_S_OK)
02773   {
02774     L1BErrorMsg(location, returnStatus, 
02775                 "Could not read maximum number of EV frames.",
02776                 "read_attribute", FIRST_L1A_GRANULE, 
02777                 Invalid_MOD01_Msg, True);
02778     return returnStatus;
02779   }
02780 
02781 
02782   /*
02783    * Read Extract Pixel Offset & Count
02784    */
02785 
02786   if (SDfindattr(L1A_Gran->sd_id, "Extract Pixel Offset") != -1) {
02787     returnStatus = read_attribute (L1A_Gran->sd_id, 
02788                                    "Extract Pixel Offset", DFNT_INT32,
02789                                    (VOIDP)&L1A_Gran->Extract_Pixel_Offset);
02790   } else L1A_Gran->Extract_Pixel_Offset = -1;
02791 
02792   if (SDfindattr(L1A_Gran->sd_id, "Extract Pixel Count") != -1) {
02793     returnStatus = read_attribute (L1A_Gran->sd_id, 
02794                                    "Extract Pixel Count", DFNT_INT32,
02795                                    (VOIDP)&L1A_Gran->Extract_Pixel_Count);
02796   } else L1A_Gran->Extract_Pixel_Count = -1;
02797 
02798 
02799   /*
02800    * Read Extract Line Offset & Count
02801    */
02802 
02803   if (SDfindattr(L1A_Gran->sd_id, "Extract Line Offset") != -1) {
02804     returnStatus = read_attribute (L1A_Gran->sd_id, 
02805                                    "Extract Line Offset", DFNT_INT32,
02806                                    (VOIDP)&L1A_Gran->Extract_Line_Offset);
02807   } else L1A_Gran->Extract_Line_Offset = -1;
02808 
02809   if (SDfindattr(L1A_Gran->sd_id, "Extract Line Count") != -1) {
02810     returnStatus = read_attribute (L1A_Gran->sd_id, 
02811                                    "Extract Line Count", DFNT_INT32,
02812                                    (VOIDP)&L1A_Gran->Extract_Line_Count);
02813   } else L1A_Gran->Extract_Line_Count = -1;
02814 
02815 
02816   /*
02817    * Read scan quality array
02818    */
02819 
02820   returnStatus = read_sds_rank2(L1A_Gran->sd_id, "Scan quality array",
02821                                 L1A_Gran->num_scans, 
02822                                 SCAN_QUALITY_ARRAY_NUM_ELEMENTS,
02823                                 (VOIDP)L1A_Gran->scan_quality);
02824   if (returnStatus != MODIS_S_OK) {
02825     L1BErrorMsg(location, returnStatus, "Could not read scan quality array",
02826                 "read_sds_rank2", FIRST_L1A_GRANULE, NULL, True);
02827     return returnStatus;
02828   }
02829 
02830   /*
02831    * Determine if a scan is completely missing based on the second element
02832    * of Scan quality array.
02833    */
02834 
02835   for (S = 0; S < L1A_Gran->num_scans; S++)
02836   {
02837     if (L1A_Gran->scan_quality[S][0] == 0)
02838       L1A_Gran->missing_scan[S] = True;
02839     else
02840       L1A_Gran->missing_scan[S] = False;
02841   }
02842 
02843   /*
02844    * Determine the satellite
02845    */
02846 
02847   returnStatus = Get_Satellite_ID(FIRST_L1A_GRANULE, &L1A_Gran->satellite_id);
02848   if (returnStatus != MODIS_S_OK)
02849   {
02850     L1BErrorMsg(location, returnStatus, "Could not get satellite ID.",
02851                 "Get_Satellite_ID", FIRST_L1A_GRANULE, Invalid_MOD01_Msg, True);
02852     return returnStatus;
02853   }
02854 
02855   /*
02856    * Determine the satellite instrument value in geo file.
02857    */
02858 
02859   returnStatus = Get_Satellite_ID(GEOLOCATION_FILE, &geo_satellite_id);
02860   if (returnStatus != MODIS_S_OK)
02861   {
02862     L1BErrorMsg(location, returnStatus, "Could not get satellite ID.",
02863                 "Get_Satellite_ID", GEOLOCATION_FILE,
02864                 "The geolocation file is invalid.", True);
02865     return returnStatus;
02866   }
02867   
02868   /*
02869    * Check if the geo granule and L1A granule is for the same instrument.
02870    */
02871 
02872   if (geo_satellite_id != L1A_Gran->satellite_id)
02873   {
02874     returnStatus = MODIS_F_NOK;
02875     L1BErrorMsg(location, returnStatus,
02876                 "*** INCORRECT GEOLOCATION FILE ***\n" 
02877                 "The satellite instrument in the geolocation file (lun 600000) is\n"
02878                 "different from that in the middle L1A granule (lun 500001).", 
02879                 NULL, 0, NULL, True);
02880     return returnStatus;
02881   } 
02882 
02883   /*
02884    * Check the run time parameter SatelliteInstrument from the PCF file against
02885    * the satellite inherent in the L1A data.
02886    */
02887 
02888   satelliteInstrument = runtime_params->SatelliteInstrument;
02889   if (!((strcmp(satelliteInstrument, "AM1M") == 0 && 
02890          L1A_Gran->satellite_id == TERRA) ||
02891         (strcmp(satelliteInstrument, "PM1M") == 0 &&
02892          L1A_Gran->satellite_id == AQUA)))
02893   {
02894     returnStatus = MODIS_F_NOK;
02895     L1BErrorMsg(location, returnStatus, 
02896                 "The satellite instrument set in the PCF does not match\n"
02897                 "the value inherent in the middle L1A granule.", 
02898                 NULL, 0, NULL, True);
02899     return returnStatus;
02900   }
02901 
02902 
02903   RFLAG = 0;
02904   if (SDnametoindex(L1A_Gran->sd_id, "EV_250m") == -1 ||
02905       SDnametoindex(L1A_Gran->sd_id, "BB_250m") == -1 ||
02906       SDnametoindex(L1A_Gran->sd_id, "SV_250m") == -1 ||
02907       SDnametoindex(L1A_Gran->sd_id, "SD_250m") == -1 ||
02908       SDnametoindex(L1A_Gran->sd_id, "SRCA_250m") == -1) {
02909     RFLAG = RFLAG | 1;
02910   }
02911 
02912   if (SDnametoindex(L1A_Gran->sd_id, "EV_500m") == -1 ||
02913       SDnametoindex(L1A_Gran->sd_id, "BB_500m") == -1 ||
02914       SDnametoindex(L1A_Gran->sd_id, "SV_500m") == -1 ||
02915       SDnametoindex(L1A_Gran->sd_id, "SD_500m") == -1 ||
02916       SDnametoindex(L1A_Gran->sd_id, "SRCA_500m") == -1) {
02917     RFLAG = RFLAG | 2;
02918   }
02919 
02920   if (SDnametoindex(L1A_Gran->sd_id, "EV_1km_day") == -1 ||
02921       SDnametoindex(L1A_Gran->sd_id, "BB_1km_day") == -1 ||
02922       SDnametoindex(L1A_Gran->sd_id, "SV_1km_day") == -1 ||
02923       SDnametoindex(L1A_Gran->sd_id, "SD_1km_day") == -1 ||
02924       SDnametoindex(L1A_Gran->sd_id, "SRCA_1km_day") == -1) {
02925     RFLAG = RFLAG | 4;
02926   }
02927 
02928   if (SDnametoindex(L1A_Gran->sd_id, "EV_1km_night") == -1 ||
02929       SDnametoindex(L1A_Gran->sd_id, "BB_1km_night") == -1 ||
02930       SDnametoindex(L1A_Gran->sd_id, "SV_1km_night") == -1 ||
02931       SDnametoindex(L1A_Gran->sd_id, "SD_1km_night") == -1 ||
02932       SDnametoindex(L1A_Gran->sd_id, "SRCA_1km_night") == -1) {
02933     RFLAG = RFLAG | 8;
02934   }
02935 
02936   if (SDfindattr(L1A_Gran->sd_id, "B_13_scale_parm") != -1)
02937     RSCL_FLAG = RSCL_FLAG | 1;
02938   if (SDfindattr(L1A_Gran->sd_id, "B_16_scale_parm") != -1)
02939     RSCL_FLAG = RSCL_FLAG | 2;
02940   if (SDfindattr(L1A_Gran->sd_id, "B_10_scale_parm") != -1)
02941     RSCL_FLAG = RSCL_FLAG | 4;
02942   if (SDfindattr(L1A_Gran->sd_id, "B_12_scale_parm") != -1)
02943     RSCL_FLAG = RSCL_FLAG | 8;
02944 
02945   returnStatus = MODIS_S_OK;  /* Successful completion of function */
02946   return returnStatus;        /* L1A granule remains open */
02947 }
02948 
02949 PGSt_SMF_status Get_Satellite_ID (PGSt_PC_Logical lun, int32 *satellite_ID)
02950 /*
02951 !C**************************************************************************
02952 !Description: This function reads the metadata "SHORTNAME" from the file
02953               designated by the lun and determines the satelitte name.
02954 
02955 !Input Parameters:
02956    int32 lun            logic identifier of the file.
02957 
02958 !Output Parameters:
02959    int32 *satellite_ID  identifier of the satellite (TERRA = 0, AQUA = 1,
02960                         INVALID_SATELLITE_ID = -1)
02961 
02962 !Revision History:
02963  (continue at top of the file)
02964 
02965    Revision 01.00 June 27, 2000
02966    Initial development.
02967    Zhenying Gu (zgu@mcst.gsfc.nasa.gov)
02968 
02969 !Team-unique Header:
02970    This software is developed by the MODIS Science Data Support
02971    Team for the National Aeronautics and Space Administration,
02972    Goddard Space Flight Center, under contract NAS5-32373.
02973 
02974 !References and Credits
02975    HDF portions developed at the National Center for Supercomputing
02976    Applications at the University of Illinois at Urbana-Champaign.
02977 
02978 !Design Notes:
02979 !END********************************************************************
02980 */
02981 {
02982   PGSt_SMF_status returnStatus = MODIS_S_OK;
02983   PGSt_integer       Version      = 1;
02984   char shortname[10];
02985   char *shortnameptr;
02986   char *attrName = "SHORTNAME";
02987   char *location = "Get_Satellite_ID";
02988 
02989   /* To use the address of the shortname[], a pointer is needed. */
02990 
02991   shortnameptr = shortname;
02992 
02993   /* Get the shortname */
02994 
02995   returnStatus = PGS_MET_GetPCAttr(lun, Version, "CoreMetadata.0",
02996                                    attrName, &shortnameptr);
02997   if (returnStatus != PGS_S_SUCCESS)
02998   {
02999     returnStatus = MODIS_F_READ_ERROR;
03000     L1BErrorMsg (location, returnStatus, "Could not get metadata \"SHORTNAME\".",
03001                  "PGS_MET_GetPCAttr", lun, NULL, True);
03002   }
03003 
03004   if (strncmp(shortname, "MOD", 3) == 0)
03005     *satellite_ID = TERRA;
03006   else if (strncmp(shortname, "MYD", 3) == 0)  
03007     *satellite_ID = AQUA;
03008   else
03009     *satellite_ID = INVALID_SATELLITE_ID; 
03010 
03011   return MODIS_S_OK;
03012 }
03013 
03014 PGSt_SMF_status Read_Run_Time_Parameters (Run_Time_Parameters_t *runtime_params)
03015 /*
03016 !C**************************************************************************
03017 !Description:
03018    Read all run-time parameters from the PCF file and set the values in the
03019    output variable.
03020 
03021 !Input Parameters:
03022    none
03023 
03024 !Output Parameters:
03025    Run_Time_Parameters_t *runtime_params  
03026                  contains SatelliteInstrument,
03027                           ReprocessingPlanned,
03028                           ReprocessingActual,
03029                           PGE02_Version,
03030                           MCST_LUT_Version,
03031                           Write_Night_Mode_HiRes_Data,
03032                           ProcessingEnvironment
03033 !Revision History:
03034  (continue at top of the file)
03035 
03036    Revision 01.07  October 31, 2003 Razor Issue #195
03037    Added the code of reading the ProcessingCenter value from the
03038    Run_Time_Parameters_t structure.
03039    Liqin Tan, SAIC GSO (ltan@saicmodis.com)
03040 
03041    Revision 01.06  October 2, 2002  Razor Issue #183
03042    Bug fix to setting ProcessingEnvironment.  The function used, while POSIX
03043      compliant, was on the list of functions forbidden by the SDP Toolkit.  
03044      "getenv" was subsituted.
03045    Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)  
03046  
03047    Revision 01.05  August 19, 2002  Razor Issue #183
03048    Revised setting ProcessingEnvironment.  It is now set by calling
03049      the appropriate POSIX function from within the module, rather
03050      than read from the PCF file.  This is to avoid seeing error messages
03051      from the SDP Toolkit for each granule when the field is left blank
03052      in the PCF file, which is allowable.
03053    Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)  
03054 
03055    Revision 01.04  April 25, 2002  Razor Issue #183
03056    Corrected syntax for setting ProcessingEnvironment to blank
03057    Gwyn Fireman, SAIC GSO (fireman@mcst.gsfc.nasa.gov)
03058 
03059    Revision 01.03  March 21, 2002  Razor Issue #181
03060    Added ProcessingEnvironment parameter as per SDST
03061    request for Collection 4
03062    Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)  
03063   
03064    Revision 01.02  November 12, 2001
03065    Added Write_Night_Mode_HiRes_Data (Razor issue #169)
03066    Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
03067    
03068    Revision 01.01  November 6, 2001
03069    Added MCST_LUT_Version (Razor issue #167)
03070    Alice Isaacman, SAIC GSO (Alice.R.Isaacman.1@gsfc.nasa.gov)
03071 
03072    Revision 01.00 February 21, 2001
03073    Initial development.
03074    Jim Rogers (rogers@mcst.gsfc.nasa.gov)
03075 
03076 !Team-unique Header:
03077    This software is developed by the MODIS Science Data Support
03078    Team for the National Aeronautics and Space Administration,
03079    Goddard Space Flight Center, under contract NAS5-32373.
03080 
03081 !References and Credits
03082    HDF portions developed at the National Center for Supercomputing
03083    Applications at the University of Illinois at Urbana-Champaign.
03084 
03085 !Design Notes:
03086 
03087 !END********************************************************************
03088 */
03089 {
03090   PGSt_SMF_status returnStatus;
03091 
03092   char  *location = "Read_Run_Time_Parameters";
03093         /* Default ProcessingEnvironment identifier */
03094   char  thisname[MAX_PROCESSING_ENVIRONMENT_STRLEN] = "";     
03095   char  *ename;  /* Value of environment variable from "getenv" calls */
03096   char  *osnames[4] = {"OS", "OSTYPE", "BRAND", "MACHINE"};
03097   char  *hostnames[3] = {"HOST", "HOSTNAME", "HOSTTYPE"};
03098   char  *revision = "REVISION";
03099   
03100   int16 j = 0;      /* A counter */  
03101 
03102   if (!runtime_params)
03103   {
03104     returnStatus = MODIS_F_INVALID_ARGUMENT;
03105     L1BErrorMsg(location, returnStatus, "Input runtime_params is NULL.",
03106                 NULL, 0, NULL, True);
03107     return returnStatus;
03108   }
03109 
03110   /*
03111    * Read and check the SatelliteInstrument value.
03112    */
03113 
03114   returnStatus = PGS_PC_GetConfigData(SATELLITE_INSTRUMENT_LUN,
03115                                       runtime_params->SatelliteInstrument);
03116   if (returnStatus != PGS_S_SUCCESS)
03117   {
03118     returnStatus = MODIS_F_NOK;
03119     L1BErrorMsg(location, returnStatus,
03120                 "Failed to get parameter SatelliteInstrument from PCF file.",
03121                 "PGS_PC_GetConfigData", SATELLITE_INSTRUMENT_LUN,
03122                 "Invalid PCF file", True);
03123     return returnStatus;
03124   }
03125   if (!(strcmp(runtime_params->SatelliteInstrument, "AM1M") == 0 ||
03126         strcmp(runtime_params->SatelliteInstrument, "PM1M") == 0))
03127   {
03128     char errmsg[256];
03129     sprintf (errmsg, 
03130              "The SatelliteInstrument value (%s) in the PCF is invalid.",
03131              runtime_params->SatelliteInstrument);
03132     returnStatus = MODIS_F_NOK;
03133     L1BErrorMsg(location, returnStatus, errmsg,
03134                 NULL, SATELLITE_INSTRUMENT_LUN, NULL, True);
03135     return returnStatus;
03136   }
03137 
03138   /*
03139    * Set the ProcessingEnvironment value.  This 
03140    * is not a mandatory entry and it is acceptable that 
03141    * the value be missing or blank, but in practice it is easier to set it
03142    * within L1B and avoid seeing error messages when it is not in the PCF file.
03143    */
03144 
03145    strcpy((runtime_params->ProcessingEnvironment), "");
03146 
03147     /*
03148      *    Obtain the processing environment fields 
03149      *        by calling the POSIX "getenv" function
03150      */ 
03151 
03152    for (j = 0; j < 4; j++)
03153    {
03154      ename = getenv(osnames[j]);
03155 
03156      if (ename != NULL)
03157 
03158      {
03159       /* Concatenate the desired names onto the ProcessingEnvironment string. */
03160       safe_strcat(thisname, ename, MAX_PROCESSING_ENVIRONMENT_STRLEN); 
03161        safe_strcat(thisname, " ", MAX_PROCESSING_ENVIRONMENT_STRLEN);
03162        
03163        break;
03164      }
03165    }
03166 
03167    for (j = 0; j < 3; j++)
03168    {
03169      ename = getenv(hostnames[j]);
03170 
03171      if (ename != NULL)
03172 
03173      {
03174       /* Concatenate the desired names onto the ProcessingEnvironment string. */
03175        safe_strcat(thisname, ename, MAX_PROCESSING_ENVIRONMENT_STRLEN); 
03176        safe_strcat(thisname, " ", MAX_PROCESSING_ENVIRONMENT_STRLEN);
03177        
03178        break;
03179      }
03180    }
03181 
03182    ename = getenv(revision);
03183 
03184    if (ename != NULL)
03185 
03186    {
03187     /* Concatenate the desired names onto the ProcessingEnvironment string. */
03188      safe_strcat(thisname, ename, MAX_PROCESSING_ENVIRONMENT_STRLEN); 
03189      safe_strcat(thisname, " ", MAX_PROCESSING_ENVIRONMENT_STRLEN);
03190    }
03191 
03192     /*
03193      * If the function getenv fails to return any values it is OK.  
03194      */
03195    
03196     safe_strcat(runtime_params->ProcessingEnvironment, thisname,
03197        MAX_PROCESSING_ENVIRONMENT_STRLEN);
03198     
03199   /*
03200    * Read the ReprocessingPlanned value.  This is not checked for specific
03201    * values because it is not clear that there is a constant set of valids
03202    * for this field (some could be added in the future).
03203    */
03204 
03205   returnStatus = PGS_PC_GetConfigData(REPROCESSING_PLANNED_LUN,
03206                                       runtime_params->ReprocessingPlanned);
03207   if (returnStatus != PGS_S_SUCCESS)
03208   {
03209     returnStatus = MODIS_F_NOK;
03210     L1BErrorMsg(location, returnStatus,
03211                 "Failed to get parameter ReprocessingPlanned from PCF file.",
03212                 "PGS_PC_GetConfigData", REPROCESSING_PLANNED_LUN,
03213                 "Invalid PCF file", True);
03214     return returnStatus;
03215   }
03216   if (strlen(runtime_params->ReprocessingPlanned) == 0)
03217   {
03218     returnStatus = MODIS_F_NOK;
03219     L1BErrorMsg(location, returnStatus,
03220                 "The ReprocessingPlanned value in the PCF is invalid (no string).",
03221                 NULL, REPROCESSING_PLANNED_LUN, NULL, True);
03222     return returnStatus;
03223   }
03224 
03225   /*
03226    * Read the ReprocessingActual value.  This is not checked for specific
03227    * values because it is not clear that there is a constant set of valids
03228    * for this field (some could be added in the future).
03229    */
03230 
03231   returnStatus = PGS_PC_GetConfigData(REPROCESSING_ACTUAL_LUN,
03232                                       runtime_params->ReprocessingActual);
03233   if (returnStatus != PGS_S_SUCCESS)
03234   {
03235     returnStatus = MODIS_F_NOK;
03236     L1BErrorMsg(location, returnStatus,
03237                 "Failed to get parameter ReprocessingActual from PCF file.",
03238                 "PGS_PC_GetConfigData", REPROCESSING_ACTUAL_LUN,
03239                 "Invalid PCF file", True);
03240     return returnStatus;
03241   }
03242   if (strlen(runtime_params->ReprocessingActual) == 0)
03243   {
03244     returnStatus = MODIS_F_NOK;
03245     L1BErrorMsg(location, returnStatus,
03246                 "The ReprocessingActual value in the PCF is invalid (no string).",
03247                 NULL, REPROCESSING_ACTUAL_LUN, NULL, True);
03248     return returnStatus;
03249   }
03250 
03251   /*
03252    * Read the Write_Night_Mode_HiRes_Data value.  This value must be 
03253    * True (1) or False (0).
03254    */
03255   returnStatus = PGS_PC_GetConfigData(WRITE_NIGHT_HIRES_LUN,
03256                          runtime_params->Write_Night_Mode_HiRes_Data);
03257   if (returnStatus != PGS_S_SUCCESS)
03258   {
03259     returnStatus = MODIS_F_NOK;
03260     L1BErrorMsg(location, returnStatus,
03261                 "Failed to get parameter Write_Night_Mode_HiRes_Data "
03262                 "from PCF file.",
03263                 "PGS_PC_GetConfigData", WRITE_NIGHT_HIRES_LUN,
03264                 "Invalid PCF file", True);
03265     return returnStatus;
03266   }
03267   if (!(strcmp(runtime_params->Write_Night_Mode_HiRes_Data, "0") == 0 ||
03268         strcmp(runtime_params->Write_Night_Mode_HiRes_Data, "1") == 0))
03269   {
03270     returnStatus = MODIS_F_NOK;
03271     L1BErrorMsg(location, returnStatus,
03272                 "The Write_Night_Mode_HiRes_Data value in the PCF file is "
03273                 "invalid (must be 0 (False) or 1 (True)).",
03274                 NULL, WRITE_NIGHT_HIRES_LUN, NULL, True);
03275     return returnStatus;
03276   }
03277   
03278   /*
03279    * Read the PGE02 Version value from PCF file.
03280    */
03281 
03282   returnStatus = PGS_PC_GetConfigData(PGE02_VERSION_LUN,
03283                                       runtime_params->PGE02_Version);
03284 
03285   if (returnStatus != PGS_S_SUCCESS)
03286   {
03287     returnStatus = MODIS_F_NOK;
03288     L1BErrorMsg(location, returnStatus,
03289                 "Failed to get parameter PGE02_Version from PCF file.",
03290                 "PGS_PC_GetConfigData", PGE02_VERSION_LUN,
03291                 "Invalid PCF file", True);
03292     return returnStatus;
03293   }
03294   if (strlen(runtime_params->PGE02_Version) == 0)
03295   {
03296     returnStatus = MODIS_F_NOK;
03297     L1BErrorMsg(location, returnStatus,
03298                 "The PGE02_Version value in the PCF is invalid (no string).",
03299                 NULL, PGE02_VERSION_LUN, NULL, True);
03300     return returnStatus;
03301   }
03302 
03303   /*
03304    * Check the PGE02 version given in the PCF file against the code macro.
03305    */
03306 
03307   if (strcmp(runtime_params->PGE02_Version, PGE02_VERSION))
03308   {
03309     returnStatus = MODIS_F_OUT_OF_RANGE;
03310     L1BErrorMsg(location, returnStatus,
03311       "PGE02 version in PCF file does not match that in the code files.",
03312       NULL, 0,
03313       "Code files must have the same PGE02 version as specified in the PCF file.",
03314       True);
03315     return returnStatus;
03316   }
03317 
03318   /*
03319    * Read the MCST_LUT_Version value.  This is not checked for specific
03320    * values because the values vary with the MCST LUT Version numbers.
03321    */
03322 
03323   returnStatus = PGS_PC_GetConfigData(MCST_LUT_VERSION_LUN,
03324                                       runtime_params->MCST_LUT_Version);
03325 
03326   if (returnStatus != PGS_S_SUCCESS)
03327   {
03328     returnStatus = MODIS_F_NOK;
03329     L1BErrorMsg(location, returnStatus,
03330                 "Failed to get parameter MCST_LUT_Version from PCF file.",
03331                 "PGS_PC_GetConfigData", MCST_LUT_VERSION_LUN,
03332                 "Invalid PCF file", True);
03333     return returnStatus;
03334   }
03335   if (strlen(runtime_params->MCST_LUT_Version) == 0)
03336   {
03337     returnStatus = MODIS_F_NOK;
03338     L1BErrorMsg(location, returnStatus,
03339                 "The MCST_LUT_Version value in the PCF is invalid (no string).",
03340                 NULL, MCST_LUT_VERSION_LUN, NULL, True);
03341     return returnStatus;
03342   }
03343 
03344   /*
03345    * Read the ProcessingCenter value from the Run_Time_Parameters_t
03346    * structure.
03347    */
03348 
03349   returnStatus = PGS_PC_GetConfigData(PROCESSING_CENTER_LUN,
03350                                       runtime_params->ProcessingCenter);
03351   if (returnStatus != PGS_S_SUCCESS)
03352   {
03353     returnStatus = MODIS_F_NOK;
03354     L1BErrorMsg(location, returnStatus,
03355                 "Failed to get parameter ProcessingCenter from PCF file.",
03356                 "PGS_PC_GetConfigData", PROCESSING_CENTER_LUN,
03357                 "Invalid PCF file", True);
03358     return returnStatus;
03359   }
03360   if (strlen(runtime_params->ProcessingCenter) == 0)
03361   {
03362     returnStatus = MODIS_F_NOK;
03363     L1BErrorMsg(location, returnStatus,
03364                 "The ProcessingCenter value in the PCF is invalid (no string).",
03365                 NULL, PROCESSING_CENTER_LUN, NULL, True);
03366     return returnStatus;
03367   }
03368 
03369     return MODIS_S_OK;
03370 }
03371