OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
h5io.c
Go to the documentation of this file.
1 #include "h5io.h"
2 #include <stdlib.h>
3 
4 int h5io_openr(char *file, int opt, h5io_str *id)
5 /*******************************************************************
6 
7  h5io_openr
8 
9  purpose: open a general hdf 5 file for reading (option to write in
10  existing file too)
11 
12  Returns type: int - return status: 0 is good
13  1 if any other error
14 
15  Parameters: (in calling order)
16  Type Name I/O Description
17  ---- ---- --- -----------
18  char * file I name of file to open
19  int32 opt I open option: 0 for standard
20  open with no write, 1 to
21  open to read and write
22  h5io_str * id O id for the opened file
23 
24  Modification history:
25  Programmer Date Description of change
26  ---------- ---- ---------------------
27  W. Robinson, SAIC 23 Sep 2008 Original development
28 
29  *******************************************************************/ {
30  unsigned int open_opt, opt_sel[2] = {H5F_ACC_RDONLY, H5F_ACC_RDWR};
31  htri_t h5ret;
32  H5E_auto_t old_func;
33  void *old_client_data;
34  /*
35  * for the read set proper open value
36  */
37  if ((opt != 0) && (opt != 1)) {
38  printf("%s: Inproper open option selected\n", __FILE__);
39  return 1;
40  }
41  /*
42  * check if file is HDF 5. The H5E calls are to disable / ensble ugly error
43  * reporting if file is not HDF 5 (I know it should not for this, but it does
44  */
45  H5Eget_auto(H5E_DEFAULT, &old_func, &old_client_data);
46  H5Eset_auto(H5E_DEFAULT, NULL, NULL);
47 
48  h5ret = H5Fis_hdf5(file);
49 
50  H5Eset_auto(H5E_DEFAULT, old_func, old_client_data);
51  if (h5ret <= 0) {
52  return 1;
53  }
54  open_opt = opt_sel[ opt ];
55  if ((id->file_id = H5Fopen(file, open_opt, H5P_DEFAULT))
56  < 0) return 1;
57  /*
58  * Also, find the root group associated with the file
59  */
60  if ((id->grp_id = H5Gopen1(id->file_id, "/")) < 0) return 1;
61  /*
62  * file is open
63  */
64  id->type = H5IO_TYP_FILE_ID;
65  return 0;
66 }
67 
68 int h5io_openw(char *file, int opt, h5io_str *id)
69 /*******************************************************************
70 
71  h5io_openw
72 
73  purpose: open a general hdf 5 file for write
74 
75  Returns type: int - return status: 0 is good
76  1 if any other error
77 
78  Parameters: (in calling order)
79  Type Name I/O Description
80  ---- ---- --- -----------
81  char * file I name of file to open
82  int32 opt I open option: 0 for standard
83  open, 1 to overwrite any old
84  file by that name (dangerous)
85  h5io_str * id O id for the opened file
86 
87  Modification history:
88  Programmer Date Description of change
89  ---------- ---- ---------------------
90  W. Robinson, SAIC 23 Sep 2008 Original development
91 
92  *******************************************************************/ {
93  unsigned int open_opt, opt_sel[2] = {H5F_ACC_EXCL, H5F_ACC_TRUNC};
94  /*
95  * for the read set proper open value
96  */
97  if ((opt != 0) && (opt != 1)) {
98  printf("%s: Improper open option selected\n", __FILE__);
99  return 1;
100  }
101  open_opt = opt_sel[ opt ];
102  if ((id->file_id = H5Fcreate(file, open_opt, H5P_DEFAULT, H5P_DEFAULT))
103  < 0) return 1;
104  /*
105  * Also, find the root group associated with the file
106  */
107  if ((id->grp_id = H5Gopen1(id->file_id, "/")) < 0) return 1;
108  /*
109  * file is open
110  */
111  id->type = H5IO_TYP_FILE_ID;
112  return 0;
113 }
114 
115 int h5io_close(h5io_str *id)
116 /*******************************************************************
117 
118  h5io_close
119 
120  purpose: close a h5io id for accessing the file, group, or dataset
121  in the file, this frees the storage associated with the id
122 
123  Returns type: int - return status: 0 is good
124  1 if any other error
125 
126  Parameters: (in calling order)
127  Type Name I/O Description
128  ---- ---- --- -----------
129  h5io_str * id I id to close
130 
131  Modification history:
132  Programmer Date Description of change
133  ---------- ---- ---------------------
134  W. Robinson, SAIC 23 Sep 2008 Original development
135 
136  *******************************************************************/ {
137  /*
138  * based on the type and the read mode, clear storage of the
139  * HDF 5 ID values
140  */
141  switch (id->type) {
142  case H5IO_TYP_FILE_ID:
143  if (H5Fclose(id->file_id) < 0) return 1;
144  if (H5Gclose(id->grp_id) < 0) return 1;
145  break;
146  case H5IO_TYP_GRP_ID:
147  if (H5Gclose(id->grp_id) < 0) return 1;
148  break;
149  case H5IO_TYP_DAT_ID:
150  if (H5Dclose(id->dat_id) < 0) return 1;
151  /*
152  * if the slice read / write mode was used, also close the data
153  * space ids and indicate dataset is not open for slice I/O
154  */
155  if (id->dat_rw_mode == H5IO_DAT_RWSLICE) {
156  if (H5Sclose(id->fil_space_id) < 0) return 1;
157  if (H5Sclose(id->mem_space_id) < 0) return 1;
158  if (H5Tclose(id->native_typ) < 0) return 1;
159  id->dat_rw_mode = H5IO_DAT_RWALL; /* just in case, say not ready */
160  /* for slices */
161  }
162  break;
163  default:
164  printf("%s: Unknown or un-initialized id\n", __FILE__);
165  return 1;
166  }
167  /*
168  * and end
169  */
170  return 0;
171 }
172 
173 int h5io_info(h5io_str *id, char *attr_name, H5T_class_t *class,
174  hid_t *native_typ, int* ndim, int *dim_siz, int *sto_len)
175 /*******************************************************************
176 
177  h5io_info
178 
179  purpose: Get information about a hdf 5 attribute or dataset from the
180  file, group (for attribute), or dataset (for attribute or dataset)
181 
182  Returns type: int - return status: 0 is good
183  1 if any other error
184 
185  Parameters: (in calling order)
186  Type Name I/O Description
187  ---- ---- --- -----------
188  h5io_str * id I id for the opened file,
189  group, or dataset
190  char * attr_name I name of attribute to get
191  If NULL, id must be a dataset
192  and dataset info will be found
193  H5T_class_t * class O class found, see below
194  hid_t * native_typ O the full type of the variable
195  int * ndim O # dimensions of the array
196  int * dim_siz O length of each dimension
197  int * sto_len O storage length in bytes (use
198  to get string length needed)
199 
200  Notes
201  HDF classes ( class )
202  These are the classes or general types of data that can be handled
203  by this package (self descriptive)
204  H5T_INTEGER, H5T_FLOAT, H5T_STRING
205 
206  HDF native type
207  The native type is more descriptive of the data including not only
208  the class, but the size (ie int with 1, 2, 4 bytes)
209  Also, to comlpetely free the storage associated with this, you should
210  do a H5Tclose( native_typ )
211 
212  The common native types are:
213  Code Corresponding C Type
214  ------------------- --------------------
215  H5T_NATIVE_CHAR char
216  H5T_NATIVE_SCHAR signed char
217  H5T_NATIVE_UCHAR unsigned char
218  H5T_NATIVE_SHORT short
219  H5T_NATIVE_USHORT unsigned short
220  H5T_NATIVE_INT int
221  H5T_NATIVE_UINT unsigned
222  H5T_NATIVE_LONG long
223  H5T_NATIVE_ULONG unsigned long
224  H5T_NATIVE_LLONG long long
225  H5T_NATIVE_ULLONG unsigned long long
226  H5T_NATIVE_FLOAT float
227  H5T_NATIVE_DOUBLE double
228  H5T_NATIVE_LDOUBLE long double
229 
230  all information on the types and classes are in the HDF5 Datatypes
231  web page (version 1.6)
232  http://www.hdfgroup.org/HDF5/doc1.6/UG/UG_frame.html.
233 
234  Modification history:
235  Programmer Date Description of change
236  ---------- ---- ---------------------
237  W. Robinson, SAIC 30 Sep 2008 Original development
238  W. Robinson, SAIC 10 Feb 2009 Change test for null attr name to
239  if " == NULL
240 
241  *******************************************************************/ {
242  hid_t *base_grp, spaceid, attr_datyp, attr_id;
243  hsize_t dims[H5IO_MAXDIM], maxdims[H5IO_MAXDIM];
244  size_t lsto_len;
245  int indx;
246  /*
247  * set the proper ID and make sure attribute name is non null for a group
248  */
249  base_grp = (id->type == H5IO_TYP_DAT_ID) ?
250  &(id->dat_id) : &(id->grp_id);
251  if ((id->type != H5IO_TYP_DAT_ID) && (attr_name == NULL)) {
252  printf("%s: no attribute entered for group information query\n",
253  __FILE__);
254  return 1;
255  }
256  if ((id->type == H5IO_TYP_DAT_ID) && (attr_name == NULL)) {
257  /*
258  * dataset and no attribute name - get dataset specific information
259  */
260  if ((spaceid = H5Dget_space(*base_grp)) < 0) return 1;
261  if ((attr_datyp = H5Dget_type(*base_grp)) < 0) return 1;
262  } else {
263  /*
264  * We have an attribute to open and get specific information
265  */
266  if ((attr_id = H5Aopen_name(*base_grp, attr_name)) < 0) return 1;
267  if ((spaceid = H5Aget_space(attr_id)) < 0) return 1;
268  if ((attr_datyp = H5Aget_type(attr_id)) < 0) return 1;
269  }
270  /*
271  * get the data size, class (basic type), and naitve data type
272  */
273  if ((*ndim = H5Sget_simple_extent_dims(spaceid, dims, maxdims)) < 0)
274  return 1;
275  if (*ndim > H5IO_MAXDIM) {
276  printf("%s: # dimensions of attribute: %s is > software maximum of %d\n",
277  __FILE__, attr_name, H5IO_MAXDIM);
278  return 1;
279  }
280  for (indx = 0; indx < *ndim; indx++)
281  dim_siz[indx] = dims[indx];
282  if ((*native_typ = H5Tget_native_type(attr_datyp, H5T_DIR_ASCEND)) < 0)
283  return 1;
284  if ((*class = H5Tget_class(attr_datyp)) == -1) return 1;
285  if ((lsto_len = H5Tget_size(attr_datyp)) <= 0) return 1;
286  *sto_len = lsto_len;
287  /* that's all there is to know, close the stuff */
288 
289  /*
290  * based on the class, read the data in
291  */
292  switch (*class) {
293  case H5T_STRING:
294  case H5T_INTEGER:
295  case H5T_FLOAT:
296  break;
297  case H5T_TIME:
298  case H5T_BITFIELD:
299  case H5T_OPAQUE:
300  case H5T_COMPOUND:
301  case H5T_REFERENCE:
302  case H5T_ENUM:
303  case H5T_VLEN:
304  case H5T_ARRAY:
305  printf("%s: Currently, classes beyond STRING, INTEGER, and FLOAT \n",
306  "may not be fully characterized here\n");
307  break;
308  default:
309  printf("%s: Unable to handle the class for attribute: %s\n",
310  __FILE__, attr_name);
311  return 1;
312  break;
313  }
314  /*
315  * close the allocated spaces before leaving
316  */
317  if (H5Sclose(spaceid) < 0) return 1;
318  if (H5Tclose(attr_datyp) < 0) return 1;
319  if (attr_name != NULL)
320  if (H5Aclose(attr_id) < 0) return 1;
321  return 0;
322 }
323 
324 int h5io_set_ds(h5io_str *id, char *path_name, h5io_str *ds_id)
325 /*******************************************************************
326 
327  h5io_rd_attr
328 
329  purpose: get the access to a particular dataset
330 
331  Returns type: int - return status: 0 is good
332  1 if any other error
333 
334  Parameters: (in calling order)
335  Type Name I/O Description
336  ---- ---- --- -----------
337  h5io_str * id I id for the opened file,
338  or group
339  char * path_name I path to set from current
340  location with the dataset name
341  as the last part of the path
342  h5io_str * ds_id O id of the dataset found
343 
344  Modification history:
345  Programmer Date Description of change
346  ---------- ---- ---------------------
347  W. Robinson, SAIC 25 Sep 2008 Original development
348 
349  *******************************************************************/ {
350  /*
351  * make sure the incoming id is OK
352  */
353  if (id->type == H5IO_TYP_DAT_ID) {
354  printf("%s: Cannot set to a dataset under a dataset\n", __FILE__);
355  return 1;
356  }
357  /*
358  * just find the id of the dataset
359  */
360  if ((ds_id->dat_id = H5Dopen1(id->grp_id, path_name)) < 0) return 1;
361  /*
362  * and set type for a group id and default to entire data array read
363  */
364  ds_id->type = H5IO_TYP_DAT_ID;
365  ds_id->dat_rw_mode = H5IO_DAT_RWALL;
366  return 0;
367 }
368 
369 int h5io_set_grp(h5io_str *id, char *path_name, h5io_str *grp_id)
370 /*******************************************************************
371 
372  h5io_rd_attr
373 
374  purpose: get the access to a particular group
375 
376  Returns type: int - return status: 0 is good
377  1 if any other error
378 
379  Parameters: (in calling order)
380  Type Name I/O Description
381  ---- ---- --- -----------
382  h5io_str * id I id for the opened file,
383  or group
384  char * path_name I path to set from current
385  location
386  h5io_str * grp_id O id of the group found
387 
388  Modification history:
389  Programmer Date Description of change
390  ---------- ---- ---------------------
391  W. Robinson, SAIC 25 Sep 2008 Original development
392 
393  *******************************************************************/ {
394  /*
395  * make sure the incoming id is OK
396  */
397  if (id->type == H5IO_TYP_DAT_ID) {
398  printf("%s: Cannot set group under a dataset\n", __FILE__);
399  return 1;
400  }
401  /*
402  * just find the id of the group
403  */
404  if ((grp_id->grp_id = H5Gopen1(id->grp_id, path_name)) < 0) return 1;
405  /*
406  * and set type for a group id
407  */
408  grp_id->type = H5IO_TYP_GRP_ID;
409  return 0;
410 }
411 
412 int h5io_rd_attr(h5io_str *id, char *attr_name, void *data)
413 /*******************************************************************
414 
415  h5io_rd_attr
416 
417  purpose: read a hdf 5 attribute from the file, group, or dataset
418 
419  Returns type: int - return status: 0 is good
420  1 if any other error
421 
422  Parameters: (in calling order)
423  Type Name I/O Description
424  ---- ---- --- -----------
425  h5io_str * id I id for the opened file,
426  group, or dataset
427  char * attr_name I name of attribute to get
428  void * data O pointer to space made for
429  the data
430 
431  Modification history:
432  Programmer Date Description of change
433  ---------- ---- ---------------------
434  W. Robinson, SAIC 23 Sep 2008 Original development
435 
436  *******************************************************************/ {
437  hid_t *base_grp, spaceid, attr_datyp, attr_id, native_typ;
438  hsize_t dims[H5IO_MAXDIM], maxdims[H5IO_MAXDIM];
439  H5T_class_t d_class;
440  int ndim, nval, idim;
441  /*
442  * open the attribute
443  */
444  base_grp = (id->type == H5IO_TYP_DAT_ID) ?
445  &(id->dat_id) : &(id->grp_id);
446  if ((attr_id = H5Aopen_name(*base_grp, attr_name)) < 0) return 1;
447  /*
448  * get the data size, class (basic type), and naitve data type
449  */
450  if ((spaceid = H5Aget_space(attr_id)) < 0) return 1;
451  if ((ndim = H5Sget_simple_extent_dims(spaceid, dims, maxdims)) < 0)
452  return 1;
453  if (ndim > H5IO_MAXDIM) {
454  printf("%s: # dimensions of attribute: %s is > software maximum of %d\n",
455  __FILE__, attr_name, H5IO_MAXDIM);
456  return 1;
457  }
458  if ((attr_datyp = H5Aget_type(attr_id)) < 0) return 1;
459  if ((d_class = H5Tget_class(attr_datyp)) == -1) return 1;
460  if ((native_typ = H5Tget_native_type(attr_datyp, H5T_DIR_ASCEND)) < 0)
461  return 1;
462 
463  nval = 1;
464  idim = 0;
465  if (ndim > 0) {
466  while (idim < ndim)
467  nval *= dims[idim++];
468  }
469  /*
470  * based on the class, read the data in
471  */
472  switch (d_class) {
473  case H5T_STRING:
474  if (H5Aread(attr_id, native_typ, data) < 0) return 1;
475  hsize_t length = H5Aget_storage_size(attr_id);
476  ((char *) data)[length] = 0;
477  break;
478  case H5T_INTEGER:
479  case H5T_FLOAT:
480  if (H5Aread(attr_id, native_typ, data) < 0) return 1;
481  break;
482  case H5T_TIME:
483  case H5T_BITFIELD:
484  case H5T_OPAQUE:
485  case H5T_COMPOUND:
486  case H5T_REFERENCE:
487  case H5T_ENUM:
488  case H5T_VLEN:
489  case H5T_ARRAY:
490  default:
491  printf("Unable to handle the class for attribute: %s\n", attr_name);
492  return 1;
493  break;
494  }
495  /*
496  * close the allocated spaces before leaving
497  */
498  if (H5Sclose(spaceid) < 0) return 1;
499  if (H5Aclose(attr_id) < 0) return 1;
500  if (H5Tclose(attr_datyp) < 0) return 1;
501  if (H5Tclose(native_typ) < 0) return 1;
502  return 0;
503 }
504 
505 int h5io_rd_ds(h5io_str *ds_id, void *data)
506 /*******************************************************************
507 
508  h5io_rd_ds
509 
510  purpose: read an entire dataset into an array
511 
512  Returns type: int - return status: 0 is good
513  1 if any other error
514 
515  Parameters: (in calling order)
516  Type Name I/O Description
517  ---- ---- --- -----------
518  h5io_str * ds_id I id for the dataset in the file
519  void * data O allocated space for the data
520  to be read into
521 
522  Modification history:
523  Programmer Date Description of change
524  ---------- ---- ---------------------
525  W. Robinson, SAIC 25 Sep 2008 Original development
526 
527  *******************************************************************/ {
528  hid_t spaceid, ds_datyp, native_typ;
529  hsize_t dims[H5IO_MAXDIM], maxdims[H5IO_MAXDIM];
530  H5T_class_t d_class;
531  int ndim, nval, idim;
532  /*
533  * make sure the incoming id is OK - it must be s dataset
534  */
535  if (ds_id->type != H5IO_TYP_DAT_ID) {
536  printf("%s: A dataset id must be passed in for this routine\n", __FILE__);
537  return 1;
538  }
539  /*
540  * The code here is very similar to the h5io_rd_attr code
541  * get the data size, class (basic type), and naitve data type
542  */
543  if ((spaceid = H5Dget_space(ds_id->dat_id)) < 0) return 1;
544  if ((ndim = H5Sget_simple_extent_dims(spaceid, dims, maxdims)) < 0)
545  return 1;
546  if (ndim > H5IO_MAXDIM) {
547  printf("%s: # dimensions of dataset is > software maximum of %d\n",
548  __FILE__, H5IO_MAXDIM);
549  return 1;
550  }
551  if ((ds_datyp = H5Dget_type(ds_id->dat_id)) < 0) return 1;
552  if ((d_class = H5Tget_class(ds_datyp)) == -1) return 1;
553  if ((native_typ = H5Tget_native_type(ds_datyp, H5T_DIR_ASCEND)) < 0)
554  return 1;
555 
556  nval = 1;
557  idim = 0;
558  if (ndim > 0) {
559  while (idim < ndim)
560  nval *= dims[idim++];
561  }
562  /*
563  * based on the class, read the data in
564  */
565  switch (d_class) {
566  case H5T_STRING:
567  if (nval == 0) {
568  if (H5Dread(ds_id->dat_id, native_typ, H5S_ALL, H5S_ALL,
569  H5P_DEFAULT, data) < 0) return 1;
570  } else {
571  if (H5Dread(ds_id->dat_id, native_typ, H5S_ALL, H5S_ALL,
572  H5P_DEFAULT, data) < 0) return 1;
573  }
574  break;
575  case H5T_INTEGER:
576  case H5T_FLOAT:
577  if (H5Dread(ds_id->dat_id, native_typ, H5S_ALL, H5S_ALL,
578  H5P_DEFAULT, data) < 0) return 1;
579  break;
580  case H5T_TIME:
581  case H5T_BITFIELD:
582  case H5T_OPAQUE:
583  case H5T_COMPOUND:
584  case H5T_REFERENCE:
585  case H5T_ENUM:
586  case H5T_VLEN:
587  case H5T_ARRAY:
588  default:
589  printf("Unable to handle the class for dataset\n");
590  return 1;
591  break;
592  }
593  /*
594  * close the allocated spaces before leaving
595  */
596  if (H5Sclose(spaceid) < 0) return 1;
597  if (H5Tclose(ds_datyp) < 0) return 1;
598  if (H5Tclose(native_typ) < 0) return 1;
599  return 0;
600 }
601 
602 int h5io_rd_ds_slice(h5io_str *ds_id, int *start, int *count, void *data)
603 /*******************************************************************
604 
605  h5io_rd_ds
606 
607  purpose: read a slice from a dataset into an array
608 
609  Returns type: int - return status: 0 is good
610  1 if any other error
611 
612  Parameters: (in calling order)
613  Type Name I/O Description
614  ---- ---- --- -----------
615  h5io_str * ds_id I id for the dataset in the file
616  int * start I Start (0 origin) of slice to
617  read, covers all array dims
618  int * count I how many items to read in
619  each dimension
620  void * data O allocated space for the data
621  to be read into
622 
623  Modification history:
624  Programmer Date Description of change
625  ---------- ---- ---------------------
626  W. Robinson, SAIC 25 Sep 2008 Original development
627 
628  Note that when called, this routine will set up the HDF 5 I/O needed
629  and will save settings for subsequent calls. If the slice size
630  (count) stays the same, minimal changes are made to permit this.
631  closing the dataset ID will unset these settings and free the space
632  needed for the slice I/O (unlike h5io_rd_ds, which does a 1-time
633  read of the data needed)
634 
635  *******************************************************************/ {
636  hsize_t dims[H5IO_MAXDIM], maxdims[H5IO_MAXDIM], dim_arr_mem[H5IO_MAXDIM];
637  hsize_t lstart[H5IO_MAXDIM], lcount[H5IO_MAXDIM];
638  hsize_t block[H5IO_MAXDIM], stride[H5IO_MAXDIM];
639  H5T_class_t d_class;
640  hid_t ds_datyp;
641  int changed_count, indx;
642  /*
643  * make sure the incoming id is OK - it must be a dataset
644  */
645  if (ds_id->type != H5IO_TYP_DAT_ID) {
646  printf("%s: A dataset id must be passed in for this routine\n", __FILE__);
647  return 1;
648  }
649  /*
650  * If this is the initial slice read, we need to set up for the read
651  */
652  if (ds_id->dat_rw_mode == H5IO_DAT_RWALL) {
653  /*
654  * initial read of a slice do all the checks and set up as in h5io_rd_ds
655  * but additionally set up the range of the memory space (file space
656  * range is variable for each slice so set it further on
657  */
658  if ((ds_id->fil_space_id = H5Dget_space(ds_id->dat_id)) < 0) return 1;
659  if ((ds_id->prev_ndim =
660  H5Sget_simple_extent_dims(ds_id->fil_space_id, dims, maxdims)) < 0)
661  return 1;
662  if (ds_id->prev_ndim > H5IO_MAXDIM) {
663  printf("%s: # dimensions of dataset is > software maximum of %d\n",
664  __FILE__, H5IO_MAXDIM);
665  return 1;
666  }
667  if ((ds_datyp = H5Dget_type(ds_id->dat_id)) < 0) return 1;
668  if ((d_class = H5Tget_class(ds_datyp)) == -1) return 1;
669  if ((ds_id->native_typ =
670  H5Tget_native_type(ds_datyp, H5T_DIR_ASCEND)) < 0)
671  return 1;
672  /*
673  * the data type is no longer of use
674  */
675  if (H5Tclose(ds_datyp) < 0) return 1;
676  /*
677  * check that the class is a readable one
678  */
679  switch (d_class) {
680  case H5T_INTEGER:
681  case H5T_FLOAT:
682  break;
683  case H5T_STRING:
684  case H5T_TIME:
685  case H5T_BITFIELD:
686  case H5T_OPAQUE:
687  case H5T_COMPOUND:
688  case H5T_REFERENCE:
689  case H5T_ENUM:
690  case H5T_VLEN:
691  case H5T_ARRAY:
692  default:
693  printf("Unable to handle the class for dataset\n");
694  return 1;
695  break;
696  }
697  /*
698  * set space size for memory (will usually not change)
699  */
700  for (indx = 0; indx < ds_id->prev_ndim; indx++) {
701  dim_arr_mem[indx] = *(count + indx);
702  *(ds_id->prev_count + indx) = *(count + indx);
703  lstart[indx] = 0;
704  block[indx] = 1;
705  stride[indx] = 1;
706  lcount[indx] = *(count + indx);
707  }
708  if ((ds_id->mem_space_id =
709  H5Screate_simple(ds_id->prev_ndim, dim_arr_mem, dim_arr_mem)) < 0)
710  return 1;
711  /* */
712  if (H5Sselect_hyperslab(ds_id->mem_space_id, H5S_SELECT_SET,
713  lstart, stride, lcount, block) < 0) return 1;
714  /*
715  * create space descriptor for file (set sub-area later)
716  */
717  if ((ds_id->fil_space_id = H5Dget_space(ds_id->dat_id)) < 0) return 1;
718  /*
719  * initialization over, say so
720  */
721  ds_id->dat_rw_mode = H5IO_DAT_RWSLICE;
722  }
723  /*
724  *
725  * If the count (slice size) was changed from the previous call, deal
726  * with that here
727  */
728  changed_count = 0;
729  for (indx = 0; indx < ds_id->prev_ndim; indx++)
730  if (*(count + indx) != *(ds_id->prev_count + indx))
731  changed_count = 1;
732  /* */
733  if (changed_count == 1) {
734  /*
735  * since the slice size changed, re-set the space for memory
736  */
737  if (H5Sclose(ds_id->mem_space_id) < 0) return 1;
738  /* */
739  for (indx = 0; indx < ds_id->prev_ndim; indx++) {
740  dim_arr_mem[indx] = *(count + indx);
741  *(ds_id->prev_count + indx) = *(count + indx);
742  lstart[indx] = 0;
743  block[indx] = 1;
744  stride[indx] = 1;
745  lcount[indx] = *(count + indx);
746  }
747  if ((ds_id->mem_space_id =
748  H5Screate_simple(ds_id->prev_ndim, dim_arr_mem, dim_arr_mem)) < 0)
749  return 1;
750  /* */
751  if (H5Sselect_hyperslab(ds_id->mem_space_id, H5S_SELECT_SET,
752  lstart, stride, lcount, block) < 0) return 1;
753  }
754  /*
755  *
756  * for each slice read, select the file slice to read
757  */
758  for (indx = 0; indx < ds_id->prev_ndim; indx++) {
759  lstart[indx] = *(start + indx);
760  ;
761  block[indx] = 1;
762  stride[indx] = 1;
763  lcount[indx] = *(count + indx);
764  }
765  if (H5Sselect_hyperslab(ds_id->fil_space_id, H5S_SELECT_SET,
766  lstart, stride, lcount, block) < 0) return 1;
767  /*
768  * and read it
769  */
770  if (H5Dread(ds_id->dat_id, ds_id->native_typ, ds_id->mem_space_id,
771  ds_id->fil_space_id, H5P_DEFAULT, (void *) data) < 0) return 1;
772  /*
773  * and finish
774  */
775  return 0;
776 }
777 
778 int h5io_mk_grp(h5io_str *id, char *grp_nam, h5io_str *grp_id)
779 /*******************************************************************
780 
781  h5io_mk_grp
782 
783  purpose: Create a group in an HDF 5 file
784 
785  Returns type: int - return status: 0 is good
786  1 if any other error
787 
788  Parameters: (in calling order)
789  Type Name I/O Description
790  ---- ---- --- -----------
791  h5io_str * id I id for the opened file,
792  or group
793  char * grp_nam I new group name to create
794  h5io_str * grp_id O id of the new group
795 
796  Modification history:
797  Programmer Date Description of change
798  ---------- ---- ---------------------
799  W. Robinson, SAIC 29 Sep 2008 Original development
800 
801  *******************************************************************/ {
802  /*
803  * make sure the incoming id is OK
804  */
805  if (id->type == H5IO_TYP_DAT_ID) {
806  printf("%s: Cannot set group under a dataset\n", __FILE__);
807  return 1;
808  }
809  /*
810  * just find the id of the group
811  */
812  if ((grp_id->grp_id = H5Gcreate1(id->grp_id, grp_nam, 0)) < 0)
813  return 1;
814  /*
815  * and set type for a group id
816  */
817  grp_id->type = H5IO_TYP_GRP_ID;
818  return 0;
819 }
820 
821 int h5io_mk_ds(h5io_str *id, char *ds_name, hid_t type, int ndim,
822  int *dim_siz, h5io_str *ds_id)
823 /*******************************************************************
824 
825  h5io_mk_ds
826 
827  purpose: Create a dataset in a HDF file
828 
829  Returns type: int - return status: 0 is good
830  1 if any other error
831 
832  Parameters: (in calling order)
833  Type Name I/O Description
834  ---- ---- --- -----------
835  h5io_str * id I id for the opened file,
836  or group
837  char * ds_name I name of dataset to create
838  hid_t type I type of the data to be created
839  (see below for more)
840  int ndim I number of dimensions of
841  data array to store
842  int * dim_siz I array of size ndim containing
843  each dimension's length in
844  elements
845  h5io_str * ds_id O id of the dataset created
846 
847  Notes
848  More on type - I hate to bring this HDF 5 value up, but this is an
849  HDF 5 descriptor of one of the standard types used. Ususlly,
850  pre-defined native computer types can be used. other types are also
851  available. All the types can be seen in the HDF5 Datatypes web page
852  (version 1.6)
853  http://www.hdfgroup.org/HDF5/doc1.6/UG/UG_frame.html.
854 
855  The common native types are:
856  Code Corresponding C Type
857  ------------------- --------------------
858  H5T_NATIVE_CHAR char
859  H5T_NATIVE_SCHAR signed char
860  H5T_NATIVE_UCHAR unsigned char
861  H5T_NATIVE_SHORT short
862  H5T_NATIVE_USHORT unsigned short
863  H5T_NATIVE_INT int
864  H5T_NATIVE_UINT unsigned
865  H5T_NATIVE_LONG long
866  H5T_NATIVE_ULONG unsigned long
867  H5T_NATIVE_LLONG long long
868  H5T_NATIVE_ULLONG unsigned long long
869  H5T_NATIVE_FLOAT float
870  H5T_NATIVE_DOUBLE double
871  H5T_NATIVE_LDOUBLE long double
872 
873  Placing of strings is probably done in an entirely different way
874  not handled here (this should be rare normally for datasets)
875 
876  Modification history:
877  Programmer Date Description of change
878  ---------- ---- ---------------------
879  W. Robinson, SAIC 29 Sep 2008 Original development
880 
881  *******************************************************************/ {
882  int idim;
883  hsize_t ldim_siz[H5IO_MAXDIM];
884  hid_t fil_space_id;
885  /*
886  * make sure the incoming id is OK
887  */
888  if (id->type == H5IO_TYP_DAT_ID) {
889  printf("%s: Cannot create a dataset under a dataset\n", __FILE__);
890  return 1;
891  }
892  /*
893  * check inputs and transfer
894  */
895  if (ndim > H5IO_MAXDIM) {
896  printf("%s: The created dataset cannot currently exceed %d dimensions\n",
897  __FILE__, H5IO_MAXDIM);
898  return 1;
899  }
900  for (idim = 0; idim < ndim; idim++)
901  ldim_siz[idim] = dim_siz[idim];
902  /*
903  * set up the file's data space
904  */
905  if ((fil_space_id = H5Screate_simple(ndim, ldim_siz, ldim_siz)) < 0)
906  return 1;
907  /*
908  * just find the id of the dataset
909  */
910  if ((ds_id->dat_id = H5Dcreate1(id->grp_id, ds_name, type,
911  fil_space_id, H5P_DEFAULT)) < 0) return 1;
912  /*
913  * and set type for a data id, default to entire data array read,
914  * and free the space id for now
915  */
916  ds_id->type = H5IO_TYP_DAT_ID;
917  ds_id->dat_rw_mode = H5IO_DAT_RWALL;
918  if (H5Sclose(fil_space_id) < 0) return 1;
919  return 0;
920 }
921 
922 int h5io_wr_attr(h5io_str *id, char *attr_name, hid_t out_type,
923  int ndim, int *dim_siz, void *data)
924 /*******************************************************************
925 
926  h5io_wr_attr
927 
928  purpose: write data as an attribute to a hdf 5 file, group, or dataset
929  Note that for strings, use h5io_wr_attr_str
930 
931  Returns type: int - return status: 0 is good
932  1 if any other error
933 
934  Parameters: (in calling order)
935  Type Name I/O Description
936  ---- ---- --- -----------
937  h5io_str * id I id for the opened file,
938  group, or dataset
939  char * attr_name I name of attribute to get
940  hid_t out_type I type of the data to be created
941  (see h5io_mk_ds for more on
942  type)
943  The type being written is
944  assumed to be the same
945  general type (ie float, short)
946  int ndim I number of dimensions of
947  data array to store if 0,
948  store 1 value as a scalar
949  int * dim_siz I array of size ndim containing
950  each dimension's length in
951  elements (ignored if ndim = 0)
952  void * data I pointer to space made for
953  the data
954 
955  Modification history:
956  Programmer Date Description of change
957  ---------- ---- ---------------------
958  W. Robinson, SAIC 29 Sep 2008 Original development
959 
960  *******************************************************************/ {
961  hid_t *base_grp, fil_spac_id, attr_id, native_type;
962  hsize_t ldim_siz[H5IO_MAXDIM];
963  int idim;
964  /*
965  * make sure the # dims is OK
966  */
967  if (ndim > H5IO_MAXDIM) {
968  printf("%s: The created dataset cannot currently exceed %d dimensions\n",
969  __FILE__, H5IO_MAXDIM);
970  return 1;
971  }
972  /*
973  * depending on array vs scalar, set the file space
974  */
975  if (ndim == 0) {
976  if ((fil_spac_id = H5Screate(H5S_SCALAR)) < 0) return 1;
977  } else {
978  for (idim = 0; idim < ndim; idim++)
979  ldim_siz[idim] = dim_siz[idim];
980  if ((fil_spac_id = H5Screate_simple(ndim, ldim_siz, ldim_siz)) < 0)
981  return 1;
982  }
983  /*
984  * create the attribute
985  */
986  base_grp = (id->type == H5IO_TYP_DAT_ID) ?
987  &(id->dat_id) : &(id->grp_id);
988  if ((attr_id = H5Acreate1(*base_grp, attr_name, out_type, fil_spac_id,
989  H5P_DEFAULT)) < 0) return 1;
990 
991  if ((native_type = H5Tget_native_type(out_type, H5T_DIR_ASCEND)) < 0)
992  return 1;
993  /*
994  * write data out
995  */
996  if (H5Awrite(attr_id, native_type, data) < 0) return 1;
997  /*
998  * close the allocated spaces before leaving
999  */
1000  if (H5Aclose(attr_id) < 0) return 1;
1001  if (H5Sclose(fil_spac_id) < 0) return 1;
1002  if (H5Tclose(native_type) < 0) return 1;
1003  return 0;
1004 }
1005 
1006 int h5io_wr_attr_str(h5io_str *id, char *attr_name, int ndim, int *dim_siz, int str_len, char *data)
1007 /*******************************************************************
1008 
1009  h5io_wr_attr_str
1010 
1011  purpose: write a string (or array of strings) to a hdf 5 attribute in
1012  a file, group, or dataset
1013  Note that for non-strings, use h5io_wr_attr
1014 
1015  Returns type: int - return status: 0 is good
1016  1 if any other error
1017 
1018  Parameters: (in calling order)
1019  Type Name I/O Description
1020  ---- ---- --- -----------
1021  h5io_str * id I id for the opened file,
1022  group, or dataset
1023  char * attr_name I name to give the attribute
1024  int ndim I number of dimensions of
1025  data array to store if 0,
1026  store 1 value as a scalar
1027  int * dim_siz I array of size ndim containing
1028  each dimension's length in
1029  elements (ignored if ndim = 0)
1030  int str_len I length of string(s) - this
1031  is required for an array,
1032  but for ndim = 0 (scalar),
1033  if this is <= 0, the size
1034  will be computed with strlen()
1035  char * data O pointer to space made for
1036  the data
1037 
1038  Modification history:
1039  Programmer Date Description of change
1040  ---------- ---- ---------------------
1041  W. Robinson, SAIC 29 Sep 2008 Original development
1042 
1043  *******************************************************************/ {
1044  hid_t *base_grp, fil_spac_id, attr_id, attr_typ;
1045  hsize_t ldim_siz[H5IO_MAXDIM];
1046  size_t lstr_len;
1047  int idim;
1048  /*
1049  * make sure the # dims is OK
1050  */
1051  if (ndim > H5IO_MAXDIM) {
1052  printf("%s: The created dataset cannot currently exceed %d dimensions\n",
1053  __FILE__, H5IO_MAXDIM);
1054  return 1;
1055  }
1056  /*
1057  * depending on array vs scalar, set the file space
1058  */
1059  if (ndim == 0) {
1060  if ((fil_spac_id = H5Screate(H5S_SCALAR)) < 0) return 1;
1061  lstr_len = (str_len <= 0) ? strlen(data) : str_len;
1062  } else {
1063  for (idim = 0; idim < ndim; idim++)
1064  ldim_siz[idim] = dim_siz[idim];
1065  lstr_len = str_len;
1066  if ((fil_spac_id = H5Screate_simple(ndim, ldim_siz, ldim_siz)) < 0)
1067  return 1;
1068  }
1069  /*
1070  * create the attribute
1071  */
1072  base_grp = (id->type == H5IO_TYP_DAT_ID) ?
1073  &(id->dat_id) : &(id->grp_id);
1074 
1075  if ((attr_typ = H5Tcopy(H5T_C_S1)) < 0) return 1;
1076  if (H5Tset_size(attr_typ, lstr_len) < 0) return 1;
1077  if (H5Tset_strpad(attr_typ, H5T_STR_NULLTERM) < 0) return 1;
1078 
1079  if ((attr_id = H5Acreate1(*base_grp, attr_name, attr_typ, fil_spac_id,
1080  H5P_DEFAULT)) < 0) return 1;
1081  /*
1082  * write data out
1083  */
1084  if (H5Awrite(attr_id, attr_typ, (void *) data) < 0) return 1;
1085  /*
1086  * close the allocated spaces before leaving
1087  */
1088  if (H5Aclose(attr_id) < 0) return 1;
1089  if (H5Sclose(fil_spac_id) < 0) return 1;
1090  if (H5Tclose(attr_typ) < 0) return 1;
1091  return 0;
1092 }
1093 
1094 int h5io_wr_ds(h5io_str *ds_id, void *data)
1095 /*******************************************************************
1096 
1097  h5io_wr_ds
1098 
1099  purpose: write an entire array into a HDF 5 dataset
1100 
1101  Returns type: int - return status: 0 is good
1102  1 if any other error
1103 
1104  Parameters: (in calling order)
1105  Type Name I/O Description
1106  ---- ---- --- -----------
1107  h5io_str * ds_id I id for the dataset in the file
1108  void * data O allocated space for the data
1109  to be read into
1110 
1111  Modification history:
1112  Programmer Date Description of change
1113  ---------- ---- ---------------------
1114  W. Robinson, SAIC 30 Sep 2008 Original development
1115 
1116  *******************************************************************/ {
1117  hid_t spaceid, ds_datyp, native_typ;
1118  hsize_t dims[H5IO_MAXDIM], maxdims[H5IO_MAXDIM];
1119  H5T_class_t d_class;
1120  int ndim;
1121  /*
1122  * make sure the incoming id is OK - it must be a dataset
1123  */
1124  if (ds_id->type != H5IO_TYP_DAT_ID) {
1125  printf("%s: A dataset id must be passed in for this routine\n", __FILE__);
1126  return 1;
1127  }
1128  /*
1129  * just get the information on dimensions from the previously created space
1130  */
1131  if ((spaceid = H5Dget_space(ds_id->dat_id)) < 0) return 1;
1132  if ((ndim = H5Sget_simple_extent_dims(spaceid, dims, maxdims)) < 0)
1133  return 1;
1134  if (ndim > H5IO_MAXDIM) {
1135  printf("%s: # dimensions of dataset is > software maximum of %d\n",
1136  __FILE__, H5IO_MAXDIM);
1137  return 1;
1138  }
1139  if ((ds_datyp = H5Dget_type(ds_id->dat_id)) < 0) return 1;
1140  if ((d_class = H5Tget_class(ds_datyp)) == -1) return 1;
1141  if ((native_typ = H5Tget_native_type(ds_datyp, H5T_DIR_ASCEND)) < 0)
1142  return 1;
1143  /*
1144  * check the class and write if int or float
1145  */
1146  switch (d_class) {
1147  case H5T_INTEGER:
1148  case H5T_FLOAT:
1149  if (H5Dwrite(ds_id->dat_id, native_typ, H5S_ALL, H5S_ALL,
1150  H5P_DEFAULT, data) < 0) return 1;
1151  break;
1152  case H5T_STRING:
1153  case H5T_TIME:
1154  case H5T_BITFIELD:
1155  case H5T_OPAQUE:
1156  case H5T_COMPOUND:
1157  case H5T_REFERENCE:
1158  case H5T_ENUM:
1159  case H5T_VLEN:
1160  case H5T_ARRAY:
1161  default:
1162  printf("Unable to handle the current class for dataset\n");
1163  return 1;
1164  break;
1165  }
1166  /*
1167  * close the allocated spaces before leaving
1168  */
1169  if (H5Sclose(spaceid) < 0) return 1;
1170  if (H5Tclose(ds_datyp) < 0) return 1;
1171  if (H5Tclose(native_typ) < 0) return 1;
1172  return 0;
1173 }
1174 
1175 int h5io_wr_ds_slice(h5io_str *ds_id, int *start, int *count, void *data)
1176 /*******************************************************************
1177 
1178  h5io_rd_ds
1179 
1180  purpose: write a slice to a dataset from an array
1181  similar to the read slice routine, h5io_rd_ds_slice
1182 
1183  Returns type: int - return status: 0 is good
1184  1 if any other error
1185 
1186  Parameters: (in calling order)
1187  Type Name I/O Description
1188  ---- ---- --- -----------
1189  h5io_str * ds_id I id for the dataset in the file
1190  void * data O data array to write
1191 
1192  Modification history:
1193  Programmer Date Description of change
1194  ---------- ---- ---------------------
1195  W. Robinson, SAIC 30 Sep 2008 Original development
1196 
1197  Note that when called, this routine will set up the HDF 5 I/O needed
1198  and will save settings for subsequent calls. If the slice size
1199  (count) stays the same, minimal changes are made to permit this.
1200  closeing the dataset ID will unset these settings and free the space
1201  needed for the slice I/O (unlike h5io_rd_ds, which does a 1-time
1202  read of the data needed)
1203 
1204  *******************************************************************/ {
1205  hsize_t dims[H5IO_MAXDIM], maxdims[H5IO_MAXDIM], dim_arr_mem[H5IO_MAXDIM];
1206  hsize_t lstart[H5IO_MAXDIM], lcount[H5IO_MAXDIM];
1207  hsize_t block[H5IO_MAXDIM], stride[H5IO_MAXDIM];
1208  H5T_class_t d_class;
1209  hid_t ds_datyp;
1210  int changed_count, indx;
1211  /*
1212  * make sure the incoming id is OK - it must be a dataset
1213  */
1214  if (ds_id->type != H5IO_TYP_DAT_ID) {
1215  printf("%s: A dataset id must be passed in for this routine\n", __FILE__);
1216  return 1;
1217  }
1218  /*
1219  *
1220  * If this is the initial slice write, we need to do the set up for it
1221  */
1222  if (ds_id->dat_rw_mode == H5IO_DAT_RWALL) {
1223  /*
1224  * initial write of a slice - do all the checks and set up as in h5io_wr_ds
1225  * but additionally set up the range of the memory space (file space
1226  * range is variable for each slice so set it further on)
1227  */
1228  if ((ds_id->fil_space_id = H5Dget_space(ds_id->dat_id)) < 0) return 1;
1229  if ((ds_id->prev_ndim =
1230  H5Sget_simple_extent_dims(ds_id->fil_space_id, dims, maxdims)) < 0)
1231  return 1;
1232  if (ds_id->prev_ndim > H5IO_MAXDIM) {
1233  printf("%s: # dimensions of dataset is > software maximum of %d\n",
1234  __FILE__, H5IO_MAXDIM);
1235  return 1;
1236  }
1237  if ((ds_datyp = H5Dget_type(ds_id->dat_id)) < 0) return 1;
1238  if ((d_class = H5Tget_class(ds_datyp)) == -1) return 1;
1239  if ((ds_id->native_typ =
1240  H5Tget_native_type(ds_datyp, H5T_DIR_ASCEND)) < 0)
1241  return 1;
1242  /*
1243  * the data type is no longer of use
1244  */
1245  if (H5Tclose(ds_datyp) < 0) return 1;
1246  /*
1247  * check that the class is a readable one
1248  */
1249  switch (d_class) {
1250  case H5T_INTEGER:
1251  case H5T_FLOAT:
1252  break;
1253  case H5T_STRING:
1254  case H5T_TIME:
1255  case H5T_BITFIELD:
1256  case H5T_OPAQUE:
1257  case H5T_COMPOUND:
1258  case H5T_REFERENCE:
1259  case H5T_ENUM:
1260  case H5T_VLEN:
1261  case H5T_ARRAY:
1262  default:
1263  printf("Unable to handle the class for dataset\n");
1264  return 1;
1265  break;
1266  }
1267  /*
1268  * set space size for memory (will usually not change)
1269  */
1270  for (indx = 0; indx < ds_id->prev_ndim; indx++) {
1271  dim_arr_mem[indx] = *(count + indx);
1272  *(ds_id->prev_count + indx) = *(count + indx);
1273  lstart[indx] = 0;
1274  block[indx] = 1;
1275  stride[indx] = 1;
1276  lcount[indx] = *(count + indx);
1277  }
1278  if ((ds_id->mem_space_id =
1279  H5Screate_simple(ds_id->prev_ndim, dim_arr_mem, dim_arr_mem)) < 0)
1280  return 1;
1281  /* */
1282  if (H5Sselect_hyperslab(ds_id->mem_space_id, H5S_SELECT_SET,
1283  lstart, stride, lcount, block) < 0) return 1;
1284  /*
1285  * create space descriptor for file (set sub-area later)
1286  */
1287  if ((ds_id->fil_space_id = H5Dget_space(ds_id->dat_id)) < 0) return 1;
1288  /*
1289  * initialization over, say so
1290  */
1291  ds_id->dat_rw_mode = H5IO_DAT_RWSLICE;
1292  }
1293  /*
1294  *
1295  * If the count (slice size) was changed from the previous call, deal
1296  * with that here
1297  */
1298  changed_count = 0;
1299  for (indx = 0; indx < ds_id->prev_ndim; indx++)
1300  if (*(count + indx) != *(ds_id->prev_count + indx))
1301  changed_count = 1;
1302  /* */
1303  if (changed_count == 1) {
1304  /*
1305  * since the slice size changed, re-set the space for memory
1306  */
1307  if (H5Sclose(ds_id->mem_space_id) < 0) return 1;
1308  /* */
1309  for (indx = 0; indx < ds_id->prev_ndim; indx++) {
1310  dim_arr_mem[indx] = *(count + indx);
1311  *(ds_id->prev_count + indx) = *(count + indx);
1312  lstart[indx] = 0;
1313  block[indx] = 1;
1314  stride[indx] = 1;
1315  lcount[indx] = *(count + indx);
1316  }
1317  if ((ds_id->mem_space_id =
1318  H5Screate_simple(ds_id->prev_ndim, dim_arr_mem, dim_arr_mem)) < 0)
1319  return 1;
1320  /* */
1321  if (H5Sselect_hyperslab(ds_id->mem_space_id, H5S_SELECT_SET,
1322  lstart, stride, lcount, block) < 0) return 1;
1323  }
1324  /*
1325  * select the file space for each slice written
1326  */
1327  for (indx = 0; indx < ds_id->prev_ndim; indx++) {
1328  lstart[indx] = *(start + indx);
1329  ;
1330  block[indx] = 1;
1331  stride[indx] = 1;
1332  lcount[indx] = *(count + indx);
1333  }
1334  if (H5Sselect_hyperslab(ds_id->fil_space_id, H5S_SELECT_SET,
1335  lstart, stride, lcount, block) < 0) return 1;
1336  /*
1337  * and write it
1338  */
1339  if (H5Dwrite(ds_id->dat_id, ds_id->native_typ, ds_id->mem_space_id,
1340  ds_id->fil_space_id, H5P_DEFAULT, (void *) data) < 0) return 1;
1341  /*
1342  * and finish
1343  */
1344  return 0;
1345 }
1346 
1347 int h5io_grab_ds(h5io_str *id, char *path_name, void *data)
1348 /*******************************************************************
1349 
1350  h5io_grab_ds
1351 
1352  purpose: get the data from a dataset without keeping it open
1353 
1354  Returns type: int - return status: 0 is good
1355  1 if any other error
1356 
1357  Parameters: (in calling order)
1358  Type Name I/O Description
1359  ---- ---- --- -----------
1360  h5io_str * id I id for the opened file,
1361  or group
1362  char * path_name I path to set from current
1363  location with the dataset name
1364  as the last part of the path
1365  void * data O allocated space for the data
1366  to be read into
1367 
1368  Modification history:
1369  Programmer Date Description of change
1370  ---------- ---- ---------------------
1371  W. Robinson, SAIC 02 Oct 2009 Original development
1372 
1373  *******************************************************************/ {
1374  h5io_str ds_id;
1375  /*
1376  * This is a convenience, built from h5io_set_ds, h5io_rd_ds, and h5io_close
1377  */
1378  if (h5io_set_ds(id, path_name, &ds_id) != 0) {
1379  printf("%s:%d - failed to open the %s dataset\n", __FILE__,
1380  __LINE__, path_name);
1381  return 1;
1382  }
1383  if (h5io_rd_ds(&ds_id, data) != 0) {
1384  printf("%s:%d - failed to read the %s dataset\n", __FILE__,
1385  __LINE__, path_name);
1386  return 1;
1387  }
1388  if (h5io_close(&ds_id) != 0) {
1389  printf("%s:%d - failed to close the %s dataset\n", __FILE__,
1390  __LINE__, path_name);
1391  return 1;
1392  }
1393  return 0;
1394 }
1395 
1396 int h5io_grab_ds_slice(h5io_str *id, char *path_name, int *start,
1397  int *count, void *data)
1398 /*******************************************************************
1399 
1400  h5io_grab_ds_slice
1401 
1402  purpose: get a slice of data from a dataset without keeping it open
1403 
1404  Returns type: int - return status: 0 is good
1405  1 if any other error
1406 
1407  Parameters: (in calling order)
1408  Type Name I/O Description
1409  ---- ---- --- -----------
1410  h5io_str * id I id for the opened file,
1411  or group
1412  char * path_name I path to set from current
1413  location with the dataset name
1414  as the last part of the path
1415  int * start I Start (0 origin) of slice to
1416  read, covers all array dims
1417  int * count I how many items to read in
1418  each dimension
1419  void * data O allocated space for the data
1420  to be read into
1421 
1422  Modification history:
1423  Programmer Date Description of change
1424  ---------- ---- ---------------------
1425  W. Robinson, SAIC 09 Nov 2011 Original development
1426 
1427  *******************************************************************/ {
1428  h5io_str ds_id;
1429  /*
1430  * This is a convenience, built from h5io_set_ds, h5io_rd_ds_slice,
1431  * and h5io_close
1432  */
1433  if (h5io_set_ds(id, path_name, &ds_id) != 0) {
1434  printf("%s:%d - failed to open the %s dataset\n", __FILE__,
1435  __LINE__, path_name);
1436  return 1;
1437  }
1438  if (h5io_rd_ds_slice(&ds_id, start, count, data) != 0) {
1439  printf("%s:%d - failed to read the %s dataset\n", __FILE__,
1440  __LINE__, path_name);
1441  return 1;
1442  }
1443  if (h5io_close(&ds_id) != 0) {
1444  printf("%s:%d - failed to close the %s dataset\n", __FILE__,
1445  __LINE__, path_name);
1446  return 1;
1447  }
1448  return 0;
1449 }
1450 
1451 int h5io_attr_exist(h5io_str *id, char *attr_name)
1452 /*******************************************************************
1453 
1454  h5io_rd_attr
1455 
1456  purpose: read a hdf 5 attribute from the file, group, or dataset
1457  does an attribute exist?
1458 
1459  Returns type: int - return status: 0 is good
1460  1 if no attribute by that name exists
1461  -1 if an error
1462 
1463  Parameters: (in calling order)
1464  Type Name I/O Description
1465  ---- ---- --- -----------
1466  h5io_str * id I id for the opened file,
1467  group, or dataset
1468  char * attr_name I name of attribute to get
1469 
1470  Modification history:
1471  Programmer Date Description of change
1472  ---------- ---- ---------------------
1473  W. Robinson, SAIC 23 Sep 2008 Original development
1474  W. Robinson, SAIC 4 Oct 2016 add a H5Aclose to stem leaks
1475 
1476  *******************************************************************/ {
1477  int attr_exist;
1478  hid_t *base_grp, attr_id;
1479  H5E_auto_t old_func;
1480  void *old_client_data;
1481  /*
1482  * set the error reporting off
1483  */
1484  H5Eget_auto(H5E_DEFAULT, &old_func, &old_client_data);
1485  H5Eset_auto(H5E_DEFAULT, NULL, NULL);
1486  /*
1487  * open the attribute
1488  */
1489  base_grp = (id->type == H5IO_TYP_DAT_ID) ?
1490  &(id->dat_id) : &(id->grp_id);
1491  attr_exist = 0;
1492  if ((attr_id = H5Aopen_name(*base_grp, attr_name)) < 0) {
1493  attr_exist = 1;
1494  H5Aclose(attr_id);
1495  }
1496  /*
1497  * return to chatty error reporting
1498  */
1499  H5Eset_auto(H5E_DEFAULT, old_func, old_client_data);
1500  /*
1501  * and return result
1502  */
1503  return attr_exist;
1504 }
1505 
1506 int h5io_grp_contents(h5io_str *id, int *n_obj, char ***o_names,
1507  int **types)
1508 /*******************************************************************
1509 
1510  h5io_grp_contents
1511 
1512  purpose: get a list of object names and types stored in a group
1513 
1514  Returns type: int - return status: 0 is good
1515  1 if any other error
1516 
1517  Parameters: (in calling order)
1518  Type Name I/O Description
1519  ---- ---- --- -----------
1520  h5io_str * id I id of group to use
1521  int * n_obj O # of objects found
1522  char *** o_names O pointer to string array of
1523  names maintained in this
1524  function
1525  int ** types O pointer to a list of object
1526  types found
1527  values will be:
1528  H5G_GROUP - a group
1529  H5G_DATASET - a dataset
1530 
1531  NOTE - the o_names and types are local storage that will be re-used
1532  upon another call. if the results are needed longer, they must
1533  be transfered to other storage.
1534 
1535  Modification history:
1536  Programmer Date Description of change
1537  ---------- ---- ---------------------
1538  W. Robinson, SAIC 13 Oct 2010 Original development
1539 
1540  *******************************************************************/ {
1541  static char **lo_names;
1542  static int *ltypes, ln_obj = 0;
1543  H5G_info_t g_info;
1544  H5G_stat_t info;
1545  int i, len, len0;
1546  /*
1547  * make sure the id is not for a dataset
1548  */
1549  if (id->type == H5IO_TYP_DAT_ID) {
1550  printf("%s, %d: Error: A dataset cannot be the input id\n",
1551  __FILE__, __LINE__);
1552  return 1;
1553  }
1554  /*
1555  * if previously used, free the storage (less memory leaks)
1556  */
1557  if (ln_obj != 0) {
1558  free(ltypes);
1559  for (i = 0; i < ln_obj; i++)
1560  free(lo_names[i]);
1561  free(lo_names);
1562  ln_obj = 0;
1563  }
1564  /*
1565  * find the # of objects (attributes left out for some strange reason)
1566  */
1567  if (H5Gget_info(id->grp_id, &g_info) < 0) {
1568  return 1;
1569  }
1570  *n_obj = g_info.nlinks;
1571  ln_obj = *n_obj;
1572  lo_names = (char **) malloc(*n_obj * sizeof ( char *));
1573  ltypes = (int *) malloc(*n_obj * sizeof ( int));
1574  /*
1575  * get the object names and types
1576  */
1577  for (i = 0; i < *n_obj; i++) {
1578  if ((len0 = H5Gget_objname_by_idx(id->grp_id, i, NULL, 500))
1579  < 0) {
1580  printf("%s, %d - H5Gget_objname_by_idx 1 failed\n",
1581  __FILE__, __LINE__);
1582  return 1;
1583  }
1584  len0++;
1585  lo_names[i] = (char *) malloc(len0 * sizeof ( char));
1586  if ((len = H5Gget_objname_by_idx(id->grp_id, i, lo_names[i], len0))
1587  < 0) {
1588  printf("%s, %d - H5Gget_objname_by_idx failed\n",
1589  __FILE__, __LINE__);
1590  return 1;
1591  }
1592  if (H5Gget_objinfo(id->grp_id, lo_names[i], 0, &info) < 0) {
1593  printf("%s, %d - H5Gget_objinfo failed\n",
1594  __FILE__, __LINE__);
1595  return 1;
1596  }
1597  *(ltypes + i) = info.type;
1598  }
1599  *o_names = lo_names;
1600  *types = ltypes;
1601  return 0;
1602 }
1603 
1604 int h5io_inq_path(h5io_str *id, char *path, int *found_path)
1605 /*******************************************************************
1606 
1607  h5io_inq_path
1608 
1609  purpose: determine if a path defined by group names, exists
1610  below the current location
1611 
1612  Returns type: int - return status: 0 is good
1613  1 if any other error
1614 
1615  Parameters: (in calling order)
1616  Type Name I/O Description
1617  ---- ---- --- -----------
1618  h5io_str * id I id of group to use
1619  char * path I path of group names, like
1620  'Data/Products/May'
1621  Note that last part of path can
1622  also be a dataset name
1623  int * found_path O indicates path exists if 1
1624  non-existant if 0
1625 
1626  Modification history:
1627  Programmer Date Description of change
1628  ---------- ---- ---------------------
1629  W. Robinson, SAIC 24 May 2013 Original development
1630 
1631  *******************************************************************/ {
1632  char *cptr, *tok, str_wrk[FILENAME_MAX], **grp_names;
1633  int32_t nelts, ielt, elt_num, ngid, nobj, iobj, igrp, found_elt;
1634  /* nelts # path elements, ngid # group IDs open */
1635  int *types;
1636  h5io_str *ar_gid, sgid;
1637  /*
1638  * make sure the id is not for a dataset
1639  */
1640  if (id->type == H5IO_TYP_DAT_ID) {
1641  printf("%s, %d, E: h5io_inq_path, a dataset cannot be the input id\n",
1642  __FILE__, __LINE__);
1643  return 1;
1644  }
1645  /*
1646  * count the # elements in the path
1647  */
1648  nelts = 0;
1649  strcpy(str_wrk, path);
1650  cptr = str_wrk;
1651  while ((tok = strtok(cptr, "/")) != NULL) {
1652  nelts++;
1653  cptr = NULL;
1654  }
1655 
1656  ngid = nelts - 1;
1657  /*
1658  * set up the list of group ids for the elements of the path
1659  * and go through checking out the path sent in
1660  */
1661  ar_gid = (h5io_str *) malloc(ngid * sizeof ( h5io_str));
1662  strcpy(str_wrk, path);
1663  sgid = *id;
1664  cptr = str_wrk;
1665  for (ielt = 0; ielt < nelts; ielt++) {
1666  /* get the next path element = tok */
1667  if ((tok = strtok(cptr, "/")) == NULL) {
1668  printf("%s, %d, E: h5io_inq_path, tokens exhausted unexpectedly\n",
1669  __FILE__, __LINE__);
1670  return 1;
1671  }
1672  /* get contents of current group */
1673  if (h5io_grp_contents(&sgid, &nobj, &grp_names, &types) != 0) {
1674  printf("%s, %d: h5io_inq_path problem, exiting\n", __FILE__, __LINE__);
1675  return 1;
1676  }
1677  /* look through contents names and match up with path element */
1678  found_elt = 0;
1679  if (nobj > 0) {
1680  for (iobj = 0; iobj < nobj; iobj++) {
1681  if (strcmp(grp_names[iobj], tok) == 0) {
1682  found_elt = 1;
1683  elt_num = iobj;
1684  break;
1685  }
1686  }
1687  }
1688  if (found_elt == 0) {
1689  *found_path = 0;
1690  if (ielt >= 1)
1691  for (igrp = 0; igrp < (ielt - 1); igrp++)
1692  h5io_close(&(ar_gid[igrp]));
1693  free(ar_gid);
1694  return 0;
1695  }
1696  /* make sure that all but the last path element is a group */
1697  if ((ielt < (nelts - 1)) && (types[elt_num] != H5G_GROUP)) {
1698  printf("%s, %d, E: h5io_inq_path\n", __FILE__, __LINE__);
1699  printf(" non-group found before the last element in the path\n");
1700  printf(" path: %s\n", path);
1701  printf(" non-group element: %s\n", grp_names[elt_num]);
1702  return 1;
1703  }
1704  /*
1705  * set to the next element in the path and check
1706  */
1707  if (ielt < (nelts - 1)) {
1708  if (h5io_set_grp(&sgid, tok, &ar_gid[ielt]) != 0) {
1709  printf("%s, %d: h5io_inq_path problem, exiting\n",
1710  __FILE__, __LINE__);
1711  return 1;
1712  }
1713  }
1714  sgid = ar_gid[ielt];
1715  cptr = NULL;
1716  }
1717  /*
1718  * if we've arrived here, the path is there. close all the ids
1719  * and return success
1720  */
1721  for (igrp = 0; igrp < ngid; igrp++)
1722  h5io_close(&(ar_gid[igrp]));
1723 
1724  *found_path = 1;
1725  free(ar_gid);
1726 
1727  return 0;
1728 }
#define H5IO_DAT_RWALL
Definition: h5io.h:34
int h5io_openr(char *file, int opt, h5io_str *id)
Definition: h5io.c:4
int h5io_attr_exist(h5io_str *id, char *attr_name)
Definition: h5io.c:1451
int h5io_wr_ds_slice(h5io_str *ds_id, int *start, int *count, void *data)
Definition: h5io.c:1175
int h5io_mk_grp(h5io_str *id, char *grp_nam, h5io_str *grp_id)
Definition: h5io.c:778
int h5io_wr_ds(h5io_str *ds_id, void *data)
Definition: h5io.c:1094
#define NULL
Definition: decode_rs.h:63
#define H5IO_TYP_FILE_ID
Definition: h5io.h:31
int h5io_info(h5io_str *id, char *attr_name, H5T_class_t *class, hid_t *native_typ, int *ndim, int *dim_siz, int *sto_len)
Definition: h5io.c:173
int h5io_close(h5io_str *id)
Definition: h5io.c:115
#define H5IO_MAXDIM
Definition: h5io.h: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 h5io_set_grp(h5io_str *id, char *path_name, h5io_str *grp_id)
Definition: h5io.c:369
int h5io_set_ds(h5io_str *id, char *path_name, h5io_str *ds_id)
Definition: h5io.c:324
#define H5IO_DAT_RWSLICE
Definition: h5io.h:35
#define H5IO_TYP_GRP_ID
Definition: h5io.h:32
int h5io_rd_ds_slice(h5io_str *ds_id, int *start, int *count, void *data)
Definition: h5io.c:602
int h5io_rd_attr(h5io_str *id, char *attr_name, void *data)
Definition: h5io.c:412
string path
Definition: color_dtdb.py:221
int h5io_grp_contents(h5io_str *id, int *n_obj, char ***o_names, int **types)
Definition: h5io.c:1506
int h5io_grab_ds_slice(h5io_str *id, char *path_name, int *start, int *count, void *data)
Definition: h5io.c:1396
#define H5IO_TYP_DAT_ID
Definition: h5io.h:33
int h5io_wr_attr(h5io_str *id, char *attr_name, hid_t out_type, int ndim, int *dim_siz, void *data)
Definition: h5io.c:922
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude data
Definition: HISTORY.txt:356
int h5io_grab_ds(h5io_str *id, char *path_name, void *data)
Definition: h5io.c:1347
int h5io_openw(char *file, int opt, h5io_str *id)
Definition: h5io.c:68
int h5io_wr_attr_str(h5io_str *id, char *attr_name, int ndim, int *dim_siz, int str_len, char *data)
Definition: h5io.c:1006
int h5io_inq_path(h5io_str *id, char *path, int *found_path)
Definition: h5io.c:1604
int h5io_mk_ds(h5io_str *id, char *ds_name, hid_t type, int ndim, int *dim_siz, h5io_str *ds_id)
Definition: h5io.c:821
int h5io_rd_ds(h5io_str *ds_id, void *data)
Definition: h5io.c:505
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 count
Definition: decode_rs.h:79