NAPI: The NeXus Application Programming Interface¶
The NeXus API consists of routines to read and write NeXus data files. It was written to provide a simple to use and consistent common interface for all supported backends (XML, HDF4 and HDF5) to scientific programmers and other users of the NeXus Data Standard.
Note
It is not necessary to use the NAPI to write or read NeXus data files. The intent of the NAPI is to simplify the programming effort to use the HDF programming interface. There are Examples of writing and reading NeXus data files to help you understand.
This section will provide a brief overview of the available functionality. Further documentation of the NeXus Application Programming Interface (NAPI) for bindings to specific programming language can be found in the NAPI chapter and may be downloaded from the NeXus development site. [1]
For an even more detailed description of the internal workings of NAPI
see NeXusIntern.pdf
, copied from the NeXus code repository.
That document is written for programmers who want to work on the NAPI itself.
If you are new to NeXus and just want to implement basic file reading or writing
you should not start by reading that.
How do I write a NeXus file?¶
The NeXus Application Program Interface (NAPI) provides a set of subroutines that make it easy to read and write NeXus files. These subroutines are available in C, Fortran 77, Fortran 90, Java, Python, C++, and IDL.
The API uses a very simple state model to navigate through a NeXus file. (Compare this example with NAPI Simple 2-D Write Example (C, F77, F90), in the NAPI chapter, using the native HDF5 commands.) When you open a file, the API provides a file handle, which stores the current location, i.e. which group and/or field is currently open. Read and write operations then act on the currently open entity. Following the simple example titled Example structure of a simple data file, we walk through a schematic of NeXus program written in C (without any error checking or real data).
Writing a simple NeXus file using NAPI
Note
We assume the program can define
the arrays tth
and counts
, each length n
.
This part has been omitted from the example code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include "napi.h"
int main()
{
/* we start with known arrays tth and counts, each length n */
NXhandle fileID;
NXopen ("NXfile.nxs", NXACC_CREATE, &fileID);
NXmakegroup (fileID, "Scan", "NXentry");
NXopengroup (fileID, "Scan", "NXentry");
NXmakegroup (fileID, "data", "NXdata");
NXopengroup (fileID, "data", "NXdata");
NXmakedata (fileID, "two_theta", NX_FLOAT32, 1, &n);
NXopendata (fileID, "two_theta");
NXputdata (fileID, tth);
NXputattr (fileID, "units", "degrees", 7, NX_CHAR);
NXclosedata (fileID); /* two_theta */
NXmakedata (fileID, "counts", NX_FLOAT32, 1, &n);
NXopendata (fileID, "counts");
NXputdata (fileID, counts);
NXclosedata (fileID); /* counts */
NXclosegroup (fileID); /* data */
NXclosegroup (fileID); /* Scan */
NXclose (&fileID);
return;
}
|
program analysis
- line 7:
Open the file
NXfile.nxs
with create access (implying write access). NAPI [2] returns a file identifier of typeNXhandle
.
- line 10:
The plottable data is contained within an NXdata group, which must also be created and opened.
- line 12:
To create a field, call
NXmakedata()
, specifying the data name, type (NX_FLOAT32
), rank (in this case,1
), and length of the array (n
). Then, it can be opened for writing. [4]
- line 14:
Write the data using
NXputdata()
.
- line 16:
Then we close the field before opening another. In fact, the API will do this automatically if you attempt to open another field, but it is better style to close it yourself.
- line 17:
The remaining fields in this group are added in a similar fashion. Note that the indentation whenever a new field or group are opened is just intended to make the structure of the NeXus file more transparent.
- line 20:
Finally, close the groups (
NXdata
andNXentry
) before closing the file itself.
How do I read a NeXus file?¶
Reading a NeXus file works in the same way by traversing the tree with the handle.
This schematic C code will read the two-theta array created in the example above. (Again, compare this example with Reading a simple NeXus file using native HDF5 commands in C.)
Reading a simple NeXus file using NAPI
1 2 3 4 5 6 7 8 9 10 11 | NXopen ('NXfile.nxs', NXACC_READ, &fileID);
NXopengroup (fileID, "Scan", "NXentry");
NXopengroup (fileID, "data", "NXdata");
NXopendata (fileID, "two_theta");
NXgetinfo (fileID, &rank, dims, &datatype);
NXmalloc ((void **) &tth, rank, dims, datatype);
NXgetdata (fileID, tth);
NXclosedata (fileID);
NXclosegroup (fileID);
NXclosegroup (fileID);
NXclose (fileID);
|
How do I browse a NeXus file?¶
NeXus files can also be viewed by a command-line browser,
nxbrowse
, which is included as a helper tool in the
NeXus API
distribution. The following
is an example session of nxbrowse
nxbrowse
to view a data file.
Using nxbrowse
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | %> nxbrowse lrcs3701.nxs
NXBrowse 3.0.0. Copyright (C) 2000 R. Osborn, M. Koennecke, P. Klosowski
NeXus_version = 1.3.3
file_name = lrcs3701.nxs
file_time = 2001-02-11 00:02:35-0600
user = EAG/RO
NX> dir
NX Group : Histogram1 (NXentry)
NX Group : Histogram2 (NXentry)
NX> open Histogram1
NX/Histogram1> dir
NX Data : title[44] (NX_CHAR)
NX Data : analysis[7] (NX_CHAR)
NX Data : start_time[24] (NX_CHAR)
NX Data : end_time[24] (NX_CHAR)
NX Data : run_number (NX_INT32)
NX Group : sample (NXsample)
NX Group : LRMECS (NXinstrument)
NX Group : monitor1 (NXmonitor)
NX Group : monitor2 (NXmonitor)
NX Group : data (NXdata)
NX/Histogram1> read title
title[44] (NX_CHAR) = MgB2 PDOS 43.37g 8K 120meV E0@240Hz T0@120Hz
NX/Histogram1> open data
NX/Histogram1/data> dir
NX Data : title[44] (NX_CHAR)
NX Data : data[148,750] (NX_INT32)
NX Data : time_of_flight[751] (NX_FLOAT32)
NX Data : polar_angle[148] (NX_FLOAT32)
NX/Histogram1/data> read time_of_flight
time_of_flight[751] (NX_FLOAT32) = [ 1900.000000 1902.000000 1904.000000 ...]
units = microseconds
long_name = Time-of-Flight [microseconds]
NX/Histogram1/data> read data
data[148,750] (NX_INT32) = [ 1 1 0 ...]
units = counts
signal = 1
long_name = Neutron Counts
axes = polar_angle:time_of_flight
NX/Histogram1/data> close
NX/Histogram1> close
NX> quit
|
program analysis
- line 1:
Start
nxbrowse
from the UNIX command line and open filelrcs3701.nxs
from IPNS/LRMECS.
- line 8:
List the contents of the current group.
- line 11:
Open the NeXus group
Histogram1
.
- line 23:
Print the contents of the NeXus data labeled
title
.
- line 41:
Close the current group.
- line 43:
Quits
nxbrowse
.
The source code of nxbrowse
[8]
provides an example of how to write a NeXus reader.
The test programs included in the NeXus
API may also be useful to study.
[1] | http://download.nexusformat.org |
[2] | NAPI: NeXus Application Programmer Interface (frozen) |
[3] | See the chapter Base Class Definitions for more information. |
[4] | The NeXus Data Types
section describes the available
data types, such as NX_FLOAT32
and NX_CHAR . |
[5] | NeXus Data Units |
[6] | The NeXus rule about data units is described in the NeXus Data Units section. |
[7] | see Data Types allowed in NXDL specifications |
[8] | https://github.com/nexusformat/code/blob/master/applications/NXbrowse/NXbrowse.c |