OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
ancnrt.c
Go to the documentation of this file.
1 /*****************************************************************
2  * File: ancnrt.c
3  *
4  * Purpose: create HDF ancillary real time datafile from
5  * NCEP (formerly NMC) (unpacked GRIB format) W, P, PW, H input
6  * or the NCEP above PLUS O3
7  * or a TOVS ozone unpacked GRIB file from NMC.
8  *
9  * Description: this program will create a HDF with the components:
10  *
11  * Met data (along with a '_QC' dataset):
12  * 2-D data parameter SDS (z_wind)
13  * 2-D data parameter SDS (m_wind)
14  * 2-D data parameter SDS (press)
15  * 2-D data parameter SDS (rel_hum)
16  * 2-D data parameter SDS (p_water)
17  *
18  * Ozone data (along with a '_QC' dataset):
19  * 2-D data parameter SDS (ozone)
20  * Note that the NCEP O3 can also be put into a met file, if supplied
21  *
22  * Input parms:
23  * char *annotfile - input of DAAC compliant annotations ("fillenv.met")
24  * a set of binary file names, 3 forms:
25  * ANC_MET - 5 files (products)
26  * wind, 10 m agl (z_wind.dat, m_wind.dat), 1000 mb pressure (press.dat),
27  * Column water vapor (p_water.dat), syc relative humidity (rel_hum.dat)
28  * ANC_OZONE - 1 files (products)
29  * Column ozone (ozone.dat)
30  * ANC_METOZ - 6 files (products)
31  * all products in ANC_MET and ANC_OZONE, from NCEP
32  * char *outdir - output directory to write file
33  *
34  * Output file names
35  * Example name: "N199312300_MET_NCEP_6h.hdf"
36  * "S199312300_TOVS.OZONE" for ozone file
37  * "N201412303_MET_NCEP_f12_360x181.hdf"
38  * (proposed for the forecast with different grid size)
39  *
40  * Author: Brian D. Schieber, GSC, 4/93
41  *
42  * Modification history:
43  * BDS, 4/19/93 - HDF missing flag removed after discussions
44  * with Jim F. and M.Darzi.
45  * - NCEP data in Pascals, divided by 100 => millibars.
46  * BDS, 4/30/93 - Modified GRIB read WPHLONSZ to remove "world wrapped"
47  * extra Lon. Will skip last longitude in HDF write.
48  * BDS, 10/4/93 - Modified for new HDF design and to produce and
49  * output file which holds all three met fields (WPH).
50  * BDS, 11/8/93 - Modified to create z/m wind SDS rather than windspeed.
51  * BDS, 11/28/93- Modified MAX_EAST to 177.5 (from 180.0).
52  * BDS, 12/6/93 - Assuming no missing values, 0.0's passed through.
53  * BDS, 5/19/95 - Support new SeaWiFS v 2.7 product specs.
54  * BDS, 8/21/96 - Renamed 'perror' to 'pexit' to avoid conflict with
55  * HDF4.0.
56  * BDS, 9/18/96 - Changed annot structure. Modify to support new 1x1
57  * GDAS1 files.
58  * BDS, 9/19/96 - Precipitable water has units kg/m^2
59  * W. Robinson, GSC, 4 Feb 97 put rh back in
60  * W. Robinson, GSC, 18 Jun 98 rename to ancnrt to include added
61  * role of processing the TOVS ozone data
62  * W. Robinson, GSC, 18 Dec 98 for the ozone output, write the
63  * start and end times to be compatible with o3nrt
64  * W. Robinson, SAIC, 23 Jan 2008 to add ability to read the binary
65  * files derived from the GRIB 2 format files (just a few
66  * differences, see readgrib2 in readgrib.c)
67  * W. Robinson, SAIC, 18 Sep 2009 modify readgrib2 call args- rgmode
68  * W. Robinson, SAIC, 16 Feb 2010 modify readgrib2 call args npix, nlin
69  * W. Robinson, SAIC, 24 Jun 2014 updates for new met file name
70  * W. Robinson, SAIC, 18 Mar 2015 more grid size flexability, and
71  * use of forecast data
72  *****************************************************************/
73 
74 #include <mfhdf.h>
75 #include "ancil.h"
76 #include <time.h>
77 #include <limits.h>
78 #include <unistd.h>
79 #include "ancnrt_proto.h"
80 #include <timeutils.h>
81 
82 #define VGROUPNAME "Geophysical Data"
83 /* default grid sizes for older datasets */
84 #define WPH_DFT_LATSZ 181 /* latitude of GRIB files */
85 #define WPH_DFT_LONSZ 360 /* long of MODIFIED GRIB files */
86 #define OZLATSZ 180 /* fixed TOVS output # lines to cvt to */
87 #define OZLONSZ 288 /* fixed TOVS output made to this size */
88 #define ANC_MET 0 /* for ancillary data type (anctyp) say this is met data */
89 #define ANC_OZONE 1 /* say this is ozone data */
90 #define ANC_METOZ 2 /* combined met and ozone from NCEP */
91 #define ANC_METOZ2 3 /* for test 2 extra parms of RH at 1000, RH at 10 m */
92 #define GRIB_MODE_1 1 /* the GRIB modes, GRIB 1 old, GRIB 2 post jan 08 */
93 #define GRIB_MODE_2 2
94 
95 int main(int argc, char *argv[]) {
96  int i, j, k, l, h_fcst, anctyp, iprm, rank;
97  int result = 0, numannarr = 0;
98  int rgmode = 1, pyear = 0;
99  int year = 0, month, day, doy = 0, hour = 0, msec = 0;
100  int32 shape[2];
101  int npix = WPH_DFT_LONSZ, nlin = WPH_DFT_LATSZ, npix_n, nlin_n, n_parm;
102  double usec, vsec = 0.;
103  float *float_out;
104  int8 *qc_out;
105 
106  float32 *datarr; /* dynamically allocated storage for all met fields */
107  char in_fnames[8][MAXNAMELNG];
108 
109  char message[MAXNAMELNG];
110  char *longname, *sdsname;
111  char *units;
112  char *datafmt, outfile[MAXNAMELNG];
113  char outfilename[MAXNAMELNG], outdir[MAXNAMELNG];
114  char annotfile[MAXNAMELNG], source_name[100];
115  int n_opt_arg;
116  float latstep, lonstep; /* lat/lon incr. */
117  int latsz, lonsz; /* lat/lon size */
118  float nmostlat, smostlat, wmostlon, emostlon; /* lat/lon corners */
119  time_t t; /* processing time */
120  struct tm *localtm; /* processing time */
121  struct annotation *xannot;
122  int grib_mode;
123  char grib2_t_str[300];
124  int ipoff, npix_out, nlin_out;
125  /*
126  * info for SDSes of data and QC
127  */
128  /*
129  char *metoz_nm[6] = { "z_wind", "m_wind", "press", "p_water", "rel_hum",
130  "ozone" };
131  char *metoz_ln_nm[6] = { "Zonal wind at 10 m", "Meridional wind at 10 m",
132  "Atmospheric pressure at mean sea level", "Precipitable water",
133  "Relative humidity at 1000 mb", "Total ozone" };
134  char *metoz_units[6] = { "m sec^-1", "m sec^-1", "millibars", "kg m^-2",
135  "percent", "Dobson units" };
136  char *qc_nm[6] = { "z_wind_QC", "m_wind_QC", "press_QC", "p_water_QC",
137  "rel_hum_QC", "ozone_QC" };
138  char *qc_ln_nm[6] = { "Zonal wind at 10 m Q/C flag",
139  "Meridional wind at 10 m Q/C flag",
140  "Atmospheric pressure at mean sea level Q/C flag",
141  "Precipitable water Q/C flag",
142  "Relative humidity at 1000 mb Q/C flag",
143  "Total ozone Q/C flag" };
144  float fac_lst[6] = { 1., 1., 0.01, 1., 1., 1. };
145  */
146  char *metoz_nm[8] = {"z_wind", "m_wind", "press", "p_water", "rel_hum",
147  "ozone", "rel_hum_2m_agl", "rel_hum_d30mb"};
148  char *metoz_ln_nm[8] = {"Zonal wind at 10 m", "Meridional wind at 10 m",
149  "Atmospheric pressure at mean sea level", "Precipitable water",
150  "Relative humidity at 1000 mb", "Total ozone",
151  "Relative humidity at 2 m AGL", "Relative humidity at 0-30 mb AGL"};
152  char *metoz_units[8] = {"m sec^-1", "m sec^-1", "millibars", "kg m^-2",
153  "percent", "Dobson units", "percent", "percent"};
154  char *qc_nm[8] = {"z_wind_QC", "m_wind_QC", "press_QC", "p_water_QC",
155  "rel_hum_QC", "ozone_QC", "rel_hum_2m_agl_QC", "rel_hum_d30mb_QC"};
156  char *qc_ln_nm[8] = {"Zonal wind at 10 m Q/C flag",
157  "Meridional wind at 10 m Q/C flag",
158  "Atmospheric pressure at mean sea level Q/C flag",
159  "Precipitable water Q/C flag",
160  "Relative humidity at 1000 mb Q/C flag",
161  "Total ozone Q/C flag",
162  "Relative humidity at 2 m AGL Q/C flag",
163  "Relative humidity at 0-30 mb AGL Q/C flag"};
164  float fac_lst[8] = {1., 1., 0.01, 1., 1., 1., 1., 1.};
165  /*
166  * HDF datafile variables
167  */
168  int32 sdfid, fid, gridid;
169  int32 datatype;
170  /*
171  * data type array pointers
172  */
173  int16 *float_SDS_oz, *oz_newsiz;
174  /*
175  * external functions used
176  */
177  int readgrib(), julian_(), wrtattr(), startHDF();
178  int addAttr(), setSDSref(), grib2_t();
179  int32 wrtsds();
180  void deattachHDFGrid(), pexit();
181  int8 check_usage();
182  struct annotation * fillenv_annot();
183 
184  /*
185  * ------- check command line arguments and set args ------------------
186  */
187 
188  if ((check_usage(argc, argv, &anctyp, &n_opt_arg, source_name,
189  &grib_mode, grib2_t_str)) != 0)
190  exit(-1);
191  strcpy(annotfile, argv[ n_opt_arg ]);
192  if (anctyp == ANC_METOZ) {
193  strcpy(in_fnames[0], argv[ 1 + n_opt_arg ]);
194  strcpy(in_fnames[1], argv[ 2 + n_opt_arg ]);
195  strcpy(in_fnames[2], argv[ 3 + n_opt_arg ]);
196  strcpy(in_fnames[3], argv[ 4 + n_opt_arg ]);
197  strcpy(in_fnames[4], argv[ 5 + n_opt_arg ]);
198  strcpy(in_fnames[5], argv[ 6 + n_opt_arg ]);
199  strcpy(outdir, argv[ 7 + n_opt_arg ]);
200  } else if (anctyp == ANC_METOZ2) {
201  strcpy(in_fnames[0], argv[ 1 + n_opt_arg ]);
202  strcpy(in_fnames[1], argv[ 2 + n_opt_arg ]);
203  strcpy(in_fnames[2], argv[ 3 + n_opt_arg ]);
204  strcpy(in_fnames[3], argv[ 4 + n_opt_arg ]);
205  strcpy(in_fnames[4], argv[ 5 + n_opt_arg ]);
206  strcpy(in_fnames[5], argv[ 6 + n_opt_arg ]);
207  strcpy(in_fnames[6], argv[ 7 + n_opt_arg ]);
208  strcpy(in_fnames[7], argv[ 8 + n_opt_arg ]);
209  strcpy(outdir, argv[ 9 + n_opt_arg ]);
210  } else if (anctyp == ANC_MET) {
211  strcpy(in_fnames[0], argv[ 1 + n_opt_arg ]);
212  strcpy(in_fnames[1], argv[ 2 + n_opt_arg ]);
213  strcpy(in_fnames[2], argv[ 3 + n_opt_arg ]);
214  strcpy(in_fnames[3], argv[ 4 + n_opt_arg ]);
215  strcpy(in_fnames[4], argv[ 5 + n_opt_arg ]);
216  strcpy(outdir, argv[ 6 + n_opt_arg ]);
217  } else {
218  strcpy(in_fnames[0], argv[ 1 + n_opt_arg ]);
219  strcpy(outdir, argv[ 2 + n_opt_arg ]);
220  }
221  /*
222  * get grib2-specific information
223  */
224  if (grib_mode == GRIB_MODE_2) {
225  if (grib2_t(grib2_t_str, &year, &doy, &hour, &npix_n, &nlin_n, &h_fcst)
226  != 0) exit(-1);
227  if ((npix_n > 0) && (nlin_n > 0)) {
228  npix = npix_n;
229  nlin = nlin_n;
230  }
231  }
232  /*
233  * the ozone (TOAST) is at a fixed 1.25x1 degree grid so -
234  * and also reserve storage for all the data in the dararr array
235  */
236  n_parm = 1;
237  if (anctyp == ANC_MET) n_parm = 5;
238  if (anctyp == ANC_METOZ) n_parm = 6;
239  if (anctyp == ANC_METOZ2) n_parm = 8;
240 
241  datarr = (float *) malloc(n_parm * npix * nlin * sizeof ( float));
242  /*
243  * ------- Read each binary file, extract data array and time ----------
244  */
245  for (iprm = 0; iprm < n_parm; iprm++) {
246  ipoff = iprm * npix * nlin;
247  if (grib_mode == GRIB_MODE_2)
248  result = readgrib2(in_fnames[iprm], npix, nlin, rgmode,
249  (float *) (datarr + ipoff));
250  else {
251  result = readgrib(in_fnames[iprm], npix, nlin, (datarr + ipoff),
252  &year, &month, &day, &hour);
253  /* need to expand year out for the old grib year */
254  if (year < 70) year = year + 2000; /* 2 digit 19xx or 20xx yrs to 4 */
255  else year = year + 1900;
256  usec = ymds2unix(year, month, day, vsec);
257  unix2yds(usec, (int16_t *) & year, (int16_t *) & doy, &vsec);
258  }
259  if (result == 1) {
260  strcpy(message, "readgrib file: ");
261  strcat(message, in_fnames[iprm]);
262  pexit(message);
263  }
264  }
265 
266  /*
267  *** This used to dump the GRIB array to stdout for a data check ***
268  float dlat = 2.5;
269  float dlon = 2.5;
270  for (i = 0; i < WPH_DFT_LATSZ; i++) {
271  for (j = 0; j < WPH_DFT_LONSZ; j++) {
272  printf("\nLat: %f", 90.0 - (i * dlat));
273  printf(" Lon: %f", (-180.0 + (j * dlon)));
274  printf(" %f ", datarr1[i][j]/100.0);
275  }
276  }
277  */
278 
279  /*
280  * Create outfile name
281  */
282  /* if( anctyp == ANC_METOZ ) */
283  if ((anctyp == ANC_METOZ) || (anctyp == ANC_METOZ2)) {
284  sprintf(outfilename, "N%04d%03d%02d_MET_%s_%4.4dx%4.4d_f%3.3d.hdf",
285  year, doy, hour, source_name, npix, nlin, h_fcst);
286  sprintf(outfile, "%s/%s",
287  outdir, outfilename);
288  /* For SDPS' benefit! */
289  printf("%s\n", outfile);
290  } else if (anctyp == ANC_MET) {
291  sprintf(outfilename, "N%04d%03d%02d_MET_%s_6h.hdf",
292  year, doy, hour, source_name);
293  sprintf(outfile, "%s/%s",
294  outdir, outfilename);
295  /* For SDPS' benefit! */
296  printf("%s\n", outfile);
297  } else {
298  sprintf(outfilename, "S%04d%03d00%03d23_%s.OZONE",
299  year, doy, doy, source_name);
300  sprintf(outfile, "%s/%s",
301  outdir, outfilename);
302  /* For SDPS' benefit! */
303  printf("%s+%04d%03d000000000+%04d%03d235959999\n", outfile, year, doy,
304  year, doy);
305  }
306 
307 
308  /*
309  * Write HDF annotations
310  */
311 
312  /**** check for existing HDF ***/
313  /* WDR disable unless some complaints about behavior change
314  if (!access(outfile, F_OK)) pexit ("....output file exists");
315  */
316 
317  if ((numannarr = count_annot(annotfile)) == 0)
318  pexit("no annotations found");
319 
320  if ((xannot = (struct annotation *)
321  malloc(sizeof (struct annotation) * numannarr))
322  == NULL) pexit("malloc Annotation");
323 
324  xannot = fillenv_annot(annotfile);
325 
326  /*
327  * Determine processing time
328  */
329 
330  (void) time(&t);
331  localtm = localtime(&t);
332  pyear = localtm->tm_year;
333  if (pyear < 90) pyear = pyear + 2000; /* 2 digit 19xx or 20xx yrs to 4 */
334  else pyear = pyear + 1900;
335 
336  if (hour > 0) msec = hour * 60 * 60 * 1000;
337  else msec = 0;
338 
339  /*
340  * ------- assign metadata values to local descriptive variables ----
341  * ------- insert dates and other values to metadata array ---------
342  * ------- follow order of fillenv data file -----------------------
343  */
344 
345  for (i = 0; i < numannarr; i++) {
346 
347  /* Insert values to descr array element */
348 
349  if (!strcmp(xannot[i].label, "Product Name"))
350  sprintf(xannot[i].descr, "%s", outfilename);
351 
352  else if (!strcmp(xannot[i].label, "Title")) {
353  if ((anctyp == ANC_METOZ) || (anctyp == ANC_METOZ2))
354  strcpy(xannot[i].descr, "NCEP Forecast Ancillary Data");
355  } else if (!strcmp(xannot[i].label, "Data Type")) {
356  if ((anctyp == ANC_METOZ) || (anctyp == ANC_METOZ2))
357  strcpy(xannot[i].descr, "Meteorological and Ozone");
358  }
359  else if (!strcmp(xannot[i].label, "Processing Time"))
360  sprintf(xannot[i].descr, "%04d%03d%02d%02d%02d%03d",
361  pyear, (localtm->tm_yday + 1), localtm->tm_hour, localtm->tm_min,
362  localtm->tm_sec, 0);
363 
364  else if (!strcmp(xannot[i].label, "Input Files"))
365  if (anctyp == ANC_MET)
366  sprintf(xannot[i].descr, "%s %s %s %s %s",
367  in_fnames[0], in_fnames[1], in_fnames[2], in_fnames[3],
368  in_fnames[4]);
369  else if (anctyp == ANC_METOZ)
370  sprintf(xannot[i].descr, "%s %s %s %s %s %s",
371  in_fnames[0], in_fnames[1], in_fnames[2], in_fnames[3],
372  in_fnames[4], in_fnames[5]);
373  else if (anctyp == ANC_METOZ2)
374  sprintf(xannot[i].descr, "%s %s %s %s %s %s %s %s",
375  in_fnames[0], in_fnames[1], in_fnames[2], in_fnames[3],
376  in_fnames[4], in_fnames[5], in_fnames[6], in_fnames[7]);
377  else
378  sprintf(xannot[i].descr, "%s", in_fnames[0]);
379 
380  else if (!strcmp(xannot[i].label, "Processing Control"))
381  if (anctyp == ANC_MET)
382  sprintf(xannot[i].descr, "%s %s %s %s %s %s %s %s",
383  argv[0], annotfile, in_fnames[0], in_fnames[1], in_fnames[2],
384  in_fnames[3], in_fnames[4], outdir);
385  else if (anctyp == ANC_METOZ)
386  sprintf(xannot[i].descr, "%s %s %s %s %s %s %s %s %s",
387  argv[0], annotfile, in_fnames[0], in_fnames[1], in_fnames[2],
388  in_fnames[3], in_fnames[4], in_fnames[5], outdir);
389  else if (anctyp == ANC_METOZ)
390  sprintf(xannot[i].descr, "%s %s %s %s %s %s %s %s %s %s %s",
391  argv[0], annotfile, in_fnames[0], in_fnames[1], in_fnames[2],
392  in_fnames[3], in_fnames[4], in_fnames[5], in_fnames[6],
393  in_fnames[7], outdir);
394  else
395  sprintf(xannot[i].descr, "%s %s %s %s",
396  argv[0], annotfile, in_fnames[0], outdir);
397 
398  else if (!strcmp(xannot[i].label, "Start Time"))
399  if (anctyp != ANC_OZONE)
400  sprintf(xannot[i].descr, "%04d%03d%02d0000000", year, doy, hour);
401  else
402  sprintf(xannot[i].descr, "%04d%03d000000000", year, doy);
403 
404  else if (!strcmp(xannot[i].label, "End Time"))
405  if (anctyp != ANC_OZONE)
406  sprintf(xannot[i].descr, "%04d%03d%02d0000000", year, doy, hour);
407  else
408  sprintf(xannot[i].descr, "%04d%03d230000000", year, doy);
409 
410  else if (!strcmp(xannot[i].label, "Start Year"))
411  sprintf(xannot[i].descr, "%04d", year);
412 
413  else if (!strcmp(xannot[i].label, "Start Day"))
414  sprintf(xannot[i].descr, "%03d", doy);
415 
416  else if (!strcmp(xannot[i].label, "Start Millisec"))
417  if (anctyp != ANC_OZONE)
418  sprintf(xannot[i].descr, "%08d", msec);
419  else
420  sprintf(xannot[i].descr, "00000000");
421 
422  else if (!strcmp(xannot[i].label, "End Year"))
423  sprintf(xannot[i].descr, "%04d", year);
424 
425  else if (!strcmp(xannot[i].label, "End Day"))
426  sprintf(xannot[i].descr, "%03d", doy);
427 
428  else if (!strcmp(xannot[i].label, "End Millisec"))
429  if (anctyp != ANC_OZONE)
430  sprintf(xannot[i].descr, "%08d", msec);
431  else
432  sprintf(xannot[i].descr, "82800000");
433 
434  /* WDR for ozone, modify the data type and data source*/
435  /* This should come from the metadata file
436  else if ( ( anctyp == ANC_OZONE ) &&
437  ( !strcmp(xannot[i].label, "Data Type")) )
438  sprintf(xannot[i].descr, "Ozone" );
439 
440  else if ( ( anctyp == ANC_OZONE ) &&
441  ( !strcmp(xannot[i].label, "Data Source")) )
442  sprintf(xannot[i].descr, "TOVS" );
443 
444  else if ( ( anctyp == ANC_OZONE ) &&
445  ( !strcmp(xannot[i].label, "Data Source Desc")) )
446  sprintf(xannot[i].descr, "NOAA TIROS Operational Vertical Sounder" );
447  */
448 
449  else if ((anctyp == ANC_OZONE) &&
450  (!strcmp(xannot[i].label, "Temporal Resolution")))
451  sprintf(xannot[i].descr, "12");
452  else if ((anctyp == ANC_METOZ) &&
453  (!strcmp(xannot[i].label, "Temporal Resolution")))
454  sprintf(xannot[i].descr, "0");
455 
456  /* Extract values from descr array element for program use */
457 
458  else if (!strcmp(xannot[i].label, "Northernmost Latitude"))
459  sscanf(xannot[i].descr, "%f", &nmostlat);
460 
461  else if (!strcmp(xannot[i].label, "Southernmost Latitude"))
462  sscanf(xannot[i].descr, "%f", &smostlat);
463 
464  else if (!strcmp(xannot[i].label, "Westernmost Longitude"))
465  sscanf(xannot[i].descr, "%f", &wmostlon);
466 
467  else if (!strcmp(xannot[i].label, "Easternmost Longitude"))
468  sscanf(xannot[i].descr, "%f", &emostlon);
469 
470  else if ((!strcmp(xannot[i].label, "Latitude Step")) &&
471  ((anctyp == ANC_METOZ) || (anctyp == ANC_METOZ2))) {
472  latstep = 180. / (float) (nlin - 1);
473  sprintf(xannot[i].descr, "%f", latstep);
474  } /*
475  * WDR now a variable longitude step, # rows and columns
476  */
477  else if (!strcmp(xannot[i].label, "Longitude Step")) {
478  if (anctyp == ANC_OZONE)
479  lonstep = 1.25;
480  else if ((anctyp == ANC_METOZ) || (anctyp == ANC_METOZ2))
481  lonstep = 360. / (float) npix;
482  else
483  lonstep = 1.;
484  sprintf(xannot[i].descr, "%f", lonstep);
485  }
486  else if (!strcmp(xannot[i].label, "Number of Rows")) {
487  if (anctyp == ANC_OZONE)
488  latsz = 180;
489  else if (anctyp == ANC_METOZ)
490  latsz = nlin;
491  else if (anctyp == ANC_METOZ2)
492  latsz = nlin;
493  else
494  latsz = 181;
495  sprintf(xannot[i].descr, "%d", latsz);
496  }
497  else if (!strcmp(xannot[i].label, "Number of Columns")) {
498  if (anctyp == ANC_OZONE)
499  lonsz = 288;
500  else if (anctyp == ANC_METOZ)
501  lonsz = npix;
502  else if (anctyp == ANC_METOZ2)
503  lonsz = npix;
504  else
505  lonsz = 360;
506  sprintf(xannot[i].descr, "%d", lonsz);
507  } /*
508  * SW point is different for the ozone
509  */
510  else if (!strcmp(xannot[i].label, "SW Point Latitude") &&
511  anctyp == ANC_OZONE)
512  sprintf(xannot[i].descr, "%f", -89.5);
513 
514  else if (!strcmp(xannot[i].label, "SW Point Longitude") &&
515  anctyp == ANC_OZONE)
516  sprintf(xannot[i].descr, "%f", -179.375);
517 
518  }
519 
520  /*
521  * Create HDF file
522  */
523 
524  if ((result = startHDF(outfile, &sdfid, &fid, DFACC_CREATE)) != 0)
525  pexit("Fatal error starting HDF file");
526 
527  /*
528  * Write attribute array to HDF file
529  */
530 
531  if ((result = wrtattr(sdfid, xannot, numannarr)) != 0) pexit("wrtattr");
532  free(xannot);
533 
534  /*
535  * -------- Allocate space for 2D data arrays -----------------------
536  */
537 
538  rank = 2;
539 
540  /*
541  * ----------------- Create Vgroup ----------------------------
542  */
543  gridid = setupGrid(fid, VGROUPNAME);
544  npix_out = (anctyp == ANC_OZONE) ? OZLONSZ : npix;
545  nlin_out = (anctyp == ANC_OZONE) ? OZLATSZ : nlin;
546 
547  if ((oz_newsiz =
548  (int16 *) malloc(sizeof (int16) * npix_out * nlin_out)) == NULL)
549  pexit("malloc oz_newsiz");
550 
551  if ((float_out = (float *) malloc(npix_out * nlin_out * sizeof (float)))
552  == NULL) pexit("malloc float_out");
553  if ((qc_out = (int8 *) calloc(npix * nlin, sizeof (int8)))
554  == NULL) pexit("malloc qc_out");
555  shape[0] = nlin_out;
556  shape[1] = npix_out;
557  if (anctyp != ANC_OZONE) {
558  for (iprm = 0; iprm < n_parm; iprm++) {
559  /*
560  * Shift data from 0-360 lon to -180 -> 180 in arrays
561  */
562  ipoff = iprm * npix_out * nlin_out;
563  shift_180((datarr + ipoff), npix_out, nlin_out, *(fac_lst + iprm),
564  float_out);
565  /*
566  * Write each data and qc SDS
567  */
568  sdsname = metoz_nm[iprm];
569  longname = metoz_ln_nm[iprm];
570  units = metoz_units[iprm];
571  datafmt = "float32";
572  datatype = DFNT_FLOAT32;
573 
574  if (SDSinFile(sdsname, longname, units, datafmt, datatype, sdfid,
575  rank, shape, float_out, gridid) != 0)
576  pexit(strcat("SDSinFile ", metoz_nm[iprm]));
577 
578  sdsname = qc_nm[iprm];
579  longname = qc_ln_nm[iprm];
580  units = "";
581  datafmt = "int8";
582  datatype = DFNT_INT8;
583 
584  if (SDSinFile(sdsname, longname, units, datafmt, datatype, sdfid,
585  rank, shape, qc_out, gridid) != 0)
586  pexit(strcat("SDSinFile ", qc_nm[iprm]));
587  }
588  } else {
589  /*
590  * shift and write the ozone - it is a short in this usage
591  */
592  if ((float_SDS_oz = (int16 *) malloc(sizeof (int16) * npix * nlin))
593  == NULL) pexit("malloc float_SDS_oz");
594 
595  l = 0;
596  for (j = 0; j < nlin; j++) { /* lats */
597  for (k = (npix / 2); k < npix; k++) { /* lons */
598  if (*(datarr + k + j * npix) < 0 ||
599  *(datarr + k + j * npix) > SHRT_MAX)
600  float_SDS_oz[l] = 0;
601  else
602  float_SDS_oz[l] = (int16)*(datarr + k + j * npix);
603  l++; /* index counter */
604  } /* for k */
605 
606  for (k = 0; k < (npix / 2); k++) { /* lons */
607  if (*(datarr + k + j * npix) < 0 ||
608  *(datarr + k + j * npix) > SHRT_MAX)
609  float_SDS_oz[l] = 0;
610  else
611  float_SDS_oz[l] = (int16)*(datarr + k + j * npix);
612  l++; /* index counter */
613  } /* for k */
614  } /* for j */
615  /*
616  * interpolate the array to the traditional TOVS ozone size
617  */
618  resize_oz((short *) float_SDS_oz, npix, nlin,
619  npix_out, nlin_out, (short *) oz_newsiz);
620  free(float_SDS_oz);
621 
622  sdsname = "ozone";
623  longname = "Total ozone";
624  units = "Dobson units";
625  datafmt = "int16";
626  datatype = DFNT_INT16;
627 
628  if ((SDSinFile(sdsname, longname, units, datafmt,
629  datatype, sdfid, rank, shape,
630  oz_newsiz, gridid)) != 0)
631  pexit("SDSinFile ozone");
632 
633  free(oz_newsiz);
634  /* ---- Write QC flag SDS, units attribute, and add to grid Vgroup -- */
635  sdsname = "ozone_QC";
636  longname = "Total ozone Q/C flag";
637  units = "";
638  datafmt = "int8";
639  datatype = DFNT_INT8;
640 
641  if ((SDSinFile(sdsname, longname, units, datafmt,
642  datatype, sdfid, rank, shape,
643  qc_out, gridid)) != 0)
644  pexit("SDSinFile ozone_QC");
645 
646  }
647 
648  /*
649  * free storage for QC array (used for all products)
650  */
651  free(qc_out);
652  free(datarr);
653  free(float_out);
654  /*
655  * deattach HDF grid (used for all products)
656  */
657 
658  deattachHDFgrid(gridid);
659 
660  /*
661  * close HDF structures
662  */
663 
664  if ((result = closeHDFstructs(sdfid, fid)) != 0) pexit("closeHDFstructs");
665  return 0;
666 } /* main */
667 
668 void shift_180(float *in, int npix, int nlin, float fact, float *out)
669 /*****************************************************************
670  shift_180 - shift a float array to have longitude range change
671  from 0 -> 360 to -180 -> 180
672 
673  Returns: none
674 
675  Parameters: (in calling order)
676  Type Name I/O Description
677  ---- ---- --- -----------
678  float * in I input array
679  int npix I array size in pixels
680  int nlin I array size in lines
681  float fact I conversion factor to apply
682  to the data values
683  float * out O finished output array,
684  already allocated storage
685 
686  W. Robinson, SAIC, 19 Mar 2015
687 
688  *****************************************************************/ {
689  int iln, ipx, oloc;
690 
691  oloc = 0;
692  for (iln = 0; iln < nlin; iln++) {
693  for (ipx = npix / 2; ipx < npix; ipx++) {
694  *(out + oloc) = *(in + ipx + npix * iln) * fact;
695  oloc++;
696  }
697 
698  for (ipx = 0; ipx < npix / 2; ipx++) {
699  *(out + oloc) = *(in + ipx + npix * iln) * fact;
700  oloc++;
701  }
702  }
703 }
704 
705 int8 check_usage(int argc, char *argv[], int *anctyp, int *n_opt_arg,
706  char *source_name, int *grib_mode, char *grib2_t_str)
707 /*****************************************************************
708  File: check_usage
709 
710  Purpose: check command line arguments
711 
712  Description: check command line arguements and report proper usage
713  on argument count error or no argumnts.
714 
715  Returns: success (0) or failure(-1)
716 
717  Parameters: (in calling order)
718  Type Name I/O Description
719  ---- ---- --- -----------
720  int argc I arg count
721  char *[] argv I input arg list
722  int * anctyp O type of anc data, either
723  ANC_MET or ANC_OZONE
724  int * n_opt_arg O # option args
725  char * source_name O An alternate source (as in gbl
726  attrib source) name
727  int * grib_mode O Type of grib file the binary
728  file came from: GRIB_MODE_1 for
729  a GRIB 1 file, GRIB_MODE_2 for a
730  GRIB 2 file (NCEP std as of
731  Jan 2008)
732  char * grib2_t_str O string with time of the GRIB 2
733  data - used for setting file
734  name and attributes
735 
736  Note: This routine is custom for each program that uses it since
737  the arguments are different of course.
738 
739  Author: Brian D. Schieber, GSC, 10/93
740 
741  Mods: 10/4/93 BDS, new HDF inputs handle all 3 NCEP parms
742  W. Robinson, GSC, 4 Feb 97 changes for 5th param:rel_hum
743  W. Robinson, GSC, 18 Jun 98 add flexability to either accept
744  7 or 8 inputs for met data or 3 or 4 for ozone data
745  W. Robinson, SAIC, 12 May 2005 have optional argument -s
746  for an optional source name
747  W. Robinson, SAIC, 24 Jan 2008 add a grib mode -2 for grib 2
748  format files
749  W. Robinson, SAIC, 20 Mar 2015 expand with ANC_METOZ type
750  *****************************************************************/ {
751  extern char *optarg;
752  extern int optind, optopt;
753  int c, opt_source_found, errflg;
754 
755  /*
756  * get the options first, one for the source name
757  */
758  *grib_mode = GRIB_MODE_1;
759  opt_source_found = 0;
760  errflg = 0;
761  *n_opt_arg = 0;
762  while ((c = getopt(argc, argv, ":s:2:")) != -1) {
763  switch (c) {
764  case 's':
765  strcpy(source_name, optarg);
766  opt_source_found = 1;
767  break;
768  case '2':
769  strcpy(grib2_t_str, optarg);
770  *grib_mode = GRIB_MODE_2;
771  break;
772  case ':': /* -s without operand */
773  fprintf(stderr,
774  "Option -%c requires an operand\n", optopt);
775  errflg++;
776  break;
777  case '?':
778  fprintf(stderr, "Unrecognized option: -%c\n", optopt);
779  errflg++;
780  }
781  }
782  if (!errflg) {
783  *n_opt_arg = optind;
784  /*
785  * for regular arguments
786  */
787  if (argc - optind == 7) {
788  *anctyp = ANC_MET;
789  if (!opt_source_found) strcpy(source_name, "NCEP");
790  } else if (argc - optind == 3) {
791  *anctyp = ANC_OZONE;
792  if (!opt_source_found) strcpy(source_name, "TOVS");
793  } else if (argc - optind == 8) {
794  *anctyp = ANC_METOZ;
795  if (!opt_source_found) strcpy(source_name, "NCEP");
796  } else if (argc - optind == 10) {
797  *anctyp = ANC_METOZ2;
798  if (!opt_source_found) strcpy(source_name, "NCEP");
799  } else {
800  errflg++;
801  }
802  }
803  if (errflg) {
804  printf("\n\nUsage:\n");
805  printf("\t%s <metadata> <flist> <file> <outdir> [options]\n",
806  argv[0]);
807  printf("\nWhere:\n");
808  printf("\tmetadata: DAAC-style HDF metadata (ASCII file)\n");
809  printf("\t usually fillenv_met.ancnrt\n");
810  printf("\tflist is a set of 1, 5, or 6 binary files created by wgrib\n");
811  printf("\t or wgrib2. the 3 sets are:\n");
812  printf("\t 1 file - for making an ozone dataset\n");
813  printf("\t file is just ozone (TOVS)\n");
814  printf("\t 5 files - for making a MET dataset from the NCEP data,\n");
815  printf("\t files are z_wind, m_wind, press, p_water, and rel_hum\n");
816  printf("\t 6 files - for making a MET and OZONE from the NCEP data,\n");
817  printf("\t files are MET set and ozone\n");
818  printf("\t This also has forecast file ingest ability\n");
819  printf("\toutdir: output directory ('./' can be used)\n");
820  printf("\t Options:\n");
821  printf("\t-s <sname> Optional source name to output file with:\n");
822  printf("\t for MET data: NYYYYDDD00_MET_<sname>_6h.hdf, default sname = NCEP\n");
823  printf("\t for MET and OZONE data:\n");
824  printf("\t NYYYYDDD00_MET_<sname>_<npix>x<nlin>_f<h_fcst>.hdf,\n");
825  printf("\t default sname = NCEP\n");
826  printf("\t for OZONE data: SYYYYDDD00DDD23_<sname>.OZONE, default sname = TOVS\n");
827  printf("\t-2 <GRIB str> Specify the -2 with the <GRIB str> to process\n");
828  printf("\t binary files derived from a GRIB 2 format file. The\n");
829  printf("\t binary files are derived using wgrib2 with the -bin \n");
830  printf("\t option. The <GRIB str> is a required date / time\n");
831  printf("\t identification string gotten using wgrib -t\n");
832  printf("\t (for 360 x 181 grid, 0 hour forecast)\n");
833  printf("\t or for MET and OZONE file: wgrib -t -nxny -ftime\n");
834  printf("\t (see $SWFAPP/scripts/met_ingest2.scr for full example)\n");
835  printf("\n");
836  exit(-1);
837  }
838  return (0);
839 }
int main(int argc, char *argv[])
Definition: ancnrt.c:95
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 day
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)
int addAttr(int32_t sdsid, char *dataattr, int32_t datatype, char *dataunit)
Definition: ANCroutines.c:222
#define ANC_MET
Definition: ancnrt.c:88
#define GRIB_MODE_2
Definition: ancnrt.c:93
#define GRIB_MODE_1
Definition: ancnrt.c:92
#define NULL
Definition: decode_rs.h:63
int readgrib2(char *file, int npix, int nlin, int rgmode, float *data)
Definition: readgrib.c:77
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude resolving resolving GSFcd00179 Corrected handling of fill values for[Sensor|Solar][Zenith|Azimuth] resolving MODxl01751 Changed to validate LUT version against a value retrieved from the resolving MODxl02056 Changed to calculate Solar Diffuser angles without adjustment for estimated post launch changes in the MODIS orientation relative to incidentally resolving defects MODxl01766 Also resolves MODxl01947 Changed to ignore fill values in SCI_ABNORM and SCI_STATE rather than treating them as resolving MODxl01780 Changed to use spacecraft ancillary data to recognise when the mirror encoder data is being set by side A or side B and to change calculations accordingly This removes the need for seperate LUTs for Side A and Side B data it makes the new LUTs incompatible with older versions of the and vice versa Also resolves MODxl01685 A more robust GRing algorithm is being which will create a non default GRing anytime there s even a single geolocated pixel in a granule Removed obsolete messages from seed as required for compatibility with version of the SDP toolkit Corrected test output file names to end in out
Definition: HISTORY.txt:422
int32 * msec
Definition: l1_czcs_hdf.c:31
float tm[MODELMAX]
#define WPH_DFT_LONSZ
Definition: ancnrt.c:85
int nlin
Definition: get_cmp.c:28
#define VGROUPNAME
Definition: ancnrt.c:82
#define OZLONSZ
Definition: ancnrt.c:87
void resize_oz(short *, int, int, int, int, short *)
Definition: resize_oz.c:1
char descr[MAXDESCLEN]
Definition: ancil.h:72
#define ANC_METOZ
Definition: ancnrt.c:90
#define WPH_DFT_LATSZ
Definition: ancnrt.c:84
int wrtattr(int32_t dfile, struct annotation *annot, int numannarr)
Definition: ANCroutines.c:631
int8 check_usage(int argc, char *argv[], int *anctyp, int *n_opt_arg, char *source_name, int *grib_mode, char *grib2_t_str)
Definition: ancnrt.c:705
void shift_180(float *in, int npix, int nlin, float fact, float *out)
Definition: ancnrt.c:668
void julian_(double *dtin, double *d_jd)
#define OZLATSZ
Definition: ancnrt.c:86
int count_annot(char *filename)
Definition: countann.c:11
instead the metadata field ProcessingEnvinronment is filled in from the output of a call to the POSIX compliant function uname from within the L1B code A small bug in L1B_Tables an incorrect comparison of RVS coefficients for TEBs to RVS coefficients for RSBs was being made This was replaced with a comparison between TEB coefficients This error never resulted in an incorrect RVS correction but did lead to recalculating the coefficients for each detector in a thermal band even if the coefficients were the same for all detectors To reduce to overall size of the reflective LUT HDF fill values were eliminated from all LUTs previously dimensioned where and where NUM_TIMES is the number of time dependent table pieces In Preprocess a small error where the trailing dropped scan counter was incremented when the leading dropped scan counter should have been was fixed This counter is internal only and is not yet used for any chiefly to casting of were added to make it LINUX compatible Output of code run on LINUX machines displays differences of at most scaled sector incalculable values of the Emissive calibration factor and incalculable values of SV or BB averages was moved outside the loop over frames in Emissive_Cal c since none of these quantities are frame dependent Initialization of b1 and XMS values in Preprocess c routine Process_OBCENG_Emiss was moved inside the detector loops The code was altered so that if up to five scans are dropped between the leading middle or middle trailing the leading or trailing granule will still be used in emissive calibration to form a cross granule average QA bits and are set for a gap between the leading middle and middle trailing granules respectively This may in rare instances lead to a change in emissive calibration coefficients for scans at the beginning or end of a granule A small bug in the Band correction algorithm was corrected an uncertainty value was being checked against an upper bound whereas the proper quantity to be checked was the corresponding which is the product of the Band radiance times the ratio of the Band to Band scaling factors times the LUT correction value for that detector In addition a new LUT which allows for a frame offset with regard to the Band radiance was added A LUT which switches the correction off or on was also added Changes which do not affect scientific output of the the pixel is flagged with the newly created flag and the number of pixels for which this occurs is counted in the QA_common table The array of b1s in Preprocess c was being initialized to outside the loop over which meant that if b1 could not be the value of b1 from the previous band for that scan detector combination was used The initialization was moved inside the band loop Minor code changes were made to eliminate compiler warnings when the code is compiled in bit mode Temperature equations were upgraded to be MODIS AQUA or MODIS TERRA specific and temperature conversion coefficients for AQUA were MOD_PR02 will not cease execution if the value of this parameter is not but will print a message
Definition: HISTORY.txt:644
subroutine fact
Definition: tmd.lp.f:1161
void unix2yds(double usec, short *year, short *day, double *secs)
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 readgrib(char *file, int npix, int nlin, float *data, int *year, int *month, int *day, int *hour)
Definition: readgrib.c:6
int deattachHDFgrid(int32_t gridid)
Definition: ANCroutines.c:267
int grib2_t(char *grib2_t_str, int *year, int *doy, int *hour, int *npix, int *nlin, int *h_fcst)
Definition: readgrib.c:158
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
#define ANC_METOZ2
Definition: ancnrt.c:91
double ymds2unix(short year, short month, short day, double secs)
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_FLOAT32
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude resolving resolving GSFcd00179 Corrected handling of fill values for[Sensor|Solar][Zenith|Azimuth] resolving MODxl01751 Changed to validate LUT version against a value retrieved from the resolving MODxl02056 Changed to calculate Solar Diffuser angles without adjustment for estimated post launch changes in the MODIS orientation relative to incidentally resolving defects MODxl01766 Also resolves MODxl01947 Changed to ignore fill values in SCI_ABNORM and SCI_STATE rather than treating them as resolving MODxl01780 Changed to use spacecraft ancillary data to recognise when the mirror encoder data is being set by side A or side B and to change calculations accordingly This removes the need for seperate LUTs for Side A and Side B data it makes the new LUTs incompatible with older versions of the and vice versa Also resolves MODxl01685 A more robust GRing algorithm is being which will create a non default GRing anytime there s even a single geolocated pixel in a granule Removed obsolete messages from seed as required for compatibility with version of the SDP toolkit Corrected test output file names to end in per delivery and then split off a new MYD_PR03 pcf file for Aqua Added AssociatedPlatformInstrumentSensor to the inventory metadata in MOD01 mcf and MOD03 mcf Created new versions named MYD01 mcf and MYD03 where AssociatedPlatformShortName is rather than Terra The program itself has been changed to read the Satellite Instrument validate it against the input L1A and LUT and to use it determine the correct files to retrieve the ephemeris and attitude data from Changed to produce a LocalGranuleID starting with MYD03 if run on Aqua data Added the Scan Type file attribute to the Geolocation copied from the L1A and attitude_angels to radians rather than degrees The accumulation of Cumulated gflags was moved from GEO_validate_earth_location c to GEO_locate_one_scan c
Definition: HISTORY.txt:464
int setSDSref(int32_t sdsid, int32_t gridid)
Definition: ANCroutines.c:245
#define MAXNAMELNG
Definition: ancil.h:43
#define ANC_OZONE
Definition: ancnrt.c:89
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
int npix
Definition: get_cmp.c:27
int startHDF(char *outfile, int32_t *sdfid, int32_t *fid, int32_t mode)
Definition: ANCroutines.c:27