OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
o3nrt_omi.c
Go to the documentation of this file.
1 /*****************************************************************
2  * File: o3nrt_omi.c
3  *
4  * Purpose: create HDF ancillary real time datafile from
5  * OMI TOMS ascii input only - from o3nrt
6  *
7  * NOTE: Due to the non-ovelapping nature of the EPTOMS product
8  * 2 days worth of data are required to fill all pixels in
9  * an image. All other products cover the globe with one
10  * days's worth of data.
11  *
12  * Description: this program will create a HDF with the components:
13  *
14  * HDF DAAC compliant global attributes
15  * Geometry Vdata for storage of LAT/LON endpoints and step
16  * 2-D data parameter OZONE SDS
17  * 2-D OZONE QC flag (padded all zeroes for TOMS and TOVS,
18  * with EARLIERVAL to EPTOMS missing points filled with
19  * prior day's data)
20  *
21  * Input parms:
22  * char *annotfile - input file of DAAC compliant annots ("fillenv.eptomsnrt")
23  * char *infile - input ozone file to process ("ga960903.ept")
24  * char *directory - output file directory (".")
25  * char *itype - "OMITOMS"
26  * char *prevfile - input ozone file for previous day ("OMITOMS" only)
27  *
28  * Returns: false on error
29  *
30  * Subs called:
31  * fillenv_annot - fill an array with metadata read from
32  * an ASCII file.
33  * count_annot- determine number of entries in ASCII annot file.
34  * rdgrid_ - read TOMS/TOVS ASCII grid (FORTRAN routine)
35  * gregor_ - calc gregorian date from julian number.
36  * startHDF - open HDF file structures
37  * setupGrid - open HDF grid struct.
38  * wrtattr - write HDF attributes to file
39  * wrtsds - write SDS from array to file
40  * pexit - print fatal errors
41  * check_usage- check command line args
42  * closeHDFstructs- close HDF file structs
43  * writeGeom - write HDF file geometry (lat/lon)
44  * addAttr - set file local or global attributes
45  * setSDSref - get SDS ref and set to Vgroup
46  *
47  * History: none
48  *
49  * Note: This program is meant to generate SeaWiFS style HDF
50  * ancillary real-time datafiles.
51  * The string parsing used by rdgrid may need revised to
52  * match any new TOMS/TOVS/EPTOMS file formats.
53  *
54  * Author: Brian D. Schieber, GSC, 3/93
55  *
56  *
57  * Modification history:
58  * BDS, 4/22/93 - mod int32 to int16 (per L. Kumar, Jimf, Darzi)
59  * BDS, 6/7/93 - program now generates output filenames consistent
60  * with SeaWiFS specs.
61  * BDS, 8/30/93 - redesign for new HDF specs. Refer to
62  * "SeaWiFS ANCILLARY DATA FORMAT (HDF) UPDATE"
63  * paper (SeaWiFS tech. memo) for details.
64  * BDS, 5/17/95 - Comply with mods in "Operational Archive Prod. Specs."
65  * Version 2.7 (2 May 1995) Many changes.
66  * BDS, 10/1/95 - Comply with 2.8 specs:
67  * With this modification, TOVS and TOMS input ASCII
68  * files diverge:
69  * 1. TOVS input now contains an extra line of header to
70  * describe the starting and ending times of the data.
71  * 2. Filenames of HDF files made from TOVS input files
72  * now list the starting AND ending times of the input.
73  * BDS, 12/8/95 - change metadata "Process Control" to "Processing Control"
74  * - append terminators to some metadata strings.
75  * BDS, 8/21/96 - renamed 'perror' to 'pexit' to avoid HDF4.0 conflict.
76  * BDS, 9/4/96 - modifications to support new EPTOMS files.
77  * BDS, 9/12/96 - mod to add Ascention time metadata. Also support all
78  * three ozone sources: TOMS, TOVS, EPTOMS
79  * BDS, 9/19/96 - also support ADTOMS (not [optionally] using 2nd file as in EPTOMS)
80  * Add M.Darzi's new flags for type of EPTOMS data fill:
81  * EPTOMS values for points in "QC grid" are:
82  * 0 - no change to original value.
83  * 1 - value changed by QC routine (not this program)
84  * 10 - value from earlier source product.
85  * 11 - value from nearest non-zero grid point.
86  * W. Robinson, GSC, 3 Jul 97 call a smoothing routine: world_avg for the
87  * EP TOMS data. Also, set start time of EP TOMS to be start
88  * time of the primary file, do not use start of second
89  * file used for filler.
90  * W. Robinson, SAIC, 15 Jun 09 Quick mod to read the OMI with 360 pix,
91  * 180 lines
92  *****************************************************************/
93 #include <mfhdf.h>
94 #include "ancil.h"
95 #include <time.h>
96 #include <unistd.h>
97 #include "ancnrt_proto.h"
98 
99 /*
100  * Ozone specific settings
101  */
102 
103 #define VGROUPNAME "Geophysical Data"
104 #define BIN_METH 2
105 #define REGISTRATION CENTER
106 #define EARLIERVAL 10 /* QC grid value for EPTOMS pts filled from prev day */
107 #define NEARESTVAL 11 /* QC grid value for EPTOMS pts filled from nearest
108  (file 1 or 2) non-zero point */
109 
110 int main(int argc, char *argv[]) {
111  char *datafmt;
112  char *datalabel;
113  char dataunit[MAXNAMELNG];
114  char dataattr[MAXNAMELNG];
115  char directory[MAXNAMELNG];
116  char itype[MAXNAMELNG];
117  char annotfile[MAXNAMELNG];
118  char outfile[MAXNAMELNG];
119  char outfilename[MAXNAMELNG];
120  char infile[MAXNAMELNG];
121  char prevfile[MAXNAMELNG];
122  char start_time[17];
123  char end_time[17];
124  char node_time[17];
125  char acntime[9];
126  int i, j, k, l, kk;
127  int rank;
128  int type;
129  int result;
130  int array_size = 0;
131  int numannarr = 0;
132  int modified_pts = 0; /* EPTOMS, track pts modded */
133  int i_skip; /* integer dummy var */
134  char tmpvar[MAXNAMELNG]; /* temp time variable */
135  int year, julval, hour, min; /* data times */
136  short startyear, startday, starthour, /* start data times */
137  startmin, startsec;
138  int startmsec;
139  short endyear, endday, endhour, /* end data times */
140  endmin, endsec;
141  int endmsec;
142  int startmsecday; /* millisec of day */
143  int endmsecday; /* millisec of day */
144  int pyear = 0; /* local proc times */
145  float latstep, lonstep; /* lat/lon incr. */
146  float nmostlat, smostlat, wmostlon, emostlon; /* lat/lon corners */
147  int latsz, lonsz; /* lat/lon size */
148  int16 datarr[180][360];
149  int16 prevdatarr[180][360];
150  int32 shape[2];
151  time_t t; /* processing time */
152  struct tm *localtm; /* processing time */
153  struct annotation *xannot;
154 
155  /*
156  * HDF datafile variables
157  */
158 
159  int32 sdfid, fid, gridid;
160  int32 datatype;
161 
162  /*
163  * data type array pointers
164  */
165 
166  int8 *int8_SDSdataQC;
167  int16 *int16_SDSdataO3;
168 
169  /*
170  * functions used
171  */
172 
173  int wrtattr();
174  int32 wrtsds();
175  int startHDF();
176  int setSDSref();
177  int closeHDFstructs();
178  void pexit();
179  int8 check_usage();
180  struct annotation * fillenv_annot();
181  char *upcase();
182  void world_avg(int16 *, int32, int32, int, int, int16 *);
183 
184  /*
185  * ------- check command line arguments and set args ------------------
186  */
187 
188  if ((check_usage(argc, argv)) != 0) exit(-1);
189 
190  strcpy(annotfile, argv[1]);
191  strcpy(infile, argv[2]);
192  strcpy(directory, argv[3]);
193  strcpy(itype, argv[4]);
194 
195  /*
196  * ------- Read ozone ASCII file and extract data grid ----------
197  */
198 
199  if (!strcmp(upcase(itype), "OMITOMS")) {
200  type = 2;
201  if (argc == 6) strcpy(prevfile, argv[5]);
202  else strcpy(prevfile, ""); /* no 2nd file */
203  } else {
204  pexit("ERROR: OMITOMS not specified");
205  }
206 
207  /*
208  * Read ASCII OZONE grid
209  */
210 
211  rdgrid_(infile, &type, (int16*) datarr, &julval, &year, start_time, end_time,
212  acntime, &result, 255, 17, 17, 9);
213  if (result == 1) pexit("rdgrid_");
214 
215  /*
216  * ------- Create component date/time ----------
217  * TOVS input ASCII data provides start and end times in an additional
218  * header line.
219  * TOMS, EPTOMS and ADTOMS input ASCII does not provide start and end time,
220  * only one header line for year, Gregorian day, and Julian day.
221  */
222 
223  if (type == 0) { /* TOMS data */
224 
225  gregor_(&julval, &year, &i_skip, &i_skip); /* get year from julian */
226 
227  hour = 12;
228  sprintf(outfile, "%s/S%04d%03d%02d_%s.OZONE", directory, year,
229  julval, hour, "TOMS");
230  sprintf(outfilename, "S%04d%03d%02d_%s.OZONE", year, julval,
231  hour, "TOMS");
232 
233  /* Make hour, min, sec, ms all zeros for TOMS */
234 
235  sprintf(start_time, "%04d%03d%02d0000000", year, julval, hour);
236  sprintf(end_time, "%04d%03d%02d0000000", year, julval, hour);
237 
238  startyear = year;
239  endyear = year;
240  startday = julval;
241  endday = julval;
242  startmsecday = endmsecday = 0;
243  } else if (type == 1) { /* TOVS */
244 
245  strcpy(&start_time[16], "\0");
246  strcpy(&end_time[16], "\0");
247 
248  strncpy(tmpvar, &start_time[0], 4);
249  strcpy(&tmpvar[4], "\0");
250  startyear = (short) atoi(tmpvar);
251 
252  strncpy(tmpvar, &start_time[4], 3);
253  strcpy(&tmpvar[3], "\0");
254  startday = (short) atoi(tmpvar);
255 
256  strncpy(tmpvar, &start_time[7], 2);
257  strcpy(&tmpvar[2], "\0");
258  starthour = (short) atoi(tmpvar);
259 
260  strncpy(tmpvar, &start_time[9], 2);
261  strcpy(&tmpvar[2], "\0");
262  startmin = (short) atoi(tmpvar);
263 
264  strncpy(tmpvar, &start_time[11], 2);
265  strcpy(&tmpvar[2], "\0");
266  startsec = (short) atoi(tmpvar);
267 
268  strncpy(tmpvar, &start_time[13], 3);
269  strcpy(&tmpvar[3], "\0");
270  startmsec = atoi(tmpvar);
271 
272  /* ******************************** */
273 
274  strncpy(tmpvar, &end_time[0], 4);
275  strcpy(&tmpvar[4], "\0");
276  endyear = (short) atoi(tmpvar);
277 
278  strncpy(tmpvar, &end_time[4], 3);
279  strcpy(&tmpvar[3], "\0");
280  endday = (short) atoi(tmpvar);
281 
282  strncpy(tmpvar, &end_time[7], 2);
283  strcpy(&tmpvar[2], "\0");
284  endhour = (short) atoi(tmpvar);
285 
286  strncpy(tmpvar, &end_time[9], 2);
287  strcpy(&tmpvar[2], "\0");
288  endmin = (short) atoi(tmpvar);
289 
290  strncpy(tmpvar, &end_time[11], 2);
291  strcpy(&tmpvar[2], "\0");
292  endsec = (short) atoi(tmpvar);
293 
294  strncpy(tmpvar, &end_time[13], 3);
295  strcpy(&tmpvar[3], "\0");
296  endmsec = atoi(tmpvar);
297 
298 #ifdef DEBUG
299  /* Print SeaWiFS Project required output to STDOUT */
300 
301  printf("startyear: %04d\n", startyear);
302  printf("startday: %03d\n", startday);
303  printf("starthour: %02d\n", starthour);
304 
305  printf("endyear: %04d\n", endyear);
306  printf("endday: %03d\n", endday);
307  printf("endhour: %02d\n", endhour);
308 
309  printf("%s/S%04d%03d%02d%03d%02d_%s.OZONE\n", directory,
310  startyear, startday, starthour, endday, endhour, "TOVS");
311 #endif
312 
313  sprintf(outfile, "%s/S%04d%03d%02d%03d%02d_%s.OZONE", directory,
314  startyear, startday, starthour, endday, endhour, "TOVS");
315  sprintf(outfilename, "S%04d%03d%02d%03d%02d_%s.OZONE",
316  startyear, startday, starthour, endday, endhour, "TOVS");
317 
318  startmsecday =
319  (starthour * 60 * 60 * 1000) +
320  (startmin * 60 * 1000) +
321  (startsec * 1000) +
322  startmsec;
323 
324  endmsecday =
325  (endhour * 60 * 60 * 1000) +
326  (endmin * 60 * 1000) +
327  (endsec * 1000) +
328  endmsec;
329  } else if (type == 2) { /* EPTOMS */
330 
331  hour = 00;
332  sprintf(outfile, "%s/N%04d%03d%02d_O3_TOMSOMI_24h.hdf",
333  directory, year, julval, hour);
334 
335  sprintf(outfilename, "N%04d%03d%02d_O3_TOMSOMI_24h.hdf",
336  year, julval, hour);
337 
338  /* ending times based on 1st file in EPTOMS case */
339  sprintf(end_time, "%04d%03d235959999", year, julval);
340 
341  endyear = year;
342  endday = julval;
343  endmsecday = 86399999;
344 
345  /* set the starting times as 0Z on day of primary file */
346  sprintf(start_time, "%04d%03d000000000", year, julval);
347  startyear = year;
348  startday = julval;
349  startmsecday = 0;
350 
351  /* Determine metadata "Node Crossing Time" value from hh:mm [AP]M form */
352 
353  strcpy(&acntime[8], "\0");
354 
355  strncpy(tmpvar, &acntime[0], 2);
356  strcpy(&tmpvar[2], "\0");
357  hour = (short) atoi(tmpvar);
358 
359  strncpy(tmpvar, &acntime[6], 2); /* AM or PM? */
360  if (!strcmp(tmpvar, "pm")) hour += 12;
361 
362  strncpy(tmpvar, &acntime[3], 2);
363  strcpy(&tmpvar[2], "\0");
364  min = (short) atoi(tmpvar);
365 
366  sprintf(node_time, "%04d%03d%02d%02d00000",
367  year, julval, hour, min);
368 
369  /* Read previous day */
370 
371  rdgrid_(prevfile, &type, (int16*) prevdatarr, &julval, &year,
372  start_time, end_time, acntime, &result, 255, 17, 17, 9);
373  if (result == 1) pexit("rdgrid_");
374 
375  if (type != 2) pexit("2nd EPTOMS file not of EPTOMS type. Exit.");
376 
377  } else if (type == 3) { /* ADTOMS */
378 
379  hour = 12; /* change to 12 from 0 */
380  sprintf(outfile, "%s/S%04d%03d%02d_%s.OZONE",
381  directory, year, julval, hour, "ADTOMS");
382 
383  sprintf(outfilename, "S%04d%03d%02d_%s.OZONE",
384  year, julval, hour, "ADTOMS");
385 
386  sprintf(end_time, "%04d%03d235959999", year, julval);
387 
388  endyear = year;
389  endday = julval;
390  endmsecday = 86399999;
391 
392  /* Determine metadata "Node Crossing Time" value from hh:mm [AP]M form */
393 
394  strcpy(&acntime[8], "\0");
395 
396  strncpy(tmpvar, &acntime[0], 2);
397  strcpy(&tmpvar[2], "\0");
398  hour = (short) atoi(tmpvar);
399 
400  strncpy(tmpvar, &acntime[6], 2); /* AM or PM? */
401  /*
402  * Note that we want the day-side crossing node. For ADEOS, it is
403  * descending during daylight, so take ascending time and correct by 12
404  * hours
405  */
406  if (!strcmp(tmpvar, "AM")) hour += 12;
407 
408  strncpy(tmpvar, &acntime[3], 2);
409  strcpy(&tmpvar[2], "\0");
410  min = (short) atoi(tmpvar);
411 
412  sprintf(node_time, "%04d%03d%02d%02d00000",
413  year, julval, hour, min);
414 
415  sprintf(start_time, "%04d%03d000000000", year, julval);
416  startyear = year;
417  startday = julval;
418  startmsecday = 0;
419  } else pexit("ERROR: Neither TOMS, TOVS, EPTOMS or ADTOMS specified");
420 
421  if (!access(outfile, F_OK))
422  pexit("....output file exists. Won't overwrite.");
423 
424  /*
425  * --- read annotation ASCII file for metadata placement in new HDF -----
426  */
427 
428  if ((numannarr = count_annot(annotfile)) == 0)
429  pexit("no annotations found");
430 
431  if ((xannot = (struct annotation *)
432  malloc(sizeof (struct annotation) * numannarr))
433  == NULL) pexit("malloc Annotation");
434 
435  xannot = fillenv_annot(annotfile);
436 
437  /*
438  * Extract values from descr array element for program use
439  */
440 
441  for (i = 0; i < numannarr; i++) {
442 
443  if (!strcmp(xannot[i].label, "Northernmost Latitude"))
444  sscanf(xannot[i].descr, "%f", &nmostlat);
445 
446  else if (!strcmp(xannot[i].label, "Southernmost Latitude"))
447  sscanf(xannot[i].descr, "%f", &smostlat);
448 
449  else if (!strcmp(xannot[i].label, "Westernmost Longitude"))
450  sscanf(xannot[i].descr, "%f", &wmostlon);
451 
452  else if (!strcmp(xannot[i].label, "Easternmost Longitude"))
453  sscanf(xannot[i].descr, "%f", &emostlon);
454 
455  else if (!strcmp(xannot[i].label, "Latitude Step"))
456  sscanf(xannot[i].descr, "%f", &latstep);
457 
458  else if (!strcmp(xannot[i].label, "Longitude Step"))
459  sscanf(xannot[i].descr, "%f", &lonstep);
460 
461  else if (!strcmp(xannot[i].label, "Number of Rows"))
462  sscanf(xannot[i].descr, "%d", &latsz);
463 
464  else if (!strcmp(xannot[i].label, "Number of Columns"))
465  sscanf(xannot[i].descr, "%d", &lonsz);
466 
467  } /* for i */
468 
469  /*
470  * Lat and Lon limits adjusted by 1/2 step size
471  */
472 
473  nmostlat = nmostlat - (latstep / 0.5); /* 89.500 = 90 - (1.00 / 0.5) */
474  smostlat = smostlat + (latstep / 0.5); /* -89.500 = -90 + (1.00 / 0.5) */
475  wmostlon = wmostlon + (lonstep / 0.5); /* -179.5 = 180 + (1.0 / 0.5) */
476  emostlon = emostlon - (lonstep / 0.5); /* 179.5 = 180 - (1.0 / 0.5) */
477 
478  /*
479  * Create HDF file
480  */
481 
482  if ((result = startHDF(outfile, &sdfid, &fid, DFACC_CREATE)) != 0)
483  pexit("Fatal error starting HDF file");
484 
485  /*
486  * Allocate space for 2D data arrays
487  */
488 
489  rank = 2;
490  shape[0] = latsz; /* lat */
491  shape[1] = lonsz; /* lon */
492  array_size = shape[0] * shape[1];
493 
494  if ((int16_SDSdataO3 =
495 #ifdef USE_MALLOC
496  (int16 *) malloc(sizeof (int16) * array_size)) == NULL)
497  pexit("malloc int16_SDSdataO3");
498 #else
499  (int16 *) calloc(sizeof (int16), array_size)) == NULL)
500  pexit("calloc int16_SDSdataO3");
501 #endif
502 
503  if ((int8_SDSdataQC =
504 #ifdef USE_MALLOC
505  (int8 *) malloc(sizeof (int8) * array_size)) == NULL)
506  pexit("malloc int8_SDSdataQC");
507 #else
508  (int8 *) calloc(sizeof (int8), array_size)) == NULL)
509  pexit("calloc int8_SDSdataQC");
510 #endif
511  for (i = 0; i < array_size; i++) int8_SDSdataQC[i] = 0; /* init */
512 
513  /*
514  * Create SDS array for writing
515  */
516 
517  l = 0;
518  for (j = 0; j < shape[0]; j++) { /* lats */
519  for (k = 0; k < shape[1]; k++) { /* lons */
520 
521  /* For EPTOMS data, overwrite missings (0's) with matching
522  position from previous day's data. Mark QC array (as EARLIERVAL) */
523 
524  if ((type == 2) && (datarr[j][k] == 0)) {
525  if (prevdatarr[j][k] != 0) {
526  datarr[j][k] = prevdatarr[j][k];
527  int8_SDSdataQC[l] = EARLIERVAL;
528  } else { /* even 2nd file is missing for this point */
529 
530  /* Scan lons in either longitudinal direction from current point */
531 
532  for (kk = 1; kk <= 50; kk++) {
533  if ((k - kk >= 0) && (datarr[j][k - kk] > 0)) {
534  datarr[j][k] = datarr[j][k - kk];
535  int8_SDSdataQC[l] = NEARESTVAL;
536  break;
537  } else if ((k + kk < shape[1]) && (datarr[j][k + kk] > 0)) {
538  datarr[j][k] = datarr[j][k + kk];
539  int8_SDSdataQC[l] = NEARESTVAL;
540  break;
541  }
542  }
543  }
544  modified_pts++;
545  }
546 
547  if (datarr[j][k] > 0) {
548  int16_SDSdataO3[l] = (int16) datarr[j][k];
549  } else int16_SDSdataO3[l] = 0;
550  l++; /* index counter */
551  } /* for k */
552  } /* for j */
553 
554  /*
555  * WDR for EP-TOMS, apply an average to the data
556  */
557  if (type == 2) world_avg((int16 *) datarr, shape[0], shape[1], 5, 5,
558  int16_SDSdataO3);
559 
560  /*
561  * ------- Assign metadata values to local descriptive variables ----
562  * ------- insert dates and other values to metadata array ---------
563  */
564 
565  for (i = 0; i < numannarr; i++) {
566 
567  if (!strcmp(xannot[i].label, "Product Name"))
568  sprintf(xannot[i].descr, "%s", outfilename);
569 
570  else if (!strcmp(xannot[i].label, "Processing Time")) {
571 
572  /* Determine processing time */
573  (void) time(&t);
574  localtm = localtime(&t);
575  pyear = localtm->tm_year;
576  if (pyear < 90) pyear = pyear + 2000; /* 2 digit to 4 */
577  else pyear = pyear + 1900;
578 
579  sprintf(xannot[i].descr, "%04d%03d%02d%02d%02d%03d",
580  pyear, localtm->tm_yday + 1, localtm->tm_hour, localtm->tm_min,
581  localtm->tm_sec, 0);
582  }
583  else if (!strcmp(xannot[i].label, "Input Files")) {
584  if (type == 2)
585  sprintf(xannot[i].descr, "%s,%s", infile, prevfile);
586  else
587  sprintf(xannot[i].descr, "%s", infile);
588  }
589  else if (!strcmp(xannot[i].label, "Processing Control"))
590  if (type == 2)
591  sprintf(xannot[i].descr, "%s %s %s %s %s %s",
592  argv[0], annotfile, infile, directory, itype, prevfile);
593  else
594  sprintf(xannot[i].descr, "%s %s %s %s %s",
595  argv[0], annotfile, infile, directory, itype);
596 
597  else if (!strcmp(xannot[i].label, "Start Time"))
598  sprintf(xannot[i].descr, "%s", start_time);
599 
600  else if (!strcmp(xannot[i].label, "End Time"))
601  sprintf(xannot[i].descr, "%s", end_time);
602 
603  else if (!strcmp(xannot[i].label, "Start Year"))
604  sprintf(xannot[i].descr, "%04d", startyear);
605 
606  else if (!strcmp(xannot[i].label, "Start Day"))
607  sprintf(xannot[i].descr, "%03d", startday);
608 
609  else if (!strcmp(xannot[i].label, "Start Millisec"))
610  sprintf(xannot[i].descr, "%08d", startmsecday);
611 
612  else if (!strcmp(xannot[i].label, "End Year"))
613  sprintf(xannot[i].descr, "%04d", endyear);
614 
615  else if (!strcmp(xannot[i].label, "End Day"))
616  sprintf(xannot[i].descr, "%03d", endday);
617 
618  else if (!strcmp(xannot[i].label, "End Millisec"))
619  sprintf(xannot[i].descr, "%08d", endmsecday);
620 
621  else if (!strcmp(xannot[i].label, "Node Crossing Time"))
622  sprintf(xannot[i].descr, "%s", node_time);
623 
624  else if (!strcmp(xannot[i].label, "Points Modified"))
625  sprintf(xannot[i].descr, "%08d", modified_pts);
626 
627  } /* for i */
628 
629 
630  /*
631  * Write attribute array to HDF file
632  */
633 
634  if ((result = wrtattr(sdfid, xannot, numannarr)) != 0) pexit("wrtattr");
635  free(xannot);
636 
637 
638  /*
639  * --- Write OZONE SDS, units attribute, and add to grid Vgroup ----------
640  */
641 
642  datalabel = "ozone";
643  strcpy(dataunit, "Total ozone");
644  strcpy(dataattr, "Dobson units");
645  datafmt = "int16";
646  datatype = DFNT_INT16;
647 
648  gridid = setupGrid(fid, VGROUPNAME);
649 
650  if ((SDSinFile(datalabel, dataunit, dataattr, datafmt,
651  datatype, sdfid, rank, shape, int16_SDSdataO3, gridid)) != 0)
652  pexit("SDSinFile ozone wrtsds");
653 
654  free(int16_SDSdataO3);
655 
656  /*
657  * --- Write OZONE QC flag SDS, units attribute, and add to grid Vgroup ---
658  */
659 
660  datalabel = "ozone_QC";
661  strcpy(dataunit, "Total ozone Q/C flag");
662  strcpy(dataattr, "");
663  datafmt = "int8";
664  datatype = DFNT_INT8;
665 
666  if ((SDSinFile(datalabel, dataunit, dataattr, datafmt,
667  datatype, sdfid, rank, shape, int8_SDSdataQC, gridid)) != 0)
668  pexit("SDSinFile ozone QC wrtsds");
669 
670  free(int8_SDSdataQC);
671 
672  deattachHDFgrid(gridid); /* deattach HDF grid */
673 
674  /*
675  * close HDF structures
676  */
677 
678  result = 0;
679  if ((result = closeHDFstructs(sdfid, fid)) != 0) pexit("closeHDFstructs");
680 
681 
682  /*
683  * Print info to STDOUT for SeaWiFS Project
684  */
685 
686  printf("%s+%s+%s\n", outfile, start_time, end_time);
687 
688  exit(0);
689 
690 } /* main */
691 
692 /*****************************************************************
693  * File: check_usage
694  *
695  * Purpose: check command line arguments
696  *
697  * Description: check command line arguements and report proper usage
698  * on argument count error or no argumnts.
699  *
700  * Input parms:
701  * char *annotfile - input file of DAAC compliant annots ("fillenv.tomsnrt")
702  * char *infile - input ozone file to process ("nimoz100.y93")
703  * char *directory - output file directory (".")
704  *
705  * Output parms:none
706  *
707  * Returns: success (0) or failure(-1)
708  *
709  * Subs called: none
710  *
711  * History: none
712  *
713  * Note: This routine is custom for each program that uses it since
714  * the arguments are different of course.
715  *
716  * Author: Brian D. Schieber, GSC, 9/93
717  *
718  * Modification history:
719  *****************************************************************/
720 
721 
722 int8 check_usage(int argc, char *argv[]) {
723  if (argc < 5) {
724  printf("\n\nUsage:\n");
725  printf("\t%s <metafile> <file> <directory> <itype> [<prevfile>]\n", argv[0]);
726  printf("\nWhere:\n");
727  printf("\tmetafile: HDF metadata file (in ASCII)\n");
728  printf("\tfile: file to process\n");
729  printf("\tdirectory: output directory (no ending slash)\n");
730  printf("\titype: input data type 'TOMS', 'TOVS', 'EPTOMS' or 'ADTOMS'\n");
731  printf("\tprevfile: [optional] previous day if type 'EPTOMS'\n");
732  printf("\n\n");
733  printf("\tExample:\n");
734  printf("\t\t o3nrt $SDSDEMO/fillenv.eptomsnrt $SDSDEMO/ga960903.ept\n");
735  printf("\t\t ./ 'EPTOMS' $SDSDEMO/ga960902.ept\n\n");
736  return -1;
737  }
738  return 0;
739 }
int32_t setupGrid(int32_t fid, char *grpname)
Definition: ANCroutines.c:51
integer, parameter int16
Definition: cubeio.f90:3
data_t t[NROOTS+1]
Definition: decode_rs.h:77
int j
Definition: decode_rs.h:73
int32_t SDSinFile(char *sdsname, char *longname, char *units, char *datafmt, int32_t datatype, int32_t sdfid, int32_t rank, int32_t *shape, void *data, int32_t gridid)
These are used to scale the SD before writing it to the HDF4 file The default is and which means the product is not scaled at all Since the product is usually stored as a float inside of this is a way to write the float out as a integer l2prod min
int8 check_usage(int argc, char *argv[])
Definition: o3nrt_omi.c:721
#define NULL
Definition: decode_rs.h:63
float tm[MODELMAX]
void rdgrid_()
char descr[MAXDESCLEN]
Definition: ancil.h:72
int wrtattr(int32_t dfile, struct annotation *annot, int numannarr)
Definition: ANCroutines.c:631
#define EARLIERVAL
Definition: o3nrt_omi.c:106
int main(int argc, char *argv[])
Definition: o3nrt_omi.c:109
int count_annot(char *filename)
Definition: countann.c:11
int32_t wrtsds(int32_t sdfid, int rank, int32_t *shape, int32_t datatype, char *datalabel, void *data)
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_INT16
struct annotation * fillenv_annot(char *filename)
Definition: fillenv.c:15
int deattachHDFgrid(int32_t gridid)
Definition: ANCroutines.c:267
#define NEARESTVAL
Definition: o3nrt_omi.c:107
char * upcase(char *instr)
Definition: upcase.c:10
int closeHDFstructs(int32_t sdfid, int32_t fid)
Definition: ANCroutines.c:281
void pexit(char *string)
Definition: pexit.c:10
this program makes no use of any feature of the SDP Toolkit that could generate such a then geolocation is calculated at that and then aggregated up to Resolved feature request Bug by adding three new int8 SDSs for each high resolution offsets between the high resolution geolocation and a bi linear interpolation extrapolation of the positions This can be used to reconstruct the high resolution geolocation Resolved Bug by delaying cumulation of gflags until after validation of derived products Resolved Bug by setting Latitude and Longitude to the correct fill resolving to support Near Real Time because they may be unnecessary if use of entrained ephemeris and attitude data is turned resolving bug report Corrected to filter out Aqua attitude records with missing status helping resolve bug MOD_PR03 will still correctly write scan and pixel data that does not depend upon the start time
Definition: HISTORY.txt:248
Extra metadata that will be written to the HDF4 file l2prod rank
PARAM_TYPE_NONE Default value No parameter is buried in the product name name_prefix is case insensitive string compared to the product name PARAM_TYPE_VIS_WAVE The visible wavelength bands from the sensor are buried in the product name The product name is compared by appending and name_suffix ie aph_412_giop where prod_ix will be set to PARAM_TYPE_IR_WAVE same search method as PARAM_TYPE_VIS_WAVE except only wavelength above are looped through but prod_ix is still based ie aph_2_giop for the second and prod_ix set to PARAM_TYPE_INT name_prefix is compared with the beginning of the product name If name_suffix is not empty the it must match the end of the product name The characters right after the prefix are read as an integer and prod_ix is set to that number strncpy(l2prod->name_prefix, "myprod", UNITLEN)
#define VGROUPNAME
Definition: o3nrt_omi.c:103
void gregor_(int *julday, int *year, int *month, int *day)
int setSDSref(int32_t sdsid, int32_t gridid)
Definition: ANCroutines.c:245
#define MAXNAMELNG
Definition: ancil.h:43
int i
Definition: decode_rs.h:71
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
int k
Definition: decode_rs.h:73
string outfilename
Definition: color_dtdb.py:220
void world_avg(int16 *inarr, int32 nlin, int32 npix, int avg_pix, int avg_lin, int16 *outarr)
Definition: world_avg.c:4
int startHDF(char *outfile, int32_t *sdfid, int32_t *fid, int32_t mode)
Definition: ANCroutines.c:27