Genie IO

There are three ways of reading/writing data in GENIE

Via a loaded MODULE

The MODULE command and it related functionality are discussed in a separate chapter. If an existing FORTRAN subroutine or C function is available to read the file into e.g. a few arrays, then this program can easily be modified to place these arrays into a GENIE Workspace for display or further manipulation. An example of this is included in the GENIE distribution in the form of the MARI "get_2d_file" routine, which is loaded in the module "mari.so" - the source for this is in the file "mari_get_2d_file.f" in the library directory (usually /usr/local/genie/library). As GENIE uses FORTRAN IO itself, you should not just read or write to an arbitrary FORTRAN logical unit in case you cause a clash - instead use "INQUIRE(UNIT=I,CONNECT=C)" in a loop and test for logical C being .FALSE. indicating that unit I is available.

Via the GET and PUT commands

These commands read files which GENIE "knows about" (i.e. those recognised by the FILETYPE command) and writes variables in pre-defined formats. The current known file types are:

GENIE can write HDF format files, but this facility is for demonstration only at present; however it may be useful if you have e.g. an HDF file browser and wish to use it to examine GENIE data. Basically, arrays map to Scientific Data Sets (SDS) and Workspaces to Vgroups. Proper HDF I/O facilities will be added when the NEXUS format is standardised.

If a file if of a recognised format, the LIST command will give a brief description of the file layout. All the above formats support the idea of numbered "blocks" in a file - the Open GENIE ASCII and Intermediate files additionally allow blocks to be named. The usual reading syntax will be:

WK1 = GET(2,"datafile.dat")

and, for those supporting named access, additionally:

WK1=GET("vanadium", "calib.dat")

These will read block 2 from file "datafile,dat" and block "vanadium" from "calib.dat". If several reads are to be made form the same file, the SET/FILE/INPUT command can be used to provide a default e.g.

SET/FILE/INPUT "datafile.dat"

WK1=GET(2)

WK2=GET(4)

The NBLOCKS command will give you the number of blocks in the file - for an ISIS RAW file a "block" is considered a single spectrum.

Via the ASCIIFILE command

The ASCIIFILE command provides a flexible way for reading and writing ASCII data files from GENIE. Data can be written in both free and fixed format, and the syntax used is similar to the printf/sscanf syntax in "C" The basis steps involve calling ASCIIFILE:OPEN() and storing the returned "file handle", reading/writing on the file using the "file handle" and, finally, calling ASCIIFILE/CLOSE to free the "file handle"

For our first example we will just read a single number from a file

H=ASCIIFILE:OPEN("test.dat") # open file and store "file handle" in H

N=ASCIIFILE:READFREE(H) # read single number, store in variable N

ASCIIFILE/CLOSE H # close file

Once the file is open, many sorts of operations can be performed:

NLINES=ASCIIFILE:LINES(H) # Number of lines remaining in file from

# current position (=total in file if we have just opened it)

ASCIIFILE/SKIP H # Skip the next input line

ASCIIFILE/SKIP H 5 # Skip the next 5 lines

A line is usually a stream of characters terminated by a line feed ("\n"), but this may be modified by passing the DELIMITER parameter to OPEN. For example, if your lines are terminated by a "carriage return", you should type:

H=ASCIIFILE:OPEN("test.dat", DELIMITER="\r")

ASCII files may also have comment lines, which are those lines which start with a special character. By default there is no comment character, but one can be specified with the OPEN command.

H=ASCIIFILE:OPEN("test.dat", COMMENT="!")

Note that the SKIP and LINES operations ignore comment lines in their calculations.

Free Format Read

A free format file is one where data items are separated by one or more non-data characters. Usually the non-data characters are "white space" (i.e. blanks and tabs), and often the data is columns of numbers, but this need not be the case. As genie allows you to read blocks of lines at a time, the number of columns in a file need not be the same throughout the file.

An example of a free format read would be:

WK1=ASCIIFILE:READFREE(H, "X,Y,E", $WHITESPACE, 10)

The string "X,Y,E" tells GENIE to read three data arrays, and assign these to fields X,Y and E of the Workspace variable WK1. The items will be separated by "white space" ($WHITESPACE is a special GENIE constant), and there will be 10 of them in all. Instead of $WHITESPACE, you can pass any valid regular expression (in fact $WHITESPACE is defined as "[ \t]+", meaning "one or more of blank or tab"). If you passed "[!]+" you would be saying that your data items were separated by "one or more exclamation marks"

The READFREE operation usually returns a workspace; however, if no field names are specified it will only read the first item on a line and return an array.

Fixed Format Reads

In a fixed format file, data items appear at specific places on a line and may not necessarily appear separated from each other to the naked eye. An example of a fixed format read would be

WK1=ASCIIFILE:READFIXED(H, "X,Y", "%4f%5f",4)

This notation is "sscanf" style. Characters in the input line are matched against those in the string, and the "%" character is used to indicate a data item for processing. The above would read two touching floating point number, the first being 4 characters long and the second 5. A space in the format string matches one of more spaces in the input line

%6f Matches a floating point number of total width 6

%s Matches a string of non-whitespace characters

%10c Matches ten characters, including white space

%d Matches an integer

%4d Matches an integer of width 4

%*f Skips a float in the line

%% Matches a % character

To return a Workspace containing all the data read in so far, use:

A=ASCIIFILE:DATA(H)

Note that A will only contain those items for which you specified a field name e.g.

N=ASCIIFILE:READFREE(H)

ASCIIFILE/READFREE(H,"X,Y",$WHITESPACE,N)

ASCIIFILE/READFREE(H,"Z",$WHITESPACE,2*N)

A=ASCIIFILE:DATA(H)

A will contain fields "X,Y,Z", but will not contain N.

A=ASCIIFILE:DATA:RESET(H)

will return A as above, but will clear out the accumulated data so a further call to ASCIIFILE/DATA will only include later READFREE or READFIXED entries