Getting started¶
Write a NeXus HDF5 File¶
In the main code section of simple_example_basic_write.py,
the data (mr
is similar to “two_theta” and
I00
is similar to “counts”) is collated into two Python lists. We use the
numpy package to read the file and parse the two-column format.
The new HDF5 file is opened (and created if not already existing) for writing,
setting common NeXus attributes in the same command from our support library.
Proper HDF5+NeXus groups are created for /entry:NXentry/mr_scan:NXdata
.
Since we are not using the NAPI, our
support library must create and set the NX_class
attribute on each group.
Note
We want to create the desired structure of
/entry:NXentry/mr_scan:NXdata/
.
First, our support library calls
f = h5py.File()
to create the file and root level NeXus structure.Then, it calls
nxentry = f.create_group("entry")
to create theNXentry
group calledentry
at the root level.Then, it calls
nxdata = nxentry.create_group("mr_scan")
to create theNXentry
group calledentry
as a child of theNXentry
group.
Next, we create a dataset called title
to hold a title string that can
appear on the default plot.
Next, we create datasets for mr
and I00
using our support library.
The data type of each, as represented in numpy
, will be recognized by
h5py
and automatically converted to the proper HDF5 type in the file.
A Python dictionary of attributes is given, specifying the engineering units and other
values needed by NeXus to provide a default plot of this data. By setting signal="I00"
as an attribute on the group, NeXus recognizes I00
as the default
y axis for the plot. The axes="mr"
attribute on the NXdata
group connects the dataset to be used as the x axis.
Finally, we must remember to call f.close()
or we might
corrupt the file when the program quits.
simple_example_basic_write.py: Write a NeXus HDF5 file using Python with h5py
1#!/usr/bin/env python
2"""Writes a NeXus HDF5 file using h5py and numpy"""
3
4from pathlib import Path
5from re import X
6import numpy
7
8from nexusformat.nexus import NXdata, NXentry, NXfield, nxopen
9
10print("Write a NeXus HDF5 file")
11fileName = "simple_example_basic.nexus.hdf5"
12
13# load data from two column format
14data_filename = str(Path(__file__).absolute().parent.parent / "simple_example.dat")
15data = numpy.loadtxt(data_filename).T
16mr_arr = data[0]
17i00_arr = numpy.asarray(data[1], "int32")
18
19# create the HDF5 NeXus file
20with nxopen(fileName, "w") as f:
21
22 # create the NXentry group
23 f["entry"] = NXentry()
24 f["entry/title"] = "1-D scan of I00 v. mr"
25
26 # create the NXdata group
27 x = NXfield(mr_arr, name="mr", units="degrees", long_name="USAXS mr (degrees)")
28 y = NXfield(i00_arr, name="I00", units="counts",
29 long_name="USAXS I00 (counts)")
30 f["entry/mr_scan"] = NXdata(y, x)
31
32print("wrote file:", fileName)
1#!/usr/bin/env python
2"""Writes a NeXus HDF5 file using h5py and numpy"""
3
4from pathlib import Path
5import datetime
6import h5py # HDF5 support
7import numpy
8
9print("Write a NeXus HDF5 file")
10fileName = "simple_example_basic.nexus.hdf5"
11timestamp = datetime.datetime.now().astimezone().isoformat()
12
13# load data from two column format
14data_filename = str(Path(__file__).absolute().parent.parent / "simple_example.dat")
15data = numpy.loadtxt(data_filename).T
16mr_arr = data[0]
17i00_arr = numpy.asarray(data[1], "int32")
18
19# create the HDF5 NeXus file
20with h5py.File(fileName, "w") as f:
21 # point to the default data to be plotted
22 f.attrs["default"] = "entry"
23 # give the HDF5 root some more attributes
24 f.attrs["file_name"] = fileName
25 f.attrs["file_time"] = timestamp
26 f.attrs["instrument"] = "APS USAXS at 32ID-B"
27 f.attrs["creator"] = "simple_example_basic_write.py"
28 f.attrs["NeXus_version"] = "4.3.0"
29 f.attrs["HDF5_Version"] = h5py.version.hdf5_version
30 f.attrs["h5py_version"] = h5py.version.version
31
32 # create the NXentry group
33 nxentry = f.create_group("entry")
34 nxentry.attrs["NX_class"] = "NXentry"
35 nxentry.attrs["default"] = "mr_scan"
36 nxentry.create_dataset("title", data="1-D scan of I00 v. mr")
37
38 # create the NXentry group
39 nxdata = nxentry.create_group("mr_scan")
40 nxdata.attrs["NX_class"] = "NXdata"
41 nxdata.attrs["signal"] = "I00" # Y axis of default plot
42 nxdata.attrs["axes"] = "mr" # X axis of default plot
43 nxdata.attrs["mr_indices"] = [
44 0,
45 ] # use "mr" as the first dimension of I00
46
47 # X axis data
48 ds = nxdata.create_dataset("mr", data=mr_arr)
49 ds.attrs["units"] = "degrees"
50 ds.attrs["long_name"] = "USAXS mr (degrees)" # suggested X axis plot label
51
52 # Y axis data
53 ds = nxdata.create_dataset("I00", data=i00_arr)
54 ds.attrs["units"] = "counts"
55 ds.attrs["long_name"] = "USAXS I00 (counts)" # suggested Y axis plot label
56
57print("wrote file:", fileName)
Read a NeXus HDF5 File¶
The file reader, simple_example_basic_read.py, opens the HDF5 we wrote above, prints the HDF5 attributes from the file, reads the two datasets, and then prints them out as columns. As simple as that. Of course, real code might add some error-handling and extracting other useful stuff from the file.
Note
See that we identified each of the two datasets using HDF5 absolute path references
(just using the group and dataset names). Also, while coding this example, we were reminded
that HDF5 is sensitive to upper or lowercase. That is, I00
is not the same is
i00
.
simple_example_basic_read.py: Read a NeXus HDF5 file using Python
1#!/usr/bin/env python
2"""Reads NeXus HDF5 files using nexusformat and prints the contents"""
3
4from nexusformat.nexus import nxopen
5
6fileName = "simple_example_basic.nexus.hdf5"
7with nxopen(fileName) as f:
8 print(f.tree)
1#!/usr/bin/env python
2"""Reads NeXus HDF5 files using h5py and prints the contents"""
3
4import h5py # HDF5 support
5
6fileName = "simple_example_basic.nexus.hdf5"
7with h5py.File(fileName, "r") as f:
8 for item in f.attrs.keys():
9 print(item + ":", f.attrs[item])
10 mr = f["/entry/mr_scan/mr"]
11 i00 = f["/entry/mr_scan/I00"]
12 print("%s\t%s\t%s" % ("#", "mr", "I00"))
13 for i in range(len(mr)):
14 print("%d\t%g\t%d" % (i, mr[i], i00[i]))
Output from simple_example_basic_read.py
is shown next.
Output from simple_example_basic_read.py
1file_name: simple_example_basic.nexus.hdf5
2file_time: 2010-10-18T17:17:04-0500
3creator: simple_example_basic_write.py
4HDF5_Version: 1.8.5
5NeXus_version: 4.3.0
6h5py_version: 1.2.1
7instrument: APS USAXS at 32ID-B
8# mr I00
90 17.9261 1037
101 17.9259 1318
112 17.9258 1704
123 17.9256 2857
134 17.9254 4516
145 17.9252 9998
156 17.9251 23819
167 17.9249 31662
178 17.9247 40458
189 17.9246 49087
1910 17.9244 56514
2011 17.9243 63499
2112 17.9241 66802
2213 17.9239 66863
2314 17.9237 66599
2415 17.9236 66206
2516 17.9234 65747
2617 17.9232 65250
2718 17.9231 64129
2819 17.9229 63044
2920 17.9228 60796
3021 17.9226 56795
3122 17.9224 51550
3223 17.9222 43710
3324 17.9221 29315
3425 17.9219 19782
3526 17.9217 12992
3627 17.9216 6622
3728 17.9214 4198
3829 17.9213 2248
3930 17.9211 1321
downloads¶
The Python code and files related to this section may be downloaded from the following table.
file |
description |
---|---|
2-column ASCII data used in this section |
|
h5py code to read example simple_example_basic.nexus.hdf5 |
|
nexusformat code to read example simple_example_basic.nexus.hdf5 |
|
h5py code to write example simple_example_basic.nexus.hdf5 |
|
nexusformat code to write example simple_example_basic.nexus.hdf5 |
|
h5dump analysis of the NeXus file |
|
NeXus file written by BasicWriter |
|
punx tree analysis of the NeXus file |