2.1.1. HDF5 in C with libhdf5

C-language code examples are provided for writing and reading NeXus-compliant files using the native HDF5 interfaces. These examples are derived from the simple NAPI examples for writing and reading given in the Introduction chapter.

2.1.1.1. Writing a simple NeXus file using native HDF5 commands in C

Note

This example uses the new method described in Associating plottable data using attributes applied to the NXdata group for indicating plottable data.

  1/**
  2 * This is an example how to write a valid NeXus file
  3 * using the HDF-5 API alone. Ths structure which is 
  4 * going to be created is:
  5 *
  6 * scan:NXentry
  7 *      data:NXdata
  8 *         @signal = "counts"
  9 *         @axes = "two_theta"
 10 *         @two_theta_indices = 0
 11 *         counts[]
 12 *            @units="counts"
 13 *         two_theta[]
 14 *            @units="degrees"
 15*
 16 *  WARNING: each of the HDF function below needs to be 
 17 *  wrapped into something like:
 18 *
 19 *  if((hdfid = H5function(...)) < 0){
 20 *     handle error gracefully  
 21 *  }  
 22 *  I left the error checking out in order to keep the 
 23 *  code clearer
 24 * 
 25 *  This also installs a link from /scan/data/two_theta to /scan/hugo
 26 * 
 27 *  Mark Koennecke, October 2011
 28 */
 29#include <hdf5.h>
 30#include <stdlib.h>
 31#include <string.h>
 32
 33static void write_string_attr(hid_t hid, const char* name, const char* value)
 34{
 35  /* HDF-5 handles */
 36  hid_t atts, atttype, attid;
 37
 38  atts = H5Screate(H5S_SCALAR);
 39  atttype = H5Tcopy(H5T_C_S1);
 40  H5Tset_size(atttype, strlen(value));
 41  attid = H5Acreate(hid,name, atttype, atts, H5P_DEFAULT, H5P_DEFAULT);
 42  H5Awrite(attid, atttype, value);
 43  H5Sclose(atts);
 44  H5Tclose(atttype);
 45  H5Aclose(attid);
 46}
 47
 48static void write_int_attr(hid_t hid, const char* name, int value)
 49{
 50  /* HDF-5 handles */
 51  hid_t atts, atttype, attid;
 52
 53  atts = H5Screate(H5S_SCALAR);
 54  atttype = H5Tcopy(H5T_NATIVE_INT);
 55  H5Tset_size(atttype,1);
 56  attid = H5Acreate(hid,name, atttype, atts, H5P_DEFAULT, H5P_DEFAULT);
 57  H5Awrite(attid, atttype, &value);
 58  H5Sclose(atts);
 59  H5Tclose(atttype);
 60  H5Aclose(attid);
 61}
 62
 63#define LENGTH 400
 64int main(int argc, char *argv[])
 65{
 66  float two_theta[LENGTH];
 67  int counts[LENGTH], i, rank;
 68
 69  /* HDF-5 handles */
 70  hid_t fid, fapl, gid;
 71  hid_t datatype, dataspace, dataprop, dataid;
 72  hsize_t dim[1], maxdim[1];
 73
 74
 75  /* create some data: nothing NeXus or HDF-5 specific */
 76  for(i = 0; i < LENGTH; i++){
 77    two_theta[i] = 10. + .1*i;
 78    counts[i] = (int)(1000 * ((float)random()/(float)RAND_MAX));
 79  }
 80  dim[0] = LENGTH;
 81  maxdim[0] = LENGTH;
 82  rank = 1;
 83
 84
 85 
 86  /*
 87   * open the file. The file attribute forces normal file 
 88   * closing behaviour down HDF-5's throat
 89   */
 90  fapl = H5Pcreate(H5P_FILE_ACCESS);
 91  H5Pset_fclose_degree(fapl,H5F_CLOSE_STRONG);
 92  fid = H5Fcreate("NXfile.h5", H5F_ACC_TRUNC, H5P_DEFAULT,fapl);  
 93  H5Pclose(fapl);
 94
 95
 96  /*
 97   * create scan:NXentry
 98   */
 99  gid = H5Gcreate(fid, "scan",H5P_DEFAULT,H5P_DEFAULT,H5P_DEFAULT);
100  /*
101   * store the NX_class attribute. Notice that you
102   * have to take care to close those hids after use
103   */
104  write_string_attr(gid, "NX_class", "NXentry");
105
106  /*
107   * same thing for data:Nxdata in scan:NXentry.
108   */
109  gid = H5Gcreate(fid, "/scan/data",H5P_DEFAULT,H5P_DEFAULT,H5P_DEFAULT);
110  write_string_attr(gid, "NX_class", "NXdata");
111
112  /*
113   * define axes.
114   */
115  write_string_attr(gid, "signal", "counts");
116  write_string_attr(gid, "axes", "two_theta");
117  write_int_attr(gid, "two_theta_indices", 0);
118
119  /*
120   * store the counts dataset
121   */
122  dataspace = H5Screate_simple(rank,dim,maxdim);
123  datatype = H5Tcopy(H5T_NATIVE_INT);  
124  dataprop = H5Pcreate(H5P_DATASET_CREATE);
125  dataid = H5Dcreate(gid,"counts",datatype,dataspace,H5P_DEFAULT,dataprop,H5P_DEFAULT);
126  H5Dwrite(dataid, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, counts);
127  H5Sclose(dataspace);
128  H5Tclose(datatype);
129  H5Pclose(dataprop);  
130  /*
131   * set the units attribute
132   */
133  write_string_attr(dataid, "units", "counts");
134
135  H5Dclose(dataid);
136
137  /*
138   * store the two_theta dataset
139   */
140  dataspace = H5Screate_simple(rank,dim,maxdim);
141  datatype = H5Tcopy(H5T_NATIVE_FLOAT);  
142  dataprop = H5Pcreate(H5P_DATASET_CREATE);
143  dataid = H5Dcreate(gid,"two_theta",datatype,dataspace,H5P_DEFAULT,dataprop,H5P_DEFAULT);
144  H5Dwrite(dataid, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, two_theta);
145  H5Sclose(dataspace);
146  H5Tclose(datatype);
147  H5Pclose(dataprop);  
148
149  /*
150   * set the units attribute
151   */
152  write_string_attr(dataid, "units", "degrees");
153
154  /*
155   * set the target attribute for linking
156   */
157  write_string_attr(dataid, "target", "/scan/data/two_theta");
158
159  H5Dclose(dataid);
160
161  /*
162   * make a link in /scan to /scan/data/two_theta, thereby 
163   * renaming two_theta to hugo
164   */
165  H5Glink(fid,H5G_LINK_HARD,"/scan/data/two_theta","/scan/hugo");
166
167  /*
168   * close the file 
169   */
170  H5Fclose(fid);
171}

2.1.1.2. Reading a simple NeXus file using native HDF5 commands in C

 1/**
 2 * Reading example for reading NeXus files with plain
 3 * HDF-5 API calls. This reads out counts and two_theta
 4 * out of the file generated by nxh5write.
 5 *
 6 * WARNING: I left out all error checking in this example.
 7 * In production code you have to take care of those errors
 8 *
 9 * Mark Koennecke, October 2011
10 */
11#include <hdf5.h>
12#include <stdlib.h>
13
14int main(int argc, char *argv[])
15{
16  float *two_theta = NULL;
17  int *counts = NULL,  rank, i;
18  hid_t fid, dataid, fapl;
19  hsize_t *dim = NULL;
20  hid_t dataspace, memdataspace;
21
22  /*
23   * Open file, thereby enforcing proper file close
24   * semantics
25   */
26  fapl = H5Pcreate(H5P_FILE_ACCESS);
27  H5Pset_fclose_degree(fapl,H5F_CLOSE_STRONG);
28  fid = H5Fopen("NXfile.h5", H5F_ACC_RDONLY,fapl);  
29  H5Pclose(fapl);
30
31  /*
32   * open and read the counts dataset
33   */
34  dataid = H5Dopen(fid,"/scan/data/counts",H5P_DEFAULT);
35  dataspace = H5Dget_space(dataid);
36  rank = H5Sget_simple_extent_ndims(dataspace);
37  dim = malloc(rank*sizeof(hsize_t));
38  H5Sget_simple_extent_dims(dataspace, dim, NULL);
39  counts = malloc(dim[0]*sizeof(int));
40  memdataspace = H5Tcopy(H5T_NATIVE_INT32);
41  H5Dread(dataid,memdataspace,H5S_ALL, H5S_ALL,H5P_DEFAULT, counts);
42  H5Dclose(dataid);
43  H5Sclose(dataspace);
44  H5Tclose(memdataspace);
45
46  /*
47   * open and read the two_theta data set
48   */
49  dataid = H5Dopen(fid,"/scan/data/two_theta",H5P_DEFAULT);
50  dataspace = H5Dget_space(dataid);
51  rank = H5Sget_simple_extent_ndims(dataspace);
52  dim = malloc(rank*sizeof(hsize_t));
53  H5Sget_simple_extent_dims(dataspace, dim, NULL);
54  two_theta = malloc(dim[0]*sizeof(float));
55  memdataspace = H5Tcopy(H5T_NATIVE_FLOAT);
56  H5Dread(dataid,memdataspace,H5S_ALL, H5S_ALL,H5P_DEFAULT, two_theta);
57  H5Dclose(dataid);
58  H5Sclose(dataspace);
59  H5Tclose(memdataspace);
60
61
62
63  H5Fclose(fid);
64
65  for(i = 0; i < dim[0]; i++){
66    printf("%8.2f %10d\n", two_theta[i], counts[i]);
67  }
68  
69}