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/.
Examine the example code below for these key actions to create the structure:
action |
nexusformat function |
h5py function |
|---|---|---|
create file & root ( |
|
|
create |
|
|
create |
|
|
store |
|
|
store |
|
|
add |
|
|
The title string is added to label the default plot.
The data type of mr and I00, as represented in numpy, will be recognized
by h5py and automatically converted to the proper HDF5 type in the file.
Engineering units and other metadata needed by NeXus to provide a default plot of
this data are provided. The NeXus signal="I00"
attribute on the NXdata group identifies 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.
Since we opened the file with a Python context manager (with .. as f:), it
is not necessary to make an explicit call to close the file. The context manager
will close the file with the context.
simple_example_basic_write.py: Write a NeXus HDF5 file using Python with h5py
In the nexusformat version, these attributes are added automatically
when calling NXdata(y, x) with the first argument defining the
signal and the second the axes. With signals of higher rank, the
second argument would be a list of axes.
1#!/usr/bin/env python
2"""Writes a NeXus HDF5 file using h5py and numpy"""
3
4from pathlib import Path
5
6import numpy
7from nexusformat.nexus import NXdata
8from nexusformat.nexus import NXentry
9from nexusformat.nexus import NXfield
10from nexusformat.nexus import nxopen
11
12print("Write a NeXus HDF5 file")
13fileName = "simple_example_basic.nexus.hdf5"
14
15# load data from two column format
16data_filename = str(Path(__file__).absolute().parent.parent / "simple_example.dat")
17data = numpy.loadtxt(data_filename).T
18mr_arr = data[0]
19i00_arr = numpy.asarray(data[1], "int32")
20
21# create the HDF5 NeXus file
22with nxopen(fileName, "w") as f:
23
24 # create the NXentry group
25 f["entry"] = NXentry()
26 f["entry/title"] = "1-D scan of I00 v. mr"
27
28 # create the NXdata group
29 x = NXfield(mr_arr, name="mr", units="degrees", long_name="USAXS mr (degrees)")
30 y = NXfield(i00_arr, name="I00", units="counts", long_name="USAXS I00 (counts)")
31 f["entry/mr_scan"] = NXdata(y, x)
32
33print("wrote file:", fileName)
1#!/usr/bin/env python
2"""Writes a NeXus HDF5 file using h5py and numpy"""
3
4import datetime
5from pathlib import Path
6
7import h5py # HDF5 support
8import numpy
9
10print("Write a NeXus HDF5 file")
11fileName = "simple_example_basic.nexus.hdf5"
12timestamp = datetime.datetime.now().astimezone().isoformat()
13
14# load data from two column format
15data_filename = str(Path(__file__).absolute().parent.parent / "simple_example.dat")
16data = numpy.loadtxt(data_filename).T
17mr_arr = data[0]
18i00_arr = numpy.asarray(data[1], "int32")
19
20# create the HDF5 NeXus file
21with h5py.File(fileName, "w") as f:
22 # point to the default data to be plotted
23 f.attrs["default"] = "entry"
24 # give the HDF5 root some more attributes
25 f.attrs["file_name"] = fileName
26 f.attrs["file_time"] = timestamp
27 f.attrs["instrument"] = "APS USAXS at 32ID-B"
28 f.attrs["creator"] = "simple_example_basic_write.py"
29 f.attrs["NeXus_version"] = "4.3.0"
30 f.attrs["HDF5_Version"] = h5py.version.hdf5_version
31 f.attrs["h5py_version"] = h5py.version.version
32
33 # create the NXentry group
34 nxentry = f.create_group("entry")
35 nxentry.attrs["NX_class"] = "NXentry"
36 nxentry.attrs["default"] = "mr_scan"
37 nxentry.create_dataset("title", data="1-D scan of I00 v. mr")
38
39 # create the NXentry group
40 nxdata = nxentry.create_group("mr_scan")
41 nxdata.attrs["NX_class"] = "NXdata"
42 nxdata.attrs["signal"] = "I00" # Y axis of default plot
43 nxdata.attrs["axes"] = "mr" # X axis of default plot
44 nxdata.attrs["mr_indices"] = [
45 0,
46 ] # use "mr" as the first dimension of I00
47
48 # X axis data
49 ds = nxdata.create_dataset("mr", data=mr_arr)
50 ds.attrs["units"] = "degrees"
51 ds.attrs["long_name"] = "USAXS mr (degrees)" # suggested X axis plot label
52
53 # Y axis data
54 ds = nxdata.create_dataset("I00", data=i00_arr)
55 ds.attrs["units"] = "counts"
56 ds.attrs["long_name"] = "USAXS I00 (counts)" # suggested Y axis plot label
57
58print("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
The nexusformat version prints the whole file as a tree.
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
The nexusformat version prints the whole file as a tree.
1root:NXroot
2 @HDF5_Version = '1.12.1'
3 @NeXus_version = '4.3.0'
4 @creator = 'simple_example_basic_write.py'
5 @default = 'entry'
6 @file_name = 'simple_example_basic.nexus.hdf5'
7 @file_time = '2022-06-15T14:31:39.410075+02:00'
8 @h5py_version = '3.6.0'
9 @instrument = 'APS USAXS at 32ID-B'
10 entry:NXentry
11 @default = 'mr_scan'
12 mr_scan:NXdata
13 @axes = 'mr'
14 @mr_indices = 0
15 @signal = 'I00'
16 I00 = int32(31)
17 @long_name = 'USAXS I00 (counts)'
18 @units = 'counts'
19 mr = float64(31)
20 @long_name = 'USAXS mr (degrees)'
21 @units = 'degrees'
22 title = '1-D scan of I00 v. mr'
1HDF5_Version: 1.12.1
2NeXus_version: 4.3.0
3creator: simple_example_basic_write.py
4default: entry
5file_name: simple_example_basic.nexus.hdf5
6file_time: 2022-06-15T14:31:39.410075+02:00
7h5py_version: 3.6.0
8instrument: APS USAXS at 32ID-B
9# mr I00
100 17.9261 1037
111 17.9259 1318
122 17.9258 1704
133 17.9256 2857
144 17.9254 4516
155 17.9252 9998
166 17.9251 23819
177 17.9249 31662
188 17.9247 40458
199 17.9246 49087
2010 17.9244 56514
2111 17.9243 63499
2212 17.9241 66802
2313 17.9239 66863
2414 17.9237 66599
2515 17.9236 66206
2616 17.9234 65747
2717 17.9232 65250
2818 17.9231 64129
2919 17.9229 63044
3020 17.9228 60796
3121 17.9226 56795
3222 17.9224 51550
3323 17.9222 43710
3424 17.9221 29315
3525 17.9219 19782
3626 17.9217 12992
3727 17.9216 6622
3828 17.9214 4198
3929 17.9213 2248
4030 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 |