Example NeXus C programs using native HDF5 commands

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. Compare these code examples with Example NeXus programs using NAPI.

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}

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}