RUMP, in early 1980's versions, stored RBS spectral data in a machine dependent format dictated by the FORTRAN compiler on each computer. Files written by one machine were generally incompatible with other machines due to variations in computer architectures and compiler implementation (byte ordering, integer length, real number format, record blocking, etc.). These incompatibilities became sufficiently annoying in the age of networked computers to force a transition in 1984 to a machine independent and extensible format.
Although a few of the old FORTRAN format data files may still exist, they have mostly disappeared since the commercial release of RUMP. Intel architecture versions of RUMP still carry code to read the old data format; continued validity however depends on the whims of non-portable compiler constructs. If necessary, source code for old VAX and PC format converters are available from CGS.
In 1984, a new machine independent and easily extendable data format was adopted and incorporated as the default in released versions of RUMP. The advantages of transparently moving data files between computers quickly guarenteed the general acceptance of the new format. With only very minor changes, this RBS file format has remained for over a decade. The current version is 100% backward compatible ensuring the long term accessibility of archival data.
General concepts for the file format were derived from a study of
the TIFF image file format. If you are familiar with that standard,
the concepts below should be familiar. To meet future requirements,
the specification is designed to be easily extensible with the
definition of new record types. Additional record types may be created
to support new modes of RBS analysis, or other similar analytical
techniques.
RUMP, as of 7/97, reads at the 1.1 format, but by default writes
only to the 1.0 standard (changable using the CONFIG
WRITE_LEVEL command). The additional compression available at
level 1.1 is really only useful for 3D time-of-flight spectral data
which contain extremely long runs of zeros. Unless storage space is a
critical issue, it is recommended that 1.1 features not be used to
maintain back-level compatability.
Within a major revision, however, files should be as much as possible
upward compatible and downward flexible. A reader at a higher minor
revision level must be able to read files from all lower revision level
using default values for any new features or missing data. A reader at
a lower minor revision may or may not be able to read higher revision level
files, but should flag any problems during reading. A high level writer
should attempt to write files which will be fully compatible with all lower
minor revision level by, for example, filling in obsoleted parameters with
default values.
All entries are treated as 32 bit unsigned integers for evaluating
the checksum regardless of their actual types. The sum of all entries in
the record (including the length, type and checksum) must equal
00000000h (overflow ignored).
The differential integer format is efficient for storing integer
values which change only slowly from one element to the next. It
requires byte manipulation capabilities to implement. Records
containing compressed data may be any length less than 1024 words.
If compression would require more than 1024 words, the data must be
written in uncompressed INTEGER or REAL format. Each block of compressed
data must contain exactly 1024 data elements or the number of
elements remaining to be read. For example, 1920 data elements would
be packed with 1024 elements in the first 11h record and 896 elements
in the second.
The first element in each block is the 4 byte value of the first data element.
Subsequent values are encoded as changes from the previous value, either as
byte offset, a 2 byte offsets, or a 4 byte absolute number. The next byte
following one data element is the byte offset (-127 to +127) from the current
value. If the offset is out of range, an 80h is written as the byte offset and
the next two bytes are read as a 2 byte offset (-32767 to +32767). If the
difference is still out of range, an 8000h is written and the next four bytes
give the absolute value of the data element. The process continues until all
1024 bytes have been read or written.
In addition, at revision level 1.1, a zero compression algorithm has been
implemented following the delta compression. This optional compression
reduces runs of 00 bytes to a [FLAG][REPEAT] byte sequence. This
compression is on a record-by-record basis; a record ZeroCompressed is
identified by an initial byte of 80h followed by the [FLAG] byte pattern.
True [FLAG] bytes in the data stream are stored as [FLAG][00] patterns.
Note that enabling of compression will cause a level 1.0 reader to break.
This is unfortunate but accepted for the 10-50% additional compression,
especially for extremely large spectra such as three dimensional microprobe
or time-of-flight spectra.
Revision history
General Specifications
Revision requirements
Major and minor revision levels will be specified in the first record of
the file as defined below. At major revision levels, the format may change
substantially and while a level 2.0 reader may be able to read level 1.x
files, a level 1.x reader will unlikely be able to read the 2.0 files.
Data Representations
|31........24|23........16|15.........8|7..........0| bit order
| Byte 1 | Byte 2 | Byte 3 | Byte 4 | byte order
| offset i | offset i+1 | offset i+2 | offset i+3 | disk storage
|31........24|23........16|15.........8|7..........0| bit order
|S| Exponent | Mantissa | REAL*4
| offset i | offset i+1 | offset i+2 | offset i+3 | disk storage
Record Representations
WORD 1: Record length in words (long integer) WORD 2: Record type (long integer) WORD 3: First data element of record (arbitrary) ..... ..... ..... WORD 3+N-1: Last of N data elements in record (arbitrary) WORD 3+N: Checksum (long integer) Handling of excess or missing data in a record
Differential integer format
Unpacked: 100 120 284 300 93275 93274
Packed: 00000064 14 8000A4 10 80800000016C5B FF
Unpacked: 100 120 284 300 93275 93274
Packed: 00000064 14 8000A4 10 80800000016C5B FF
Compressed: 80 81 81 03 64 14 80 00 A4 10 80 80 81 02 01 6C 5B FF
Record Types
There are only two billion possible record numbers. These will be allocated
on a first come, first serve basis to anyone requesting them. The first
1000h are reserved for RUMP and other Thompsonware software. Record types
above 1000h may be freely used by other applications. We will maintain
lists of allocations requested by other groups. The following blocks are
generally reserved for following uses.
0000h-00FFh - General data and record specifiers
0100h-01FFh - RUMP data files descriptors
0200h-0FFFh - reserved for Thompsonware
Program ID and data block descriptors
Record type 0000h:
Program/Version identifier. This record identifies the
program type and the revision level. The current revision
level is 1.0. The first record of all files must be type
00h record. Subsequent 00h records will be ignored as long
as they continue to specify the same program type. An error
is generated if the identifier is unrecognized. WORD 1: Program specifier. 10211210h ====> RUMP WORD 2: Major/minor version number, packed as 2 short integers Example: 00010000h ====> Revision 1.00 00100003h ====> Revision 2.03
Record type 0001h:
Printed comments. The character string specified in this
record should be printed to the standard output device when
reading the file. Multiple 0001h records may be included in the
file. WORD 1-n: Character Structure WORD 1: string length in bytes (integer) WORD 2-n: packed string
Record type 0002h:
Unprinted comments. Similar to record 01h, but unprinted.
Used to store information such as the generating program
name or the current date/time stamp. Multiple 0002h records
may also be included in the file. WORD 1-n: Character Structure WORD 1: string length in bytes (integer) WORD 2-n: packed string
Record type 0010h:
Data field initiator. Must immediately preceed a
series of type 11h-15h records which actually store the
data array. The data initiator specifies the total number
of elements in the array (after unpacking) and the storage
algorithm. Minimal data compression is implemented at rev
1.0. Additional zero compression implemented at rev 1.1.
Because of the possibility of adding new compression
methods at minor revisions, an unrecognized compression
flag should be reported as an error. WORD 1: Default data packing format (for 11h records). 00 -> unpacked real values
01 -> unpacked integer values
02 -> differential integer format (see below)
03 -> differential and possibly zero compressedWORD 2: Total number of elements in the array (unpacked).
Record type 0020h:
Array field initiator. Must immediately preceed a
series of type 11h-15h records which actually store the
data. The data initiator specifies the array size -- data
is actually stored as a linear array in C format ([0][0],
[0][1], [0][2], ... [1][0], ... [n][m]). Because of the
possibility of adding new compression methods at minor
revisions, an unrecognized compression flag should be
reported as an error. WORD 1: Default data packing format (for 11h records). WORD 2: Number of points in each spectra (columns in C array convention). WORD 3: Number of spectra (rows in C array convention).
Record type 0011h:
Actual data record. Must immediately follow a
type 10h record or a previous 11h-15h record. Each data
record contains a maximum of 1024 unpacked data items
(actual record size may be substantially below 1024 words
if compression was successful). WORD 1-N: Data items (or compressed data items)
Record type 0012h:
Override data record in compression 0 format.
Allows occasional alternate compression records within
the default compression method defined in the 0010h or 0020h record.
Contains 1024 (or number remaining) values. WORD 1-N: Data items
Record type 0013h:
Override data record in compression 1 format.
Allows occasional alternate compression records within
the default compression method defined in the 0010h or 0020h record.
Contains 1024 (or number remaining) values. WORD 1-N: Data items
Record type 0014h:
Override data record in compression 2 format.
Allows occasional alternate compression records within
the default compression method defined in the 0010h or 0020h record.
Contains 1024 (or number remaining) values. WORD 1-N: Data items
Record type 0015h:
Override data record in compression 3 format.
Allows occasional alternate compression records within
the default compression method defined in the 0010h or 0020h record.
Contains 1024 (or number remaining) values. WORD 1-N: Data items
| Record type 0101h: | Identifier. Character string identifier for the data set. |
| WORD 1-n: | Character Structure |
| WORD 1: | string length in bytes (integer) |
| WORD 2-n: | Identifier string |
| Record type 0102h: | Livetime/Clocktime. String containing MCA information. |
| WORD 1-n: | Character Structure |
| WORD 1: | string length in bytes (integer) |
| WORD 2-n: | Livetime/Clocktime string |
| Record type 0103h: | Date. Character string with collection date and time. |
| WORD 1-n: | Character Structure |
| WORD 1: | string length in bytes (integer) |
| WORD 2-n: | Date string |
| Record type 0110h: | Correction factor. Catch all multiplicative correction factor to scale the data. |
| WORD 1: | (REAL) Correction factor |
| Record type 0111h: | Accelerator Parameters |
| WORD 1: | (REAL) Beam Energy (MeV) |
| WORD 2: | (INT4) Z of incident beam |
| WORD 3: | (REAL) Mass of incident beam (AMU) |
| WORD 4: | (INT4) Charge state of beam |
| WORD 5: | (REAL) Total integrated charge (micro-Coulombs) |
| WORD 6: | (REAL) Beam current (nano-Amps) |
| Record type 0112h: | Data Collections Parameters |
| WORD 1: | (REAL) keV/channel (keV) |
| WORD 2: | (REAL) keV of channel 0 (keV) |
| WORD 3: | (REAL) Starting channel of data (really REAL) |
| WORD 4: | (REAL) FWHM detector resolution (keV) |
| Record type 0120h: | RBS spectrum type. Geometry set as follows. |
| WORD 1: | (INT4) Scattering Geometry (see below) |
| WORD 2: | (REAL) Theta - incident target angle (degrees) |
| WORD 3: | (REAL) Phi - 180-scattering angle (degrees) |
| WORD 4: | (REAL) Psi - exit target angle (degrees) |
| WORD 5: | (REAL) Omega - detector solid angle (millisteradians) |
| Notes: | Angle definitions do not follow the same conventions as common RBS texts. This is unfortunate, but historical usage of these definitions in RUMP now prevents change to more precise usage. In particular, the specified scattering angle is really the complement of the scattering angle. Three angles are sufficient to fully define the scattering geometry, but usually only two are given with the third determined by the configuration of the experimental chamber. |
| Phi | Supplement of the scattering angle (180-scattering angle). Backscattering is typically 0-10 degrees. |
| Theta | Angle between the surface normal and the incident beam. Sample normal to incident beam is zero. |
| Psi | Angle between the surface normal and the scattered beam. Zero if sample normal points to the detector. (PSI will be calculated from THETA and PHI if the GEOMETRY is non-zero.) |
| Geometry | In normal operation, only two angles are necessary to define the full geometry. This integer specifies the common scattering geometries. For historic reasons, one is affectionately named Cornell and the other IBM. In the Cornell geometry, the sample tilt axis for THETA is in the plane defined by the incident and scattered beams. In the IBM geometry, the sample normal, incident beam and scattered beams are all coplanar. The sign ambiguity is resolved so that PSI = THETA+PHI. If the sample normal points to the detector, then THETA should equal -PHI. |
| 0 ==> Cornell geometry. | |
| 1 ==> IBM geometry. | |
| -1 ==> No geometry. THETA/PHI/PSI all defined and valid. |
| Record type 0121h: | FRES spectrum type. Geometry set as follows. |
| WORD 1: | (INT4) Scattering Geometry (see below) |
| WORD 2: | (REAL) Theta - incident target angle (degrees) |
| WORD 3: | (REAL) Phi - 180-scattering angle (degrees) |
| WORD 4: | (REAL) Psi - exit target angle (degrees) |
| WORD 5: | (REAL) Omega - detector solid angle (millisteradians) |
| Record type 0122h: | PIXE spectrum type. Parameters undefined at this time. |
| Record type 0123h: | Nuclear reaction spectrum type. Parameters undefined at this time. |
00000005 00000000 10211210 00010000 efddedeb ;Header
0000000b 00000002 00000019 'PC-RUMP data file [v 1.0]xxx' ;Comment
f2e1ec83
0000000d 00000101 00000024 'Ni/NiSi/Si ....' ced4b22f ;ID string
00000008 00000102 0000000f 'LT= 857 CT= 860a' ffec1d26 ;LTCT string
0000000a 00000103 00000017 '18-JUN-1985 12:33:48.48 ' ada0c869 ;Date
00000009 00000111 404145d0 00000002 40800c56 00000002 41200000 ;Accelerator
41000000 fd1eacbc
00000007 00000112 409e6666 3fcccccd 00000000 414282e8 3e5248cc ;MCA
00000008 00000120 00000000 40e00000 41100000 00000000 4059999a ;Geometry
3db6653e
00000004 00000110 3f866666 c0799886 ;CORR Factor
00000005 00000010 00000002 00000400 fffffbe9 ;1024 compressed data
0000010e 00000011 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02
1b 8000c2 800106 80 012d 800107 8000b6 80008e 2b 58 35 0a ce
16 e0 2e a6 35 c6 d1 43 80ff68 5b 0b cb e1 da e5 d7 ed 46 d5
12 b8 1c f8 f4 de d5 13 27 d4 fa ba 04 0b de 2e 16 d8 10 f8
c3 28 05 05 fb de 06 e6 57 b8 06 01 da 06 ad 80008a c0 f7 01
e1 de 1b 34 03 cc 10 e8 06 f3 dd 1e df 25 05 dc ec 34 d9 3b
f5 ca 0e 12 0a e7 26 c3 0c f7 1d 21 cc 26 c5 fa 15 f9 1c e1
......................
00 00 00 00 52dbd061
00000008 00000120 00000000 40e00000 41100000 00000000 4059999a ;MCA parms
3db6653e
00000004 00000110 3f866666 c0799886 ;Correction
00000005 00000010 00000000 00000400 fffffbeb ;1024 reals
00000403 00000011 00000000 00000000 00000000 00000000 00000000 ;Real data
00000000 00000000 be2f8af9 bfe66666 c1033333
4246a0ea 43590000 43f48ea1 4443c57c
4482399a 449af249 44a97333 44b36666
44bb3a84 44c2b8b0 44c24750 44c063a8
....................................
441ce2be 44127e2c 440ba666 43f62f8b
00000000 00000000 53f717e6
| rump_rdw.h | Defines structures and prototypes for the RUMP routines. The
structure SPECTRUM contains all the parameters related
to RBS scattering including data. Pointers to this structure are
used by the API to refer to each spectrum. This include file also
contains the prototypes for the 7 external API routines.
|
| rump_rdw.c | Contains the source code for the API routines. Optional features
are accessible using compiler #define switch options or editing the
code. For standalone applications, NO_EA_MODE and
LOCAL_MODE should be defined.
|
| preload.h | Contains several #defines identifying computer capabilities. This must be loaded before system #include files. |
| mytypes.h | Defines internal variable types. Must be loaded after system #include files. |
#define _POSIX_SOURCE /* POSIX compliance required */
#include "preload.h"
#include <stdio.h>
.... other system include files ...
#include "mytypes.h"
#include "rump_rdw.h"
-DNT -Di486 -DMSC70
to define the operating system (NT, OS2, or UNIX), the architecture (i486
for all Intel chips), and the compiler (MSC70 for the current Microsoft
compiler). On UNIX systems, check the makefile for the appropriate values.
These definitions are used by mytpes.h to select appropriate
routines.
In addition, when compiling rump_rdw.c, the following
definitions must also be included to disable features unavailable in stand
alone programs.
-DLOCAL_MODE -DNO_EA_MODE -DNO_PIPE_MODE
Alternatively, the #define for these may be uncommented in the
source file.
typedef enum _SPECTRUM_TYPE {RBS, FRES, PIXE, NUCLEAR, OTHER} SPECTRUM_TYPE;
typedef enum _GEOMETRY_TYPE {
CORNELL = 0, /* Cornell theta/phi definitions */
IBM = 1, /* IBM theta/phi definitions */
GENERAL = -1 /* Full theta/phi/psi definition */
} GEOMETRY_TYPE;
typedef struct _SPECTRUM {
char filename[PATH_MAX]; /* Filename */
char date[IDCHR]; /* Date spectrum collected */
char ltct[IDCHR]; /* Live time/Clock time information */
char id[IDCHR]; /* Identifier string */
SPECTRUM_TYPE type; /* Type of spectrum */
FLOAT e0; /* Incident energy (MeV) */
int zbeam; /* Atomic Z of incident */
FLOAT mbeam; /* Atomic mass of incident (amu) */
int cbeam; /* |Charge| state of beam */
FLOAT q; /* Total accumulated charge (uC) */
FLOAT current; /* Average beam current (nA) */
FLOAT scale1,scale2; /* Conversion MCA chan # -> keV */
FLOAT first; /* Channel number of first data pt */
FLOAT fwhm; /* Detector resolution (keV) */
FLOAT tau; /* MCA shaping time constant (uS) */
GEOMETRY_TYPE geom; /* Geometry identifier */
FLOAT phi,theta,psi; /* Scattering angles (degrees) */
FLOAT omega; /* Detector solid angle (mSr) */
FLOAT corr; /* Random correction factor */
int nspectra; /* Number of spectra in data */
int npt; /* Number of data points */
int nptmax; /* Dimensioned size of counts */
FLOAT *counts; /* Pointer to actual data */
int dirty; /* Has data changed since read */
int modify; /* Have parameters been modified */
int iddone; /* Is ID been done for this spectra */
} SPECTRUM ;
rump_rdw.c are:
|
|
|
|
|
|
|
cl -DNT -DMSC70 -Di486 -DLOCAL_MODE -DNO_PIPE_MODE -DNO_EA_MODE test.c rump_rdw.c
/* Example usage of the RUMP read routines */
#define _POSIX_SOURCE
#include "preload.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include "mytypes.h"
#include "rump_rdw.h"
/* ===========================================================================
-- Routine to encode the mass, Z and charge state of an ion into a string
=========================================================================== */
static char *BeamCode(int zbeam, REAL mbeam, int cbeam) {
int i;
char *aptr;
static char buffer[20];
static char *ATOM_LIST[] = {"xx","H","He","Li","Be","B","C","N",
"O","F","Ne","Na","Mg","Al","Si","P","S","Cl","Ar"};
sprintf(buffer,"%d%s", (int) (mbeam+0.5), ATOM_LIST[zbeam] );
aptr = buffer + strlen(buffer);
if (cbeam > 0) {for (i=0; i<+cbeam; i++) *aptr++ = '+';}
if (cbeam > 0) {for (i=0; i<-cbeam; i++) *aptr++ = '-';}
*aptr = '\0';
return(buffer);
}
/* ===========================================================================
-- ShowActive(SPECTRUM *buf)
--
-- Prints header block to standard output
-- Filename: c:\rump\example.rbs
-- Identifier: Ni/NiSi/Si Annealed 90 min 295^~o^+C
-- LTCT Text: LT= 857 CT= 860
-- Date: 18-JUN-1985 12:33:48.48
-- Beam: 3.000 MeV 4He++ xxxx.yy uCoul @ xx.yy nA
-- Geometry: General Theta: -180.0 Phi: -109.0 Psi: +000.0
-- MCA: Econv: xxx.yyy xxx.yyy First chan: 0.0 NPT: 1024
-- Detector: FWHM: 35.0 keV Omega: 3.400
-- Correction: 1.0041
=========================================================================== */
static void ShowActive(SPECTRUM *buf) {
char *geometry, *filetype, *beam_string;
/* Create string of form 4He++ for the incident beam */
beam_string = BeamCode(buf->zbeam, buf->mbeam, buf->cbeam);
/* Look and convert geometry ID into the appropriate string */
if (buf->geom == CORNELL) geometry = "Cornell";
else if (buf->geom == IBM) geometry = "IBM";
else if (buf->geom == GENERAL) geometry = "General";
else geometry = "Unknown";
/* Look and convert spectrum type into an appropriate string */
if (buf->type == RBS) filetype = "RBS";
else if (buf->type == FRES) filetype = "FRES";
else if (buf->type == PIXE) filetype = "PIXE";
else filetype = "Unknown";
printf(
" %-4s File: %s\n"
" Identifier: %s\n"
" LTCT Text: %s\n"
" Date: %s\n"
" Beam: %6.3f MeV %-7s% 7.2f uCoul @ %5.2f nA\n"
" Geometry: %7s Theta: %7.2f Phi: %7.2f Psi: %7.2f\n"
" MCA: Econv: %7.3f %7.3f First chan: %4.1f NPT: %4d\n"
" Detector: FWHM: %4.1f keV Tau: %4.1f Omega: %5.3f\n"
" Correction: %6.4f\n",
filetype,
buf->filename, buf->id, buf->ltct, buf->date,
buf->e0, beam_string,
buf->q, buf->current,
geometry, buf->theta, buf->phi, buf->psi,
buf->scale1, buf->scale2, buf->first, buf->npt,
buf->fwhm, buf->tau, buf->omega,
buf->corr);
return;
}
/* ===========================================================================
-- Main routine. Will print out the header for each file on the command line.
=========================================================================== */
int main(int argc, char *argv[]) {
SPECTRUM *spectrum; /* Pointer to spectra structure */
int rcode;
/* Require at least a single argument */
if (argc < 2) {
fprintf(stderr, "Usage: show <file1.rbs> <file2.rbs>\n");
return(EXIT_FAILURE);
}
/* Go through each argument on command line showing the header information */
argc--; argv++;
while (argc) {
if ( (spectrum = RbsReadSpectrum(*argv, NULL, &rcode)) == NULL) {
fprintf(stderr, "ERROR: Read failure on %s (%d)\n", *argv, rcode);
} else {
ShowActive(spectrum); /* Print identifier */
RbsFreeSpectrum(spectrum);
}
argc--; argv++;
}
return(EXIT_SUCCESS);
}