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