This document describes a set of routines designed to create, populate, read and modify ISIS format and NeXus format data files. The aim of these routines is to provide one simple way to read and write all styles of data files. The routines are based on the routines used in Open GENIE and will therefore cope with automatic detection of file input types for all Open GENIE supported file formats.
Any data interface design is a compromise between flexibility and complexity. The interface below is intended to be simple to use from C, C++ or FORTRAN programs but does make use of some of the most advanced parts of the Open GENIE data access subsystem to do this. As a result, it is worth being aware of how data is actually read or written by the interface.
When reading a file on different machine types, there are inherently several different conversion problems which may arise. Some are due to differences in the structure of the data files, others may be due to differences in numerical precision or binary format. As a result, the access routines work in two stages.
For reading:
For writing:
In both cases, this is a very simple operation if the structure of the data file is simple. On the other hand, if the structure of the data file is complex, the data access routines provide a unique and powerful data structure parsing mechanism which allows complex structures to be easily snipped up into manageable (if not byte sized!) pieces.
A "Handle" is the name given to the data block which has been converted from the file but has not yet been loaded into your program. It is simply a user chosen name to identify the block of data in transition between stages (1) and (2) above, effectively the data enters a holding area where you can then make detailed requests of it. For example, if we read one experimental parameter from an ISIS raw file, "NSP1", the fragment of the program using handles would look something like the one below.
... * Access the data item by name and put in the transfer area CALL GX_get('MY_HANDLE', 'NSP1', 0) * Read the value into the INTEGER variable "my_nsp" CALL GX_transfer('MY_HANDLE', '-->', 'INTEGER', my_nsp, 0, 0) ...
The handle name links the request to get the data with the subsequent request to load the data into a program variable.
A handle can be re-used as often as required or several different handles may be used to allow to store data blocks before reading them out into the code. A handle expression can also be used to select a small amount of data to read into the program from a larger data block.
Let's assume now that we want to read the first "MAXLEN" elements of the detector to spectrum mapping table and write it out to a new file. We know the name of the data item in the ISIS raw file and can access it as below.
* Somewhere to put the data we are about to read INTEGER*4 my_tab(42) ... * Get the whole data block to the handle. CALL GX_get('MY_HANDLE', 'SPEC', 0) * Select part of the data to read out from the handle. CALL GX_transfer('MY_HANDLE[1:42]', '-->', 'INTEGER', my_tab, 42, 1) ...
This way we can slice the first 42 elements out of the array (assuming it has at least 42 elements). This example could have just specified a single array element if only one value was required. In some file formats, the block may contain named fields or attributes. These can be accessed using the syntax for accessing workspaces, for example "My_Handle.Two_Theta".
Before reading or writing data, a session must be initialised using GX_activate_session(), at the end of data access GX_deactivate_session() session should also be called. These routines control the allocation and deallocation of memory as well as setting the default output file format.
The interface makes the general assumption that a user may well want to have one file open for writing at the same time as having a different file open for reading. This is achieved by having both GX_select_source() and GX_select_destination routines(), either or both of these calls may be used in a data access session. The GX_directory() function allows the calling program to find out what data items are available for a program to read in the specified file.
The following is a generic description of the Application Programming Interface (API) and is divided into sections grouping similar functions. Language specific routine calls are given in the reference documentation for each rouitine.
Session Control
Function | Return value | Description |
GX_activate_session(in default_format) | status code | Initialises the interface selecting a default data format for output. |
GX_deactivate_session() | status code | Deactivates the interface, frees storage |
File operations
Function | Return value | Description |
GX_select_source(in filename) | status code | Selects a data source for subsequent operations |
GX_select_destination(in filename, in file_format) | status code | Selects a data destination for subsequent operations |
GX_directory(in filename, [out dir_listing]) | status code | Returns a directory of available fields in any data file. |
Data reading/writing
Function | Return value | Description |
GX_get(in handle, in tag, in object-id) | status code | Associates a handle with the referenced data file object. |
GX_put(in handle, in tag, in object-id, in flag) | status code | Writes data associated with a handle into a data file. |
Handle manipulation
Function | Return value | Description |
GX_assign_handle(in handle_lval, in handle_rval) | status code | Assign one handle to the whole or part of another handle. |
GX_release_handle(in handle) | status code | Deactivate the handle and release and storage. |
GX_transfer(in handle, in direction, in type, inout data, in length, in dims) | status code | Transfer data to or from variables in the program. |
NOTES: