OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
readgrib.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <timeutils.h>
5 
6 int readgrib(char *file, int npix, int nlin, float *data, int *year,
7  int *month, int *day, int *hour)
8 /*******************************************************************
9 
10  read_grib
11 
12  purpose: read in the data from a binary grib file with header
13  and pds
14 
15  Returns type: void
16 
17  Parameters: (in calling order)
18  Type Name I/O Description
19  ---- ---- --- -----------
20  char * file I binary grib file name
21  int npix I # pixels in grid
22  int nlin I # lines in grid
23  float * data O returned data
24  int * year O year
25  int * month O month
26  int * day O day
27  int * hour O hour
28 
29  Modification history:
30  Programmer Date Description of change
31  ---------- ---- ---------------------
32  W. Robinson 17-Sep-2003 Original development - replacement
33  for fortran version and upgrade
34  for use with wgrib program
35  W. Robinson, SAIC 24 Jan 2008 Adapt to call rd_grib_grid to
36  get the data size and data grid
37  W. Robinson, SAIC 24 Jun 2014 have variable # pixels, lines
38 
39  *******************************************************************/ {
40  FILE *stream;
41  int retcode;
42  int rd_grib_pds(FILE *, int *, int *, int *, int *);
43  int rd_grib_grid(FILE *, int, int, float *);
44  /*
45  * First, open the file
46  */
47  retcode = 0;
48  if ((stream = fopen(file, "r")) == NULL) {
49  printf("Unable to open GRIB file: %s, Exiting\n", file);
50  retcode = 1;
51  } else {
52  /*
53  * read the PDS / GDS and get the date and time
54  */
55  if (rd_grib_pds(stream, year, month, day, hour) != 0) {
56  printf(
57  "Error on PDS portion of grib file read for file: %s, Exiting\n", file);
58  retcode = 1;
59  } else {
60  /*
61  * check size and read grid
62  */
63  if (rd_grib_grid(stream, npix, nlin, data) != 0) {
64  printf("%s: rd_grib_grid failed for file: %s\n", __FILE__, file);
65  retcode = 1;
66  }
67  }
68  }
69  fclose(stream);
70 
71  /*
72  * close the data file and return hopefully with the data
73  */
74  return retcode;
75 }
76 
77 int readgrib2(char *file, int npix, int nlin, int rgmode,
78  float *data)
79 /*******************************************************************
80 
81  readgrib2
82 
83  purpose: read in the data from a binary grib 2 file generated
84  using wgrib2 with the -bin option
85 
86  Returns type: int 0 if all is OK
87 
88  Parameters: (in calling order)
89  Type Name I/O Description
90  ---- ---- --- -----------
91  char * file I binary grib file name
92  int npix I # pixels in grid
93  int nlin I # lines in grid
94  int rgmode I read mode: 0 do not invert in
95  latitude (aquarius), 1 invert
96  (std ancnrt)
97  float * data O returned data
98 
99  Modification history:
100  Programmer Date Description of change
101  ---------- ---- ---------------------
102  W. Robinson, SAIC 24-Jan-2008 Original development
103  W. Robinson, SAIC 18 Sep 2009 add a rgmode: 0 do not invert in
104  latitude (aquarius), 1 invert (std ancnrt)
105  W. Robinson, SAIC 10-Dec-2009 use variable grid size and extract
106  time computation
107  W. Robinson, SAIC 18-Mar-2015 remove the grib string interpretation
108 
109  *******************************************************************/ {
110  FILE *stream;
111  int retcode, ilin;
112  float *xfr_arr;
113  int rd_grib_grid(FILE *, int, int, float *);
114  /*
115  * First, open the file
116  */
117  retcode = 0;
118  if ((stream = fopen(file, "r")) == NULL) {
119  printf("Unable to open GRIB file: %s, Exiting\n", file);
120  retcode = 1;
121  } else {
122  /*
123  * check size and read grid
124  */
125  if (rd_grib_grid(stream, npix, nlin, data) != 0) {
126  printf("%s: rd_grib_grid failed for file: %s\n", __FILE__, file);
127  retcode = 1;
128  }
129  /*
130  * close the data file
131  */
132  fclose(stream);
133  }
134  /*
135  * for ancnrt use (rgmode = 1) and if no earlier problems, the grid
136  * must be reversed in latitude to match grib 1 grid
137  */
138  if ((rgmode == 1) && (retcode == 0)) {
139  if ((xfr_arr = (float *) malloc(npix * sizeof ( float))) == NULL) {
140  printf("%s: Transfer space allocation failed\n", __FILE__);
141  retcode = 1;
142  } else {
143  for (ilin = 0; ilin < nlin / 2; ilin++) {
144  memcpy((void *) xfr_arr, (void *) (data + ilin * npix),
145  npix * sizeof ( float));
146  memcpy((void *) (data + ilin * npix),
147  (void *) (data + (nlin - 1 - ilin) * npix),
148  npix * sizeof ( float));
149  memcpy((void *) (data + (nlin - 1 - ilin) * npix),
150  (void *) xfr_arr, npix * sizeof ( float));
151  }
152  free(xfr_arr);
153  }
154  }
155  return retcode;
156 }
157 
158 int grib2_t(char *grib2_t_str, int *year, int *doy, int *hour, int *npix,
159  int *nlin, int *h_fcst)
160 /*******************************************************************
161 
162  grib2_t
163 
164  purpose: get the data time, and maybe size from information for a
165  GRIB2 file
166 
167  Returns type: int 0 if all is OK
168 
169  Parameters: (in calling order)
170  Type Name I/O Description
171  ---- ---- --- -----------
172  char * grib2_t_str I string containing grib file
173  date and time (from wgrib2 -t)
174  int * year O year
175  int * doy O day of year
176  int * hour O hour
177  int * npix O # pixels, if not gotten
178  here, return -1
179  int * nlin O # lines, if not gotten
180  here, return -1
181 
182  Modification history:
183  Programmer Date Description of change
184  ---------- ---- ---------------------
185  W. Robinson, SAIC 10-Dec-2009 break out of readgrib2...
186  W. Robinson, SAIC 18-Mar-2015 enhance to just read the time data
187  gotten with wgrib2 -t <file>
188  or time and grid size, forecast time gotten with
189  wgrib2 -t -nxny -ftime
190  the time is adjusted by the forecast time.
191 
192  *******************************************************************/ {
193  int retcode, nchr, month, day;
194  char *equal_ptr, *nex_ptr, *nex_ptr2, tmp_str[200];
195  double unix_t, sec;
196  retcode = 0;
197  /*
198  * The form of the time string can be: <chars>=YYYYMMDDHH
199  * and optionally followed by: :(<# pix> x <# lin>):<fcst>
200  * with <# pix>, <# lin> an integer grid size in oix, lin and
201  * <fcst> either 'anl' for 0 h forecast or an integer # hours forecast
202  */
203  /*
204  * The time id of form YYYYMMDDHH after the last '=' in the string
205  */
206  if ((equal_ptr = strrchr(grib2_t_str, '=')) == NULL) {
207  printf("%s: Unable to find start of time in GRIB 2 time string of: %s\n",
208  __FILE__, grib2_t_str);
209  retcode = 1;
210  } else {
211  if (sscanf(equal_ptr, "=%4d%2d%2d%2d", year, &month, &day, hour) != 4) {
212  printf("%s: Unable to decode time in GRIB 2 time string of: %s\n",
213  __FILE__, grib2_t_str);
214  retcode = 1;
215  }
216  }
217  /*
218  * OK, for the optional portion
219  */
220  if ((nex_ptr = strchr(equal_ptr, '(')) == NULL) {
221  *h_fcst = 0; /* set to no forecast and fill for size */
222  *npix = -1;
223  *nlin = -1;
224  } else {
225  /* find, read # pixels, lines */
226  if ((nex_ptr2 = strchr(nex_ptr, ')')) == NULL) {
227  printf("%s, %d: wgrib2 info string has no ')' in grid size portion\n",
228  __FILE__, __LINE__);
229  return 1;
230  }
231  nchr = nex_ptr2 - nex_ptr + 1;
232  strncpy(tmp_str, nex_ptr, nchr);
233  if (sscanf(tmp_str, "(%d x %d)", npix, nlin) != 2) {
234  printf("%s, %d: Unable to convert grid size info\n",
235  __FILE__, __LINE__);
236  return 1;
237  }
238  /* get forecast time */
239  if ((nex_ptr = strchr(nex_ptr2, ':')) == NULL) {
240  printf("%s, %d: wgrib2 info string has no forecast time info\n",
241  __FILE__, __LINE__);
242  return 1;
243  }
244  if (strcmp(nex_ptr, ":anl") == 0)
245  *h_fcst = 0;
246  else {
247  if (sscanf(nex_ptr, ":%d", h_fcst) != 1) {
248  printf("%s, %d: Unable to convert forecast time info\n",
249  __FILE__, __LINE__);
250  return 1;
251  }
252  }
253  }
254  /*
255  * The only thing left is to account for the forecast time or
256  * at least make day of year time
257  */
258  sec = (double) *hour * 3600;
259  unix_t = ymds2unix(*year, month, day, sec);
260  unix_t += (double) *h_fcst * 3600;
261  unix2yds(unix_t, (int16_t *) year, (int16_t *) doy, &sec);
262  *hour = sec / 3600;
263  /* and end */
264  return retcode;
265 }
266 
267 int readgrib2_3d(char *file, char *grib2_t_str, int npix, int nlin,
268  float *data, int nprfl, int *year, int *month, int *day, int *hour)
269 /*******************************************************************
270 
271  readgrib2_3d
272 
273  purpose: read in the data from a 3D binary grib 2 file generated
274  using wgrib2 with the -bin option
275 
276  Returns type: int 0 if all is OK
277 
278  Parameters: (in calling order)
279  Type Name I/O Description
280  ---- ---- --- -----------
281  char * file I binary grib file name
282  char * grib2_t_str I string containing grib file
283  date and time (from wgrib2
284  -t)
285  int npix I # pixels in grid
286  int nlin I # lines in grid
287  float * data O returned data
288  int nprfl I # levels in grid
289  int * year O year
290  int * month O month
291  int * day O day
292  int * hour O hour
293 
294  Modification history:
295  Programmer Date Description of change
296  ---------- ---- ---------------------
297  W. Robinson, SAIC 24-Jan-2008 Original development
298  J. Gales, F.T. 15-May-2008 Add support for profile (3d) files
299  W. Robinson, SAIC 10-Dec-2009 use variable grid size and extract
300  time computation
301  W. Robinson, SAIC 19 Mar 2015 adapt for new grib2_t call seq
302 
303  *******************************************************************/ {
304  FILE *stream;
305  int retcode, iprfl, offset, doy, npix_n, nlin_n, h_fcst;
306  int rd_grib_grid(FILE *, int, int, float *);
307  int grib2_t(char *, int *, int *, int *, int *, int *, int *);
308  /*
309  * First, open the file
310  */
311  retcode = 0;
312  if ((stream = fopen(file, "r")) == NULL) {
313  printf("Unable to open GRIB file: %s, Exiting\n", file);
314  retcode = 1;
315  } else {
316  /*
317  * and get the date and time from the grib 2 time string
318  */
319  if (grib2_t(grib2_t_str, year, &doy, hour, &npix_n, &nlin_n, &h_fcst) != 0)
320  retcode = 1;
321  else {
322  /*
323  * check size and read grid
324  */
325  yd2md(*year, doy, (int16_t *) month, (int16_t *) day);
326  offset = 0;
327  for (iprfl = 0; iprfl < nprfl; iprfl++) {
328  if (rd_grib_grid(stream, npix, nlin, &data[offset]) != 0) {
329  printf("%s: rd_grib_grid failed for file: %s\n", __FILE__, file);
330  retcode = 1;
331  }
332  // offset += (nlin * npix) + 2;
333  offset += (nlin * npix);
334  }
335  }
336  }
337  /*
338  * close the data file
339  */
340  fclose(stream);
341 
342  return retcode;
343 }
344 
345 int rd_grib_grid(FILE *stream, int npix, int nlin, float *data)
346 /*******************************************************************
347 
348  rd_grib_grid
349 
350  purpose: with an open binary file with grid, read / check the size in
351  bytes and read the data grid
352 
353  Returns type: int - 0 if all is OK
354 
355  Parameters: (in calling order)
356  Type Name I/O Description
357  ---- ---- --- -----------
358  FILE * stream I ID of opened file
359  int npix I # pixels in grid
360  int nlin I # lines in grid
361  float * data O data grid read
362 
363  Modification history:
364  Programmer Date Description of change
365  ---------- ---- ---------------------
366  W. Robinson 24 Jan 2008 Original development
367  *******************************************************************/ {
368  size_t rd_count;
369  int expect_ct, retcode, in_nbyt, nbyt;
370  int32_t npt_grid;
371  void rpt_err_typ(int, int, FILE *);
372  /*
373  * read the dimensions
374  */
375  retcode = 0;
376  nbyt = npix * nlin * sizeof ( float);
377  expect_ct = 1; /* note that wgrib2 puts out a 4-byte integer
378  count of the # bytes of data in the binary data -
379  that is checked first */
380  if ((rd_count = fread(&in_nbyt, sizeof ( int), expect_ct, stream))
381  != expect_ct) {
382  printf("Error on header read of GRIB file, Exiting\n");
383  rpt_err_typ(rd_count, expect_ct, stream);
384  retcode = 1;
385  } else {
386  /*
387  * We'll assume size 144, 73 now and check that
388  */
389  if (in_nbyt != nbyt) {
390  printf("current grid size of %d bytes is not the expected size of 144 X 73 = %d bytes, Exiting\n", in_nbyt, nbyt);
391  retcode = 1;
392  } else {
393  /*
394  * read the grid
395  */
396  npt_grid = npix * nlin;
397  if ((rd_count = fread(data, sizeof ( float), npt_grid, stream)) != npt_grid) {
398  printf("Error reading grid from GRIB file, Exiting\n");
399  rpt_err_typ(rd_count, npt_grid, stream);
400  retcode = 1;
401  }
402  }
403 
404  if ((rd_count = fread(&in_nbyt, sizeof ( int), expect_ct, stream))
405  != expect_ct) {
406  printf("Error on footer read of GRIB file, Exiting\n");
407  rpt_err_typ(rd_count, expect_ct, stream);
408  retcode = 1;
409  }
410  }
411  return retcode;
412 }
413 
414 int rd_grib_pds(FILE *stream, int* year, int* month, int* day, int* hour)
415 /*******************************************************************
416 
417  read_grib
418 
419  purpose: 1 - read the date and time from the PDS in the grib data and,
420  2 - position the file so the rest of the data can be read
421 
422  Returns type: int 0 if OK read, 1 if problem
423 
424  Parameters: (in calling order)
425  Type Name I/O Description
426  ---- ---- --- -----------
427  FILE * stream I file stream id
428  int * year O year
429  int * month O month
430  int * day O day
431  int * hour O hour
432 
433  Modification history:
434  Programmer Date Description of change
435  ---------- ---- ---------------------
436  W. Robinson 23-Sep-2003 Original development
437  W. Robinson, SAIC 16-Mar-2010 # pixel, line possibility
438 
439  *******************************************************************/ {
440  int retcode, expect_ct, rd_count, lenarr[2];
441  unsigned char pds_gds[100];
442  void rpt_err_typ(int, int, FILE *);
443  /*
444  * read the length of the PDS + 4 (bytes) and the char str 'PDS '
445  * into 2 4 byte integers
446  */
447  retcode = 0;
448  expect_ct = 2;
449  if ((rd_count = fread(lenarr, sizeof ( int), expect_ct, stream)) !=
450  expect_ct) {
451  printf("Error on 1st PDS read\n");
452  rpt_err_typ(rd_count, expect_ct, stream);
453  retcode = 1;
454  } else {
455  /*
456  * read the pds as bytes and the duplicate length
457  * the char str of 'PDS ' from prev read could be checked but...
458  */
459  expect_ct = lenarr[0];
460  if ((rd_count =
461  fread(pds_gds, sizeof ( unsigned char), expect_ct, stream))
462  != expect_ct) {
463  printf("Error on 2nd PDS read\n");
464  rpt_err_typ(rd_count, expect_ct, stream);
465  retcode = 1;
466  } else {
467  /*
468  * The time info is in the 4th set of 8 bytes
469  */
470  *year = pds_gds[12];
471  *month = pds_gds[13];
472  *day = pds_gds[14];
473  *hour = pds_gds[15];
474  /*
475  * lastly, read the GDS info and the GDS bytes
476  */
477  expect_ct = 2;
478  if ((rd_count = fread(lenarr, sizeof ( int), expect_ct, stream)) !=
479  expect_ct) {
480  printf("Error on 3rd PDS read\n");
481  rpt_err_typ(rd_count, expect_ct, stream);
482  retcode = 1;
483  } else {
484  expect_ct = lenarr[0];
485  if ((rd_count =
486  fread(pds_gds, sizeof ( unsigned char), expect_ct, stream))
487  != expect_ct) {
488  printf("Error on 4th PDS read\n");
489  rpt_err_typ(rd_count, expect_ct, stream);
490  retcode = 1;
491  }
492  /*
493  * # pixels, lines available in GDS (for reg grid) and this will
494  * show the getting of them if needed in future
495  */
496  //npix = 256 * (int)pds_gds[6] + (int)pds_gds[7];
497  //nlin = 256 * (int)pds_gds[8] + (int)pds_gds[9];
498  /*
499  printf( "%s, %d, TEST - from GDS, # pixels: %d, # lines: %d\n",
500  __FILE__, __LINE__, npix, nlin );
501  */
502  }
503  }
504  }
505  return retcode;
506 }
507 
508 /*
509  * Just to report the errors in fread
510  * int rd_count - count of what was read
511  * int expect_ct - count of what was expected
512  * FILE *stream - file id from open
513  */
514 void rpt_err_typ(int rd_count, int expect_ct, FILE *stream) {
515  int errcod;
516  if ((errcod = ferror(stream)) != 0) {
517  printf("Error code of %d encountered\n", errcod);
518  } else if (feof(stream) != 0) {
519  printf("EOF encountered\n");
520  } else {
521  printf("Only %d values were read instead of the expected %d values\n",
522  rd_count, expect_ct);
523  }
524  return;
525 }
int32_t day
#define NULL
Definition: decode_rs.h:63
int readgrib2_3d(char *file, char *grib2_t_str, int npix, int nlin, float *data, int nprfl, int *year, int *month, int *day, int *hour)
Definition: readgrib.c:267
int rd_grib_grid(FILE *stream, int npix, int nlin, float *data)
Definition: readgrib.c:345
int nlin
Definition: get_cmp.c:28
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 file
Definition: HISTORY.txt:413
int grib2_t(char *grib2_t_str, int *year, int *doy, int *hour, int *npix, int *nlin, int *h_fcst)
Definition: readgrib.c:158
void yd2md(int16_t year, int16_t doy, int16_t *month, int16_t *dom)
Definition: yd2md.c:6
void rpt_err_typ(int rd_count, int expect_ct, FILE *stream)
Definition: readgrib.c:514
int readgrib2(char *file, int npix, int nlin, int rgmode, float *data)
Definition: readgrib.c:77
void unix2yds(double usec, short *year, short *day, double *secs)
integer, parameter double
int readgrib(char *file, int npix, int nlin, float *data, int *year, int *month, int *day, int *hour)
Definition: readgrib.c:6
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude data
Definition: HISTORY.txt:356
int rd_grib_pds(FILE *stream, int *year, int *month, int *day, int *hour)
Definition: readgrib.c:414
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)
double ymds2unix(short year, short month, short day, double secs)
l2prod offset
int npix
Definition: get_cmp.c:27