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}