OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
GEO_write_granule_metadata.c
Go to the documentation of this file.
1 #include "PGS_TD.h"
2 #include "GEO_earth.h"
3 #include "GEO_output.h"
4 #include "GEO_product.h"
5 #include "PGS_MODIS_35251.h"
6 #include "L1a_data.h"
7 
8 PGSt_SMF_status GEO_write_granule_metadata(
9  MODFILE * const geo_file,
10  MODFILE * const l1a_file,
11  GEO_param_struct const * const geo_parameter,
12  GEO_bcoord_struct const * const bounding_coords,
13  int const version,
14  l1a_data_struct * const l1a_data,
15  qa_metadata_struct * const qa_metadata
16 )
17 
18 /**********************************************************************
19 !C
20 
21 !Description:
22  Routine in Output group of the Level-1A geolocation software to write
23  the granule-level metadata to the geolocation product file.
24 
25 !Input Parameters:
26  geo_file MAPI structure for geolocation file
27  l1a_file MAPI structure for Level 1A file
28  geo_parameter program parameters read from (or derived directly from)
29  the geolocation parameter file
30  bounding_coords the granule's bounding coordinates.
31  version version number of input/output files.
32 
33 !Output Parameters:
34  None
35 
36 !Input/Output Parameters
37  l1a_data data read from L1A file
38  qa_metadata Granule-level quality assurance metadata. Optional,
39  can be null.
40 
41 Return Values:
42  MODIS_E_GEO If any subroutine fails.
43  MODIS_E_GEO_EPH If the ephemeris file contains an orbit number
44  that is inconsistent with the orbit time.
45  MODIS_E_BAD_INPUT_ARG If any pointer argument other than qa_metadata
46  is null.
47  PGS_S_SUCCESS Otherwise.
48 
49 Externally Defined:
50  AVERAGE_TEMPERATURES "GEO_product.h"
51  FILL_INT8 "GEO_output.h"
52  L1A_ENGINEERING_GRP "L1a_data.h"
53  MAPIOK "mapi.h"
54  MAX_SCAN_NUMBER "GEO_geo.h"
55  MODIS_E_BAD_INPUT_ARG "PGS_MODIS_35251.h"
56  MODIS_E_GEO "PGS_MODIS_35251.h"
57  MODIS_E_GEO_EPH "PGS_MODIS_35251.h"
58  MODIS_W_GEO_EPHEMERIS "PGS_MODIS_35251.h"
59  MODIS_W_NO_GEO "PGS_MODIS_35251.h"
60  PGSd_EOS_AM "PGS_TD.h"
61  PGSd_EOS_PM "PGS_TD.h"
62  PGSd_PC_FILE_PATH_MAX "PGS_PC.h"
63  PGSd_PC_LINE_LENGTH_MAX "PGS_PC.h"
64  PGSEPH_E_NO_SC_EPHEM_FILE "PGS_EPH.h"
65  PGS_S_SUCCESS "PGS_SMF.h"
66  SUCCESS "GEO_basic.h"
67  TIMECODEASIZE "smfio.h"
68 
69 Called by:
70  GEO_locate_one_granule
71 
72 
73 Routines Called:
74  GEO_get_GRing_points "GEO_earth.h"
75  GEO_get_utcpole_metadata "GEO_output.h"
76  GEO_get_version_metadata "GEO_output.h"
77  GEO_update_L1A_metadata "GEO_output.h"
78  GEO_write_ECS_metadata "GEO_output.h"
79  GEO_write_geospecific_metadata "GEO_output.h"
80  GEO_write_input_metadata "GEO_output.h"
81  GEO_write_parameters "GEO_output.h"
82  modsmf "smfio.h"
83  PGS_EPH_GetEphMet "PGS_EPH.h"
84  PGS_TD_UTCtoTAI "PGS_TD_Prototypes.h"
85  putMODIStable "mapi.h"
86  PGS_SMF_GenerateStatusReport "PGS_SMF.h"
87 
88 
89 !Revision History:
90 $Log: GEO_write_granule_metadata.c,v $
91 Revision 6.3 2010/06/30 21:28:26 kuyper
92 Added casts of cumulated_gflags to a printable type.
93 
94 Revision 6.2 2010/06/18 20:57:58 kuyper
95 Corrected format of LogReport message.
96 
97 Revision 6.1 2010/05/28 21:50:04 kuyper
98 Helped resolve Bug 2470 by removing a parameter.
99 Changed to return an SMF status code.
100 Improved several error messages.
101 Corrected sprintf() format codes for C90 compatibility.
102 Improved const-safety.
103 
104 James Kuyper Jr. James.R.Kuyper@NASA.gov
105 
106 Revision 5.6 2008/12/19 19:07:29 kuyper
107 Corrected size of orbit_validation array.
108 
109 Revision 5.5 2008/12/15 21:12:59 kuyper
110 Changed to make orbit number validation optional, controlled by a PCF
111  parameter.
112 
113 Revision 5.4 2008/09/21 19:06:38 kuyper
114 Increased size of message buffer to accomodate long path names.
115 Changed to pass sc_tag to GEO_write_input_metadata().
116 
117 Revision 5.3 2005/10/05 16:51:09 vlin
118 Code added to check for invalid Orbit Number from Ephemeris file.
119 MOD_PR03 will fail if the orbit number is incorrect.
120 vlin@saicmodis.com
121 
122 Revision 5.2 2004/10/15 22:03:17 kuyper
123 Corrected position of bounding_coords parameter.
124 
125 Revision 5.1 2004/09/22 19:44:25 vlin
126 Changed to pass bounding_coords to GEO_update_L1A_metadata().
127 Added maneuver_list parameter, passed on to GEO_write_geospecific_metadata.
128 Added a status report. vlin@saicmodis.com
129 
130 Revision 4.5 2004/04/09 22:17:45 kuyper
131 Changed FILL_BYTE to FILL_INT8.
132 
133 Revision 4.4 2004/01/23 21:40:35 vlin
134 PGS_PC_GetUniversalReference not called and removed from prologue.
135 
136 Revision 4.3 2004/01/20 19:44:27 kuyper
137 Corrected error messages.
138 Added validity checks on file handles.
139 
140 Revision 4.2 2003/10/07 13:53:29 kuyper
141 Corrected setting of equatorcrossingtime.
142 
143 Revision 4.1 2003/08/12 23:05:33 kuyper
144 Corrected to identify l1a_data and qa_metadata as input/output.
145 Added code to write the AverageTemperatures vdata record.
146 Moved input pointer handling into GEO_write_input_metadata().
147 Dropped code setting modisproductfilename.
148 Simplified handling of orbitdescendtime.
149 Changed to expect status codes from GEO_update_l1a_metadata() and
150  GEO_write_ECS_metadata.
151 Changed format for RMS error.
152 
153 Requirements:
154  PR03-F-1-3
155  PR03-F-1-3.1
156  PR03-F-4.1-1
157  PR03-F-4.1-1.6
158  PR03-F-4.1-2
159  PR03-I-1
160  PR03-I-2
161  PR03-S-1
162 
163 
164 !Team-unique Header:
165  This software is developed by the MODIS Science Data Support
166  Team for the National Aeronautics and Space Administration,
167  Goddard Space Flight Center, under contract NAS5-32373.
168 
169 !END
170 *********************************************************************************/
171 {
172  static pointer_metadata_struct pointer_metadata;
173 
174  EPH_metadata_struct EPH_metadata={-1, -999.0*DEG2RAD, "", ""};
175  GEO_GRing_struct GRing_points = {"N", {1, 2, 3, 4},
176  {0.01, 0.01, 0.0, 0.0}, /* Latitude */
177  {0.0, 0.01, 0.01, 0.0} /* Longitude. */};
178 
179  utcpole_metadata_struct utcpole_metadata = {"", {0}};
180  PGSt_double offset = 0.0; /* offset from rangedatetime, seconds.*/
181  PGSt_integer numOrbits=1;
182  PGSt_tag sc_tag=PGSd_EOS_AM;
183  int i;
184  PGSt_SMF_status retval = PGS_S_SUCCESS;
185  double pred_dtime;
186  char msgbuf[2*PGSd_PC_FILE_PATH_MAX];
187  char orbitAscendTime[TIMECODEASIZE];
188  char orbitdescendtime[TIMECODEASIZE];
189  char rangedatetime[TIMECODEASIZE];
190  char sci_abnorm[2]="1", sci_state[2]="1";
191  PGSt_integer param_version=1;
192  static char filefunc[] = __FILE__ ", GEO_write_granule_metadata";
193  int rtcode;
194 
195  if (l1a_file==NULL || geo_file==NULL || l1a_data == NULL ||
196  geo_parameter == NULL || bounding_coords == NULL)
197  {
198  sprintf(msgbuf, "l1a_file = %p, geo_file=%p, l1a_data = %p,\n"
199  "geo_parameter = %p, bounding_coords=%p",
200  (void*)l1a_file, (void*)geo_file, (void*)l1a_data,
201  (void*)geo_parameter, (void*)bounding_coords);
202  modsmf(MODIS_E_BAD_INPUT_ARG, msgbuf, filefunc);
203 
204  return MODIS_E_BAD_INPUT_ARG;
205  }
206 
207  /* Read l1a_data.ECS_metadata and fill in uptcpole_metadata */
208  if (GEO_get_utcpole_metadata(&(l1a_data->ECS_metadata), &utcpole_metadata)
209  != PGS_S_SUCCESS) {
210  modsmf(MODIS_E_GEO, "GEO_get_utcpole_metadata()", filefunc);
211 
212  retval = MODIS_E_GEO;
213  }
214 
215  /* Write the geolocation geo_parameter's to the geolocation file*/
216  if( SUCCESS != GEO_write_parameters(geo_file,
217  (GEO_param_struct *)geo_parameter) )
218  {
219  sprintf(msgbuf, "GEO_write_parameters(\"%s\")", geo_file->filename);
220  modsmf(MODIS_E_GEO, msgbuf, filefunc);
221 
222  retval = MODIS_E_GEO;
223  }
224 
225  /* Calculate spatial metadata */
226  rtcode = GEO_get_GRing_points(&GRing_points);
227 
228  /* Since the V2.1 GEO_get_GRing_points will return WARNING for several
229  * 'sparse data' conditions (which are more likely to occur than the
230  * functional failures) retval is set to FAIL only for a FAIL return.
231  */
232  if(rtcode != PGS_S_SUCCESS && rtcode != MODIS_W_NO_GEO)
233  {
234  modsmf(MODIS_E_GEO, "GEO_get_GRing_points()", filefunc);
235 
236  retval = MODIS_E_GEO;
237  }
238 
239  sprintf(rangedatetime, "%.10sT%.15sZ",
240  l1a_data->ECS_metadata.rangebeginningdate,
241  l1a_data->ECS_metadata.rangebeginningtime);
242 
243  if(strncmp(geo_parameter->spacecraft_ID, "Terra", sizeof("Terra")) )
244  {
245  sc_tag = PGSd_EOS_PM; /* Already validated; must be "Aqua" */
246  param_version = 2;
247  }
248 
249  rtcode = PGS_EPH_GetEphMet(sc_tag, 1, rangedatetime, &offset, &numOrbits,
250  &EPH_metadata.orbitnumber, &orbitAscendTime, &orbitdescendtime,
251  &EPH_metadata.equatorcrossinglongitude);
252 
253  if(rtcode != PGS_S_SUCCESS)
254  {
255  if(rtcode == PGSEPH_E_NO_SC_EPHEM_FILE)
256  modsmf(MODIS_W_GEO_EPHEMERIS, rangedatetime, filefunc);
257  else
258  {
259  sprintf(msgbuf, "PGS_EPH_GetEphMet(\"%s\")", rangedatetime);
260  modsmf(MODIS_E_GEO, msgbuf, filefunc);
261 
262  retval = MODIS_E_GEO;
263  }
264  }
265  else
266  {
267  static char orbit_validation[PGSd_PC_LINE_LENGTH_MAX];
268  PGSt_double TAI_orbitdescendtime;
269 
270  if(orbit_validation[0] == '\0' &&
271  (PGS_PC_GetConfigData(VALIDATE_ORBIT_NO_LUN, orbit_validation)
272  != PGS_S_SUCCESS ||
273  (strcmp(orbit_validation, "TRUE") &&
274  strcmp(orbit_validation, "FALSE"))) )
275  {
276  sprintf(msgbuf, "PGS_PC_GetConfigData():\"%s\"", orbit_validation);
277  modsmf(MODIS_E_GEO, msgbuf, filefunc);
278  orbit_validation[0] = '\0';
279  }
280 
281 
282  /* Assumes that orbitdescendtime has the format of a UTC A time code:
283  * "YYYY-MM-DDTHH:MM:SS.SSSSSSZ"
284  */
285  if (PGS_TD_UTCtoTAI(orbitdescendtime, &TAI_orbitdescendtime) !=
286  PGS_S_SUCCESS)
287  {
288  sprintf(msgbuf, "PGS_TD_UTCtoTAI(\"%s\")", orbitdescendtime);
289  modsmf(MODIS_E_GEO, msgbuf, filefunc);
290 
291  retval = MODIS_E_GEO;
292  }
293  else if(strcmp(orbit_validation, "TRUE")==0)
294  {
295  int step = (EPH_metadata.orbitnumber <
296  geo_parameter->orbit_valid_params.transition_orbit) ? 0 : 1;
297  pred_dtime = geo_parameter->orbit_valid_params.descend_time_0[step] +
298  geo_parameter->orbit_valid_params.period[step]*
299  EPH_metadata.orbitnumber;
300  if (abs(TAI_orbitdescendtime - pred_dtime) >
301  geo_parameter->orbit_valid_params.orbit_tolerance[step])
302  {
303  sprintf(msgbuf,". Orbit number = %d, orbit descend time = %s",
304  EPH_metadata.orbitnumber, orbitdescendtime);
305  modsmf(MODIS_E_GEO_EPH, msgbuf, filefunc);
306 
307  retval = MODIS_E_GEO_EPH;
308  }
309  }
310 
311  memcpy(EPH_metadata.equatorcrossingdate, orbitdescendtime, 10);
312  EPH_metadata.equatorcrossingdate[10] = '\0';
313  memcpy(EPH_metadata.equatorcrossingtime, orbitdescendtime+11, 15);
314  EPH_metadata.equatorcrossingtime[15] = '\0';
315  }
316 
317  if( GEO_update_L1A_metadata(l1a_file, &GRing_points, &EPH_metadata,
318  (GEO_bcoord_struct *)bounding_coords) != PGS_S_SUCCESS)
319  {
320  sprintf(msgbuf, "GEO_update_L1A_metadata(%s)", l1a_file->filename);
321  modsmf(MODIS_E_GEO, msgbuf, filefunc);
322 
323  retval = MODIS_E_GEO;
324  }
325 
326  if(GEO_write_input_metadata(geo_file, version, param_version,
327  &pointer_metadata, sc_tag) != PGS_S_SUCCESS)
328  {
329  sprintf(msgbuf, "GEO_write_input_metadata(\"%s\", %ld, %ld )",
330  geo_file->filename, (long)version, (long)param_version);
331  modsmf(MODIS_E_GEO, msgbuf, filefunc);
332 
333  retval = MODIS_E_GEO;
334  }
335 
336  /* Granule-level SCI_STATE and SCI_ABNORM */
337  if (l1a_data->num_scans <= MAX_SCAN_NUMBER) /* array bounds protection */
338  for(i=0; i<l1a_data->num_scans; i++)
339  {
340  if((l1a_data->frame_data[i].SCI_STATE!=1)
341  && (l1a_data->frame_data[i].SCI_STATE != FILL_INT8) )
342  sci_state[0] = '0';
343 
344  if((l1a_data->frame_data[i].SCI_ABNORM!=1)
345  && (l1a_data->frame_data[i].SCI_ABNORM!= FILL_INT8) )
346  sci_abnorm[0] = '0';
347  }
348  else
349  sci_state[0] = sci_abnorm[0] = '0';
350 
351  if (qa_metadata)
352  {
353  sprintf(qa_metadata->rms_error,"%-8.3g", geo_parameter->RMS_error);
354 
355  if (retval != SUCCESS)
356  qa_metadata->retval = retval;
357  }
358 
359  if (GEO_get_version_metadata(&(l1a_data->ECS_metadata.version_metadata))
360  != PGS_S_SUCCESS)
361  {
362  modsmf(MODIS_E_GEO, "GEO_get_version_metadata()", filefunc);
363 
364  retval = MODIS_E_GEO;
365  }
366 
367  if(GEO_write_ECS_metadata(geo_file, &l1a_data->ECS_metadata, &EPH_metadata,
368  (GEO_bcoord_struct *)bounding_coords, &GRing_points,
369  &pointer_metadata, qa_metadata, sci_state, sci_abnorm) != PGS_S_SUCCESS)
370  {
371  sprintf(msgbuf, "GEO_write_ECS_metadata(\"%s\")", geo_file->filename);
372  modsmf(MODIS_E_GEO, msgbuf, filefunc);
373 
374  retval = MODIS_E_GEO;
375  }
376 
377  /* Write geolocation specific metadata */
378  if(GEO_write_geospecific_metadata( geo_file, &l1a_data->granule_metadata,
379  l1a_data->num_scans, geo_parameter, qa_metadata, &utcpole_metadata)
380  != PGS_S_SUCCESS)
381  {
382  sprintf(msgbuf, "GEO_write_geospecific_metadata(\"%s\")",
383  geo_file->filename);
384  modsmf(MODIS_E_GEO, msgbuf, filefunc);
385 
386  retval = MODIS_E_GEO;
387  }
388 
389  if(putMODIStable(geo_file, AVERAGE_TEMPERATURES, L1A_ENGINEERING_GRP,
390  0, 1, (unsigned char*)l1a_data->temperatures) != MAPIOK)
391  {
392  modsmf(MODIS_E_GEO, "putMODIStable(\"" AVERAGE_TEMPERATURES "\")",
393  filefunc);
394 
395  retval = MODIS_E_GEO;
396  }
397 
398  /* Write to status report */
399  sprintf(msgbuf,
400  "Input file name: %s\n"
401  "Output file name: %s\n"
402  "Local Granule ID: %s\n"
403  "scans: %d\n"
404  "pixels: %d\n"
405  "\tmissing: %d\n"
406  "\tout of bounds: %d\n"
407  "Cumulated gflags: %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu\n"
408  "Bounding coordinates\n"
409  "\teast: %f\n"
410  "\twest: %f\n"
411  "\tnorth: %f\n"
412  "\tsouth: %f",
413  l1a_file->filename, geo_file->filename,
414  l1a_data->ECS_metadata.localinputgranuleid, l1a_data->num_scans,
415  qa_metadata->no_of_pixels, qa_metadata->missingdata,
416  qa_metadata->outofboundsdata,
417  (unsigned long)qa_metadata->cumulated_gflags[0],
418  (unsigned long)qa_metadata->cumulated_gflags[1],
419  (unsigned long)qa_metadata->cumulated_gflags[2],
420  (unsigned long)qa_metadata->cumulated_gflags[3],
421  (unsigned long)qa_metadata->cumulated_gflags[4],
422  (unsigned long)qa_metadata->cumulated_gflags[5],
423  (unsigned long)qa_metadata->cumulated_gflags[6],
424  (unsigned long)qa_metadata->cumulated_gflags[7],
425  bounding_coords->eastcoord,
426  bounding_coords->westcoord, bounding_coords->northcoord,
427  bounding_coords->southcoord);
428  PGS_SMF_GenerateStatusReport(msgbuf);
429 
430  return retval;
431 }
#define VALIDATE_ORBIT_NO_LUN
Definition: GEO_geo.h:94
#define SUCCESS
Definition: ObpgReadGrid.h:15
PGSt_integer orbitnumber
#define L1A_ENGINEERING_GRP
Definition: L1a_data.h:105
char equatorcrossingdate[11]
PGSt_SMF_status GEO_write_ECS_metadata(MODFILE *const geo_file, ECS_metadata_struct *const ECS_metadata, EPH_metadata_struct *const EPH_metadata, GEO_bcoord_struct *const bounding_coords, GEO_GRing_struct *const GRing_points, pointer_metadata_struct *const pointer_metadata, qa_metadata_struct *const qa_metadata, char *const sci_state, char *const sci_abnorm)
char equatorcrossingtime[16]
#define MODIS_E_GEO_EPH
#define NULL
Definition: decode_rs.h:63
#define MODIS_E_BAD_INPUT_ARG
int16_t * l1a_data
Definition: l1a_seawifs.c:84
int GEO_write_parameters(MODFILE *const, GEO_param_struct const *)
PGSt_SMF_status GEO_update_L1A_metadata(MODFILE *const l1a_file, GEO_GRing_struct *const GRing_points, EPH_metadata_struct *const EPH_metadata, GEO_bcoord_struct *const bounding_coords)
#define TIMECODEASIZE
Definition: Metadata.c:59
PGSt_SMF_status GEO_get_utcpole_metadata(const ECS_metadata_struct *ECS_metadata, utcpole_metadata_struct *utcpole_metadata)
#define MODIS_E_GEO
double westcoord
Definition: GEO_geo.h:185
PGSt_SMF_status GEO_write_geospecific_metadata(MODFILE *const geo_file, l1a_metadata_struct const *const granule_metadata, int const number_of_scans, GEO_param_struct const *const geo_parameter, qa_metadata_struct const *const qa_metadata, utcpole_metadata_struct const *const utcpole_metadata)
#define MODIS_W_GEO_EPHEMERIS
PGSt_double equatorcrossinglongitude
PGSt_SMF_status GEO_get_version_metadata(version_metadata_struct *version_metadata)
double southcoord
Definition: GEO_geo.h:184
#define AVERAGE_TEMPERATURES
Definition: GEO_product.h:271
double eastcoord
Definition: GEO_geo.h:183
orbit_validation_params_struct orbit_valid_params
#define MODIS_W_NO_GEO
PGSt_SMF_status GEO_get_GRing_points(GEO_GRing_struct *const GRing_points)
const int MAX_SCAN_NUMBER
int GEO_write_input_metadata(MODFILE *const geo_file, int const l1a_version, PGSt_integer const param_version, pointer_metadata_struct *const pointer_metadata, PGSt_tag sc_tag)
double northcoord
Definition: GEO_geo.h:182
PGSt_SMF_status GEO_write_granule_metadata(MODFILE *const geo_file, MODFILE *const l1a_file, GEO_param_struct const *const geo_parameter, GEO_bcoord_struct const *const bounding_coords, int const version, l1a_data_struct *const l1a_data, qa_metadata_struct *const qa_metadata)
#define FILL_INT8
Definition: GEO_output.h:108
l2prod offset
#define abs(a)
Definition: misc.h:90
int i
Definition: decode_rs.h:71
uint32 cumulated_gflags[8]
#define DEG2RAD
Definition: GEO_geo.h:174
version
Definition: setup.py:15