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 
 33 static 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 
 48 static 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
 64 int 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 
14 int 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 }