OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
nc4utils.c
Go to the documentation of this file.
1 #include "nc4utils.h"
2 #ifndef FAIL
3 #define FAIL 1
4 #endif
5 #ifndef SUCCESS
6 #define SUCCESS 0
7 #endif
8 
9 /* ------------------------------------------------------------------ */
10 /* Utilities */
11 
12 static const char* typename[] = {/* from netcdf.h */
13  "notype", /* 0 = NC_NAT : Not A Type */
14  "byte", /* 1 = NC_BYTE : signed 1-byte integer */
15  "char", /* 2 = NC_CHAR : ISO/ASCII character */
16  "short", /* 3 = NC_SHORT : signed 2-byte integer */
17  "int", /* 4 = NC_INT : signed 4-byte integer */
18  "float", /* 5 = NC_FLOAT : single precision floating point number */
19  "double", /* 6 = NC_DOUBLE : double precision floating point number */
20  "ubyte", /* 7 = NC_UBYTE : unsigned 1-byte integer */
21  "ushort", /* 8 = NC_USHORT : unsigned 2-byte integer */
22  "uint", /* 9 = NC_UINT : unsigned 4-byte integer */
23  "int64", /* 10 = NC_INT64 : signed 8-byte integer */
24  "uint64", /* 11 = NC_UINT64 : unsigned 8-byte integer */
25  "string" /* 12 = NC_STRING : string */
26 };
27 
28 void report_err(const int stat, const int line, const char *file) {
29  if (stat != NC_NOERR) {
30  (void) fprintf(stderr, "line %d of %s: %s\n", line, file, nc_strerror(stat));
31  fflush(stderr);
32  }
33 }
34 
35 void check_err(const int stat, const int line, const char *file) {
36  if (stat != NC_NOERR) {
37  (void) fprintf(stderr, "line %d of %s: %s\n", line, file, nc_strerror(stat));
38  fflush(stderr);
39  exit(1);
40  }
41 }
42 
43 char* format_ncval(void *value, nc_type type, size_t nvals) {
44  int i, nchar;
45  char *result;
46  char tmp[256];
47 
48  /*
49  TBD: prevent buffer overflows.
50  how much memory to allocate for tmp string?
51  NC_CHAR: nvals + "" + null = nvals+3
52  how about numerical types?
53  */
54 
55  if (type == NC_CHAR) {
56  ((char *) value)[nvals] = '\0'; // null terminate
57  nchar = nvals + 3; //add space for quotes
58  TRYMEM(__FILE__, __LINE__,
59  (result = malloc(nchar * sizeof (char))));
60  result[0] = '\0';
61  sprintf(result, "\"%s\"", (char *) value);
62 
63  } else {
64  TRYMEM(__FILE__, __LINE__,
65  (result = malloc(64 * nvals)));
66  result[0] = '\0';
67  for (i = 0; i < nvals; i++) {
68  switch (type) {
69  case NC_BYTE:
70  sprintf(tmp, "\%db", ((signed char *) value)[i]);
71  break;
72  case NC_SHORT:
73  sprintf(tmp, "\%ds", ((short *) value)[i]);
74  break;
75  case NC_INT:
76  sprintf(tmp, "\%d", ((int *) value)[i]);
77  break;
78  case NC_FLOAT:
79  sprintf(tmp, "\%gf", ((float *) value)[i]);
80  break;
81  case NC_DOUBLE:
82  sprintf(tmp, "\%g", ((double *) value)[i]);
83  break;
84  case NC_UBYTE:
85  sprintf(tmp, "\%uUB", ((unsigned char *) value)[i]);
86  break;
87  case NC_USHORT:
88  sprintf(tmp, "\%huUS", ((unsigned short *) value)[i]);
89  break;
90  case NC_UINT:
91  sprintf(tmp, "\%uU", ((unsigned int *) value)[i]);
92  break;
93  default:
94  sprintf(tmp, "\tvalue of unknown type %d, nvals %d)",
95  (int) type, (int) nvals);
96  } // TO DO: handle type NC_STRING
97  strcat(result, tmp);
98  if (i < nvals - 1) strcat(result, ", ");
99  }
100  }
101  return result;
102 }
103 
104 /* ------------------------------------------------------------------ */
105 
106 /* Dimensions */
107 
108 
110  int ndims = 0;
111  dim_str_nc *dim = NULL;
112 
113  /* find number of dimensions visible to group */
114  TRY_NC(__FILE__, __LINE__,
115  nc_inq_dimids(ncid, &ndims, NULL, 1));
116 
117  /* load dimension info */
118  if (ndims > 0) {
119  int i; /* dimension index */
120  int *dimids; /* dimension ID */
121 
122  TRYMEM(__FILE__, __LINE__,
123  (dimids = malloc(ndims * sizeof (*dimids))));
124  TRY_NC(__FILE__, __LINE__,
125  nc_inq_dimids(ncid, NULL, dimids, 1)); // ids for each dimension
126 
127  TRYMEM(__FILE__, __LINE__,
128  (dim = malloc(ndims * sizeof (*dim))));
129  for (i = 0; i < ndims; i++)
130  TRY_NC(__FILE__, __LINE__,
131  nc_inq_dim(ncid, dimids[i], dim[i].name, &dim[i].len));
132 
133  free(dimids);
134  dimids = NULL;
135  }
136  return dim;
137 }
138 
139 void print_dims_nc(dim_str_nc *dim, int ndims) {
140  int i; /* dimension index */
141  for (i = 0; i < ndims; i++)
142  printf("\t%s = %d ;\n",
143  dim[i].name,
144  (int) dim[i].len);
145 }
146 
148  if (dim) {
149  free(dim);
150  dim = NULL;
151  }
152 }
153 
161 int find_dimid_nc(int ncid, int *dimid, const char *dimnames[]) {
162  int i;
163  int status; /* error status */
164  i = 0;
165  while (dimnames[i] != NULL) {
166  status = nc_inq_dimid(ncid, dimnames[i], dimid);
167  if (status == NC_NOERR) break;
168  i++;
169  }
170  return status;
171 }
172 
173 /* ------------------------------------------------------------------ */
174 
175 /* Attributes */
176 
177 att_str_nc *load_atts_nc(int ncid, int varid) {
178  int natts = 0;
179  att_str_nc *att = NULL;
180 
181  /* find number of attributes for this group or variable */
182  TRY_NC(__FILE__, __LINE__,
183  nc_inq_varnatts(ncid, varid, &natts));
184 
185  if (natts > 0) {
186  int i; /* attribute index */
187  size_t typesize, nvals;
188 
189  /* initialize attribute structure */
190  TRYMEM(__FILE__, __LINE__,
191  (att = malloc(natts * sizeof (*att))));
192 
193  for (i = 0; i < natts; i++) {
194 
195  /* load info for this attribute */
196  TRY_NC(__FILE__, __LINE__,
197  nc_inq_attname(ncid, varid, i, att[i].name));
198  TRY_NC(__FILE__, __LINE__,
199  nc_inq_att(ncid, varid,
200  att[i].name,
201  &att[i].type,
202  &att[i].nvals));
203 
204  /* allocate space to read in all values of this attribute */
205  TRY_NC(__FILE__, __LINE__,
206  nc_inq_type(ncid, att[i].type, NULL, &typesize));
207  nvals = (att[i].type == NC_CHAR) ? att[i].nvals + 1 : att[i].nvals;
208  TRYMEM(__FILE__, __LINE__,
209  (att[i].value = malloc(nvals * typesize)));
210 
211  /* read attribute values */
212  TRY_NC(__FILE__, __LINE__,
213  nc_get_att(ncid, varid,
214  att[i].name,
215  att[i].value));
216  if (att[i].type == NC_CHAR) // set terminating char
217  ((char*) att[i].value)[att[i].nvals] = '\0';
218 
219  }
220  }
221  return att;
222 }
223 
224 void print_atts_nc(att_str_nc *att, int natts, char *varname) {
225  int i; /* attribute index */
226  for (i = 0; i < natts; i++)
227  if (att[i].nvals > 0)
228  printf("\t\t%s:%s = %s ;\n",
229  varname, att[i].name,
230  format_ncval(att[i].value,
231  att[i].type,
232  att[i].nvals)
233  );
234 }
235 
236 void free_atts_nc(att_str_nc *att, int natts) {
237  int i; /* attribute index */
238  if (att) {
239  for (i = 0; i < natts; i++) {
240  if (att[i].value) {
241  free(att[i].value);
242  att[i].value = NULL;
243  }
244  }
245  free(att);
246  att = NULL;
247  }
248 }
249 
250 /* ------------------------------------------------------------------ */
251 
252 /* Variables */
253 
255  int nvars = 0;
256  var_str_nc *var = NULL;
257 
258  /* find number of variables inside group */
259  TRY_NC(__FILE__, __LINE__,
260  nc_inq_varids(ncid, &nvars, NULL)); // # vars inside group
261 
262  if (nvars > 0) {
263  int i; /* variable index */
264  int *varids; /* variable ID */
265 
266  /* initialize variable structure */
267  TRYMEM(__FILE__, __LINE__,
268  (varids = malloc(nvars * sizeof (*varids))));
269  TRY_NC(__FILE__, __LINE__,
270  nc_inq_varids(ncid, NULL, varids)); // ids for each variable
271  TRYMEM(__FILE__, __LINE__,
272  (var = malloc(nvars * sizeof (*var))));
273 
274  for (i = 0; i < nvars; i++) {
275  var[i].grpid = ncid;
276  var[i].id = varids[i];
277  var[i].data = NULL;
278  var[i].dim = NULL;
279 
280  /* load info for this variable */
281  TRY_NC(__FILE__, __LINE__,
282  nc_inq_var(ncid, varids[i],
283  var[i].name,
284  &var[i].type,
285  &var[i].ndims,
286  var[i].dimids,
287  &var[i].natts));
288 
289  /* load dimensions */
290  if (var[i].ndims > 0) {
291  int idim; /* dimension index */
292  dim_str_nc *dim = NULL;
293  TRYMEM(__FILE__, __LINE__,
294  (dim = malloc(var[i].ndims * sizeof (*dim))));
295  for (idim = 0; idim < var[i].ndims; idim++) {
296  TRY_NC(__FILE__, __LINE__,
297  nc_inq_dim(ncid,
298  var[i].dimids[idim],
299  dim[idim].name,
300  &dim[idim].len));
301  }
302  var[i].dim = dim;
303  }
304  /* load variable attributes */
305  var[i].att = load_atts_nc(ncid, varids[i]);
306  }
307  }
308  return var;
309 }
310 
311 /* Returns pointer to specified variable in already-loaded group structure */
312 
313 /* Works only for 1st-level groups */
315  const char* varname, const char* grpname) {
316  int32_t igrp, ivar;
317  var_str_nc *varptr = NULL;
318 
319  for (igrp = 0; igrp < nc.ngrps; igrp++)
320  if (strcmp(grpname, (char*) nc.grps[igrp].name) == 0)
321  break;
322 
323  if (igrp < nc.ngrps) {
324  for (ivar = 0; ivar < nc.grps[igrp].nvars; ivar++)
325  if (strcmp(varname, (char*) nc.grps[igrp].var[ivar].name) == 0)
326  break;
327  if (ivar < nc.grps[igrp].nvars)
328  varptr = &nc.grps[igrp].var[ivar];
329  }
330 
331  return varptr;
332 }
333 
335  int32_t status = SUCCESS;
336 
337  if (!var) {
338  printf("-E- readall_var - Hey, you passed in a NULL pointer.\n");
339  exit(EXIT_FAILURE);
340  }
341 
342  if (var->ndims > 0) {
343  int i; /* dimension index */
344  size_t typesize;
345  size_t nvals = 1;
346 
347  /* allocate space to read in all values of this variable */
348  TRY_NC(__FILE__, __LINE__,
349  nc_inq_type(var->id, var->type, NULL, &typesize));
350  for (i = 0; i < var->ndims; i++)
351  nvals *= var->dim[i].len;
352  TRYMEM(__FILE__, __LINE__,
353  (var->data = malloc(nvals * typesize)));
354 
355  /* read variable values */
356  TRY_NC(__FILE__, __LINE__,
357  nc_get_var(var->grpid, var->id, var->data));
358  }
359  return status;
360 }
361 
362 void print_vars_nc(var_str_nc *var, int nvars) {
363  int i; /* variable index */
364  var_str_nc v;
365  int idim;
366 
367  for (i = 0; i < nvars; i++) {
368  v = var[i];
369  printf("\t%s %s", typename[v.type], v.name);
370 
371  /* dimension array */
372  if (v.ndims > 0)
373  printf("(");
374  for (idim = 0; idim < v.ndims; idim++) {
375  printf("%s", v.dim[idim].name);
376  printf("%s", idim < v.ndims - 1 ? ", " : ")");
377  }
378 
379  printf(" ;\n");
380  print_atts_nc(v.att, v.natts, v.name);
381  }
382 }
383 
384 void free_vars_nc(var_str_nc *var, int nvars) {
385  int i; /* variable index */
386  if (var) {
387  for (i = 0; i < nvars; i++) {
388  free_dims_nc(var[i].dim); // dimensions
389  free_atts_nc(var[i].att, var[i].natts); // attributes
390  if (var[i].data) { // data
391  free(var[i].data);
392  var[i].data = NULL;
393  }
394  }
395  free(var);
396  var = NULL;
397  }
398 }
399 
407 int find_varid_nc(int ncid, int *varid, const char *varnames[]) {
408  int i;
409  int status; /* error status */
410  i = 0;
411  while (varnames[i] != NULL) {
412  status = nc_inq_varid(ncid, varnames[i], varid);
413  if (status == NC_NOERR) break;
414  i++;
415  }
416  return status;
417 }
418 
419 /* ------------------------------------------------------------------ */
420 
421 /* Group (including root level) */
422 
424  int status = SUCCESS; /* error status */
425  int ncid = grp->id;
426 
427  /* load group info */
428  TRY_NC(__FILE__, __LINE__,
429  nc_inq_grpname(ncid, grp->name));
430  TRY_NC(__FILE__, __LINE__,
431  nc_inq(ncid,
432  &grp->ndims,
433  &grp->nvars,
434  &grp->natts,
435  NULL)); // don't bother with unlimited dimensions
436 
437  /* load dimensions, variables & group attributes */
438  grp->dim = load_grpdims(ncid);
439  grp->att = load_atts_nc(ncid, NC_GLOBAL);
440  grp->var = load_vars_nc(ncid);
441 
442  /* load any subgroups */
443  TRY_NC(__FILE__, __LINE__,
444  nc_inq_grps(grp->id, &grp->ngrps, NULL)); // number of subgroups
445  if (grp->ngrps > 0) {
446  int j; /* subgroup index */
447  int *grpids; /* subgroup ID */
448 
449  TRYMEM(__FILE__, __LINE__,
450  (grpids = malloc(grp->ngrps * sizeof (*grpids))));
451  TRY_NC(__FILE__, __LINE__,
452  nc_inq_grps(ncid, NULL, grpids)); // ids for each subgroup
453 
454  TRYMEM(__FILE__, __LINE__,
455  (grp->grps = malloc(grp->ngrps * sizeof (*grp->grps))));
456  for (j = 0; j < grp->ngrps; j++) {
457  grp->grps[j].id = grpids[j];
458  load_grp_nc(&grp->grps[j]); // recursive
459  }
460  free(grpids);
461  }
462 
463  return status;
464 }
465 
467  int i;
468  //static int level = 0;
469  printf("\ngroup: %s {\n", grp.name);
470 
471  /* dimensions */
472  if (grp.ndims > 0) printf("dimensions:\n");
473  print_dims_nc(grp.dim, grp.ndims);
474 
475  /* variables */
476  if (grp.nvars > 0) printf("variables:\n");
477  print_vars_nc(grp.var, grp.nvars);
478 
479  /* group attributes */
480  if (grp.natts > 0) printf("\n// attributes:\n");
481  print_atts_nc(grp.att, grp.natts, "");
482 
483  /* subgroups */
484  for (i = 0; i < grp.ngrps; i++) {
485  //level++;
486  print_grp_nc(grp.grps[i]); // recursive
487  //level--;
488  }
489 
490  printf("} // group %s\n", grp.name);
491  printf("\n");
492  fflush(stdout); // make sure everything has printed
493 }
494 
496  int i;
497 
498  if (grp) {
499 
500  /* dimensions */
501  free_dims_nc(grp->dim);
502 
503  /* variables */
504  free_vars_nc(grp->var, grp->nvars);
505 
506  /* group attributes */
507  free_atts_nc(grp->att, grp->natts);
508 
509  /* subgroups */
510  for (i = 0; i < grp->ngrps; i++)
511  free_grp_nc(&grp->grps[i]); // recursive
512 
513  /* current group */
514  if (grp->grps) {
515  free(grp->grps);
516  grp->grps = NULL;
517  }
518  }
519 
520 }
521 
522 /* ------------------------------------------------------------------ */
void free_dims_nc(dim_str_nc *dim)
Definition: nc4utils.c:147
size_t len
Definition: nc4utils.h:44
int32 value
Definition: Granule.c:1235
#define TRY_NC(file, line, ncstat)
Definition: nc4utils.h:31
int j
Definition: decode_rs.h:73
int find_varid_nc(int ncid, int *varid, const char *varnames[])
Definition: nc4utils.c:407
int status
Definition: l1_czcs_hdf.c:32
#define SUCCESS
Definition: nc4utils.c:6
void check_err(const int stat, const int line, const char *file)
Definition: nc4utils.c:35
dim_str_nc * load_grpdims(int ncid)
Definition: nc4utils.c:109
int grpid
Definition: nc4utils.h:55
void print_grp_nc(grp_str_nc grp)
Definition: nc4utils.c:466
int ndims
Definition: nc4utils.h:70
#define NULL
Definition: decode_rs.h:63
var_str_nc * load_vars_nc(int ncid)
Definition: nc4utils.c:254
int find_dimid_nc(int ncid, int *dimid, const char *dimnames[])
Definition: nc4utils.c:161
char name[NC_MAX_NAME+1]
Definition: nc4utils.h:69
att_str_nc * att
Definition: nc4utils.h:62
char name[NC_MAX_NAME+1]
Definition: nc4utils.h:57
int nvars
Definition: nc4utils.h:74
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
nc_type type
Definition: nc4utils.h:58
size_t nvals
Definition: nc4utils.h:50
int id
Definition: nc4utils.h:68
int load_grp_nc(grp_str_nc *grp)
Definition: nc4utils.c:423
int ndims
Definition: nc4utils.h:59
data_t tmp
Definition: decode_rs.h:74
void report_err(const int stat, const int line, const char *file)
Definition: nc4utils.c:28
int id
Definition: nc4utils.h:56
var_str_nc * find_var_byname_nc(grp_str_nc nc, const char *varname, const char *grpname)
Definition: nc4utils.c:314
struct grp_str_nc * grps
Definition: nc4utils.h:77
void print_atts_nc(att_str_nc *att, int natts, char *varname)
Definition: nc4utils.c:224
char * format_ncval(void *value, nc_type type, size_t nvals)
Definition: nc4utils.c:43
void * data
Definition: nc4utils.h:64
var_str_nc * var
Definition: nc4utils.h:75
void free_grp_nc(grp_str_nc *grp)
Definition: nc4utils.c:495
int ngrps
Definition: nc4utils.h:76
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude data
Definition: HISTORY.txt:356
void print_vars_nc(var_str_nc *var, int nvars)
Definition: nc4utils.c:362
dim_str_nc * dim
Definition: nc4utils.h:60
void free_atts_nc(att_str_nc *att, int natts)
Definition: nc4utils.c:236
att_str_nc * load_atts_nc(int ncid, int varid)
Definition: nc4utils.c:177
nc_type type
Definition: nc4utils.h:49
void * value
Definition: nc4utils.h:51
int32_t nvals
int readall_var(var_str_nc *var)
Definition: nc4utils.c:334
int natts
Definition: nc4utils.h:72
att_str_nc * att
Definition: nc4utils.h:73
#define TRYMEM(file, line, memstat)
Definition: l1_hmodis_hdf.c:23
int i
Definition: decode_rs.h:71
void print_dims_nc(dim_str_nc *dim, int ndims)
Definition: nc4utils.c:139
void free_vars_nc(var_str_nc *var, int nvars)
Definition: nc4utils.c:384
dim_str_nc * dim
Definition: nc4utils.h:71