Guide to the GU Toolkit

Contents

  1. The Basics
  2. User's Guide
  3. Programmer's Guide
  4. Administrator's Guide

Chapter I. The Basics

The GU Toolkit

The Geophyscial Utilities (GU) toolkit is a programming library for accessing geophysical data and programs (tools) that use the library. GU was a product of the Geotechnology Research Institute (GTRI).

Using GU Parameters

The GU library uses parameters to describe geophysical surveys. A parameter is a line of the form

	id.name=value comments

where everything but the equals sign is optional. Case is ignored for the parameter name and id. The value must immediately follow the equals sign or it is treated as comments.

For instance, a parameter called 'units' might be specified as

	units=feet

or

	units=meters

A parameter value can be an actual value, a question mark (in which case the user is prompted for a value), or the word 'default' (in which case a default value is used). A default value will also be used if the parameter is left unspecified.

A parameter value may include spaces or span multiple lines only if it is surrounded by double quotes, as in

	units="feet per second"

The 'id' of a parameter is used when a parameter can have qualified meanings. For example,

	velocity.units="feet per second"
	depth.units=feet

would set different values to the 'units' parameter for velocity and depth. If an id is not specified, the parameter applies to all ids.

If a parameter is specified more than once, the last specification is used. If an unknown parameter is specified, it is ignored. Blank lines are ignored. Parameter names, ids, and default values are set by the program or by the library. Generally, the user may specify parameters on the command line or in a file named on the command line.

In this guide, parameters used by the GU tookit will be listed with their default values.

GU Surveys

The central concept of the GU toolkit is the survey. A survey is a geophysical data set stored as a sequence of traces. A trace may contain a header and samples (data values).

Most GU tools operate on surveys. For instance, the tito tool can make a copy of a survey.

Surveys are defined by parameters which specify their format, their location and other necessary information. The following is a list of survey parameters and their defaults.

Interactivity

The GU toolkit has some ability to run in both interactive and batch modes. In interactive mode, a program can ask the user for information, such as the name of a tape drive to use. A program runs in batch mode when it is run "in the background" or submitted to a job queueing system. In this case, the program cannot directly communicate with the user and must use some other means.

The GU library provides programs with the ability to determine if they are in batch or interactive mode. The library will also behave differently in the two situations. For example, in interactive mode the user will be prompted for a tape drive, while in batch mode, the user will be sent e-mail and must respond with a separate command.

The following parameter can be interactive.

verify=no
If set to yes, parameter information about the survey will be printed for the user. In interactive mode, the user will be asked whether this information is correct.

Format Handling

The GU library can recognize trace-by-trace data in standard SEG-Y format or in similar formats, such as flat files without headers.

The survey format is described generally by:

nsamples=0
number of actual samples per trace; if less than one, will be read from reel header
sample_type=ibm32
sample type (int16 for 16-bit integer, ibm32 for 32-bit IBM floating point, ieee32 for 32-bit IEEE floating point etc.)
reel_headers=3200,400
reel header record sizes in bytes
trace_header=240
trace header size in bytes

The nkeys parameter specifies how many key values (line number, shot number, etc.) are stored in each trace header:

nkeys=0
number of keys (maximum of 3)

The locations of each key in the trace header is determined by (byte addresses start from 1, byte length can be 2 or 4):

pkey_loc=17,4
primary key address and length
skey_loc=17,4
secondary key address and length
tkey_loc=17,4
tertiary key address and length

Key values will be calculated based on modifiers given by:

pkey_mods=%0,x1.0,+0
see below
skey_mods=%0,x1.0,+0
see below
tkey_mods=%0,x1.0,+0
see below

If a key's modifiers are specified as %M,xN,+A, where M and A are integers and N is a real number, then the actual key value will be calculated from the key value in the trace header as [actual = (stored MODULUS M) x N + A]. M is ignored if it is zero. A may be specified as +A or -A. The result is an integer.

Device Handling

The GU library can use local or remote disk files or tape drives.

Device parameters are:

device=tape
device type (file or tape)
names=1
list of file names or tape labels
item_size=1.5G
maximum size of one output file or tape

The 'device' parameter is specified as device=[[user@]host:]type where 'type' is tape, file, carousel or stacker, 'host' is the remote host name if the device is remote, and 'user' is the remote user id to use if it is different from the local user id. Note that versions of the library installed outside GTRI can not use remote devices.

The 'names' parameter is specified as a comma- or space- separated list of file names or tape labels. If spaces are used the names must be enclosed in double-quotes.

The 'item_size' parameter specifies the maximum number of bytes to write to one output file or one output tape before going to the next one.

For example, to use a tape drive attached to the host 'gtri14' from another computer, using tapes labeled tape1, tape2, and tape3:

	device=gtri14:tape
	names=tape1,tape2,tape3

To access a file on host 'gtri4' as user 'joe':

	device=joe@gtri4:file
	names=/home/joe/myfile

A user has permission to access a remote device if the user has permission to rlogin to that host. Remote devices are always accessed in batch mode, even if the rest of the program operates interactively.

At the GTRI SX-3 installation, tapes will be mounted and unmounted by a tape operator (the user is not involved). If a Lago DataWheel Exabyte tape carousel is available and configured appropriately, tapes will automatically be mounted and unmounted (again the user is not involved).

Otherwise, the user mounts and unmounts tapes. In interactive mode, the user will be prompted for the tape drive to use; in batch mode, tape requests are made with e-mail (the mail(1) command).

To check for pending tape requests, enter mail on the command line. A request will be a mail message looking something like:

Mount input tape x101 then type: respond 3333 [drivename]

After the tape is mounted, type respond 3333 as requested, followed by the path to the tape drive (such as /dev/rst1). The '3333' is just an identifier. Requests to unmount a tape are similar, but do not require you to type a 'respond' command.

If a stack-loading device is used, the user will be asked to mount or unmount stacks rather than individual tapes.

The following parameters are specific to tape drives:

tape_eject=no
If yes, and the tape drive is capable, the tape will be ejected when the program closes the drive. Otherwise, the tape is left in the drive. This parameter is ignored for operator, robotics or stack-loader systems.
tape_density=high
Specifies high or low tape density. For the SX-3, high density means 6250 bytes per inch (bpi), and low density means 1600 bpi. For carousels, high density means Exabyte 8500 and low means Exabyte 8200. This parameter is ignored in all other cases, as the user can specify the appropriate tape drive name.
tape_short=pad
How to use short tape records (ignore, pad or error).
tape_long=truncate
How to use long tape records (ignore, truncate or error).

Statistics Generation

The GU library can generate statistics about traces read from input surveys. The level of statistics kept can be none, line statistics or shot statistics. The terms 'primary key' and 'line', and 'secondary key' and 'shot' are used interchangeably, even though the keys might be something else (for instance, the secondary key could be CDP).

Statistics generation uses the format handling parameters to find the key values and is controlled by:

stats_level=0
statistics generation level (0 - 2)
stats_file=?
name of file to which to write statistics

If stats_level is 0, no statistics will be kept. If stats_level is 1, line statistics will be kept (number of traces per line etc.). If stats_level is 2, line and shot statistics will be kept (number of traces per shot etc.). When the program is finished, stats_file will contain the statistics in an ASCII (human-readable) format.

Quality Control

If a survey is opened for reading, the GU library can enforce quality control on the traces read from that survey. If quality control is on, the library can skip unselected and duplicate traces and fill in missing traces with zeros. This allows the user to process a subset of a survey, enforce a regular data grid or ensure that all traces fall within certain limits.

Quality control uses the format handling parameters to find key values in each trace header. The following parameters select traces for quality control:

pkey_select=1,1,1
first and last desired primary key values and desired increment
skey_select=1,1,1
first and last desired secondary key values and desired increment
tkey_select=1,1,1
first and last desired tertiary key values and desired increment

For example, if tkey_select=1,500 and receiver #5 is missing, quality control can give the program actual traces #1 - #4, then a null trace in place of trace #5, and then the rest of the actual traces.

The following parameter specifies the type quality control:

qc=none
quality control (none, fill, discard or grid)

If qc=none, no quality control will be done, and the program will receive traces exactly as they are on the device. If qc=fill, quality control will fill in traces that are selected but missing from the device. If qc=discard, quality control will discard traces that are out of the selected range and duplicate traces. If qc=grid, quality control will both fill null traces and discard unselected ones.

Note that for qc=grid, the discard will be performed first and the fill second. The advantage of this is that if a trace is misplaced before its actual location, it will be discarded instead of everything in front of it being filled. The disadvantage is that if the last desired trace is missing, qc will read the entire remainder of the survey before filling it in.


Chapter II. User's Guide to the GU Tools

Using The GU Tools

The GU Tools are programs that use the GU library for accessing geophysical data. Tools currently available include:

tito
Tito can copy, reformat and perform other simple processing.
smooth3d
Smooth3d does spacial smoothing along the x-y-z axes of a 3-Dimensional data set.
ddsegy
Ddsegy interactively dumps trace headers and data.
intsegy
Intsegy linearly interpolates a gridded survey.
sortsegy
Sortsegy copies multiple input/multiple output.
xsegy
Xsegy displays traces in an X/Motif window.
dwi
Dwi facilitates datawheel (Exabyte carousel) interaction.

All tools use the same command-line interface. All use parameters to specify their input and output. Parameters may be specified directly on the command line, as in

	ddsegy device=gtri14:tape

or as an ASCII file containing parameters, as in

	ddsegy myparms

(where "myparms" is a file containing a list of parameters), or both,

	ddsegy myparms verify=yes

By convention, each tool specifies its input survey as "in" and its output survey as "out". A parameter file for tito could be:

	in.device=tape
	in.names=mytape1,mytape2
	out.device=file
	out.names=/me/myfile

If no arguments are given, the tool prints a list of its parameters and quits.

The default data format is SEG-Y: IBM floating point data, 3200-byte and 400-byte reel headers, and 240-byte trace headers. If your data is different, and you don't specify the format, the tools may give strange results.

smooth3d

Smooth3d does spacial smoothing along the x-y-z axes of a 3-Dimensional data set. Smoothing is done by performing one dimensional convolutions with normalized cosine filter. The filter length must be specifies separately for each axis.

smooth3d requirements:
o nkeys=2;
o pkey_select, and skey_select is mandatory;
in other word, input survey must be a segy file.
o temp_directory should has enough space to hold scatch file.

smooth3d parameters:

        skey_filter_len=1       : length of the filter on skey
        pkey_filter_len=1       : length of the filter on pkey
        samp_filter_len=1       : length of the filter in t or z
        smooth=slowness         : smooth velocity or slowness in z
        temp_directory=.        : directory for scratch file
smooth3d surveys:

        in.       : input survey
        out.      : output survey
Sample smooth3d input parameter file:

smooth3d.skey_filter_len=3
smooth3d.pkey_filter_len=3
smooth3d.samp_filter_len=3
smooth3d.smooth=velocity
smooth3d.temp_directory=/harc/gtri/amazon2/smooth3d

in.device=file
in.names=/harc/gtri/amazon2/smooth3d/testcase.segy

pkey_loc=81,4
skey_loc=85,4
nkeys=2
pkey_select=1,1000,1
skey_select=1,200,1

out.device=file
out.names=/harc/gtri/amazon2/smooth3d/testcase.smooth.segy
out.nkeys=2

ddsegy

Ddsegy reads traces from an input survey and interactively prints the reel header, trace headers, and trace data.

For example, to dump a tape, try ddsegy names=mytape.

intsegy

Intsegy linearly interpolates an input grid to an output grid. It is useful mainly for expanding a sparse velocity grid, but can interpolate any survey.

Both surveys must have the same number of trace header keys, and key increments must have the same sign for both surveys.

If there are no keys in the trace header, intsegy just linearly interpolates from one sample rate to another (both surveys are assumed to have the same trace length, but a different number of samples per trace means a different sample rate). If there is one key in the trace header, intsegy will use that value to interpolate between traces as well as between samples, and so on.

The key location and selection parameters will be used to determine the input and output grids. Quality control should be used to enforce the input grid unless the input has no trace headers.

sortsegy

Sortsegy sorts trace data. It reads from any number of input surveys, and sorts the data to any number of output surveys. The first input survey is specified as 'in', the second as 'in2', the third as 'in3' and so forth. The output surveys are specified as 'out', 'out2', 'out3' and so forth. All surveys must be available simultaneously.

Sortsegy uses the parameters

nin=1
number of input surveys
nout=1
number of output surveys

as well as format handling parameters such as nkeys, nsamples and so forth.

Sortsegy is unusual in that it uses pkey_select, skey_select, and tkey_select for the output surveys as well as the input surveys. For the input surveys, these parameters specify which traces are located in the survey. For the output surveys, these parameters specify where the traces should go. These parameters must be specified for all surveys.

Sortsegy is best used with quality control on, to guarantee the desired traces are available. Sortsegy can be used to reformat the data, because reel_headers, trace_header, pkey_loc etc. can be different in the output surveys and the input surveys.

For example:

	nin=2
	nout=2
	nkeys=2		line and cmp
	qc=grid		turn quality control on

	= first input survey has line 1, cmps 1 - 500
	in.device=file
	in.names=/disco/me/file1
	in.pkey_select=1,1
	in.skey_select=1,500

	= second input survey has line 2, cmps 1 - 500
	in2.device=file
	in2.names=/disco/me/file2
	in2.pkey_select=2,2
	in2.skey_select=1,500

	= write cmps 1 - 250 from both lines
	= to the first output survey
	out.device=tape
	out.names=mytape1
	out.pkey_select=1,2
	out.skey_select=1,250

	= write cmps 251 - 500 from both lines
	= to the second output survey
	out2.device=tape
	out2.names=mytape2
	out2.pkey_select=1,2
	out2.skey_select=251,500

xsegy

Xsegy displays survey data in an X/Motif window.

Xsegy accepts all the standard survey parameters. It also accepts all the standard X-window options, such as -fg, -bg, and -g. In addition, it accepts the following parameters:

plot_title=Traces
title to display above plot
nte=1
number of traces per ensemble
dx=0.0
trace spacing (for annotations only)
dz=0.0
sample rate (for annotations only)

Also, xsegy accepts the following X-window options, which can only be specified on the command line:

The above X-window options have X-resource equivalents, which can be placed in a user's .Xresources file:

	Option                  Resource
	------                  --------
	-pos_color color      *positiveColor: color
	-neg_color color      *negativeColor: color
	-zero_color color     *zeroColor: color
	-annot_color color    *annotationColor: color
	-annot_font font      *annotationFont: font

The xsegy window has three areas: a menu bar, a scrollable plot area, and a message area.

The menu bar contains four menus: Display, Edit, Picks, and Help. The Display menu allows you to select an ensemble to display or to quit. The Edit menu allows you to change the colors used to display data and to change the plot parameters (image or wiggle trace; wiggle trace gain, clip, and agc; number of samples and traces to display on screen; and the plot title). The Picks menu allows you to store and clear horizon picks. The Help menu provides on-line help.

The plot area has a plot title, scrollbars for scrolling through samples and traces, and a plot of the data. To pick a horizon, click the left mouse button over the various points on the horizon. Clicking the middle mouse button erases the last pick. Shift-clicking the left mouse button prints the trace number, sample number, and amplitude at that location. Shift-clicking the middle mouse button prints the complete trace header for the trace at that location.

The message area displays warnings, error messages, and the trace information gotten by shift-clicking the mouse over the plot.

Remember to set your DISPLAY environment variable before using xsegy.

dwi

The Lago DataWheel is an 8mm (Exabyte) tape carousel. The datawheel mechanically imports tapes into the carousel, mounts tapes into tape drives, unmount tapes from tape drives, and exports tapes from the carousel.

The datawheel has several parts: the tape carousel; the mechanics for rotating the carousel and loading and unloading tapes; one or two tape drives; and a serial control line for sending commands to the carousel via computer.

The user interface developed at GTRI, called dwi for DataWheel Interaction, provides a menu-driven or command-line interface. Entering dwi at the command line will bring up the dwi menu:

Commands (may be abbreviated):
	import [tape label] [slot#]: import tape into slot
	export [tape label]        : export tape from slot
	mount [tape label] [drive#]: mount tape into drive
	unmount [tape label]       : unmount tape from drive
	status                     : report carousel status
	quit                       : exit program
Command?

To import a tape into the carousel, use the import command with the tape label to be used. The slot number is optional; if present, the tape will be imported into that slot (1 - 54), and if not, the first available slot will be used. For example:

	Command? import mytape

To export a tape from the carousel, use the export command with the label of the tape to be exported. The tape must be in its slot for export to work (in other words, make sure the tape is not mounted).

To mount a tape from the carousel into a tape drive, use the mount command with the label of the tape to be mounted. The drive number is optional; if present, the tape will be mounted into that tape drive (1 or 2), and if not, the first available drive will be used.

To unmount a tape from a tape drive into the carousel, use the unmount command with the label of the tape to be unmounted.

To list the status of the datawheel, along with a map of the carousel's contents, use the status command.

To exit the dwi menu, use the quit command.

Datawheel commands can also be executed directly at the command line instead of from the menu. Simply type dwi followed by the desired command and its arguments on the command line. For example:

	dwi import mytape

will import mytape into the carousel without engaging the dwi menu.


Chapter III. Programmer's Guide to the GU Library

Using the GU Library

The Geophysical Utilities (GU) library is a collection of C-language routines for accessing geophysical data in a trace sequential format such as SEG-Y, along with some support routines. The library's advantages are:

* device independence: a program that uses the library receives traces in sequential order. The type of device (tape drive or disk file) and its location (local or remote) is irrelevant; the user or programmer specifies the device, and the library routines open, read, write, and close the device appropriately. This means, for example, that a program does not need to check for tape errors, or be recompiled to read from a disk file instead of a tape drive.

* enhanced capabilities: the library provides some capabilities to a program that uses it, including generation of statistics about surveys, quality control, and horizon pick handling.

* expandability: the library will be expanded as needed. New types of devices, or other seismic data formats, can be added. Programs will be able to use these extensions with few, if any, changes to the program code; linking with the latest version of the library will take care of it.

The GU library can be divided into three general sections: survey handling, device handling, and support routines. Survey handling routines are the only ones that most applications will be interested in, as they read and write surveys. The device handling routines are a lower level of I/O that is available but will not normally be used directly. Support routines include routines for pick handling, string manipulation, user interaction, type conversion, and parameter parsing.

All GU library routines begin with the prefix "gu". All GU types begin with the prefix "Gu", and all GU constants begin with "GU" (or "Gu" in the case of bit flags).

All routines return 0 on success and -1 on error unless otherwise noted. All routines print an error message on error.

Programs using the library must include the header file gu.h, which defines data types and constants used by the library and declares all library routines. Programs must also link in the library libgu.a.

At GTRI, the header file is in /harc/gtri/local/include and the library is in /harc/gtri/local/lib.`hostname`. For example:

cc -c -I/harc/gtri/local/include myprog.c cc -o myprog -L/harc/gtri/local/lib.`hostname` myprog.o -lgu

The header includes the system header files stdio.h, unistd.h and stdlib.h in order to declare system routines which are not located in the same header on every machine. For example, including the GU header guarantees that _exit(), exit(), malloc(), free(), sleep(), and sprintf() are declared.

Send comments, bug reports etc. to Ken Gaillot (j63kega@gtri.harc.edu).

Survey Routines

The GuSurvey type, defined in the GU header file, describes sequential-trace surveys. The GuSurvey structure is intended to be opaque to the programmer, but does make information available, such as the number of samples per trace and number of bytes per trace header. A survey is declared like any other variable; for example,

	GuSurvey in, out;

declares two surveys.

The header file also defines the GuSegyHeader type which describes the SEG-Y standard reel headers:

typedef struct {
	char ebcdic[3200];
	int job_number, line_number, tape_number;
	short traces_per_line, aux_traces_per_line;
	short sample_interval, recorded_sample_interval;
	short samples_per_trace, recorded_samples_per_trace;
	short data_type;
	short cdp_fold, sorting_method, vertical_sum;
	short sweep[8];
	short data_correlated, gain_recovered;
	short amplitude_recovery;
	short measurement_system;
	short impulse_polarity, vibratory_polarity;
	char optional[340];
} GuSegyHeader;

The following routines operate on surveys.

GuSurvey *guCreateSurvey(char *id, char **argv, char *mode)

Defines a survey from a parameter list 'argv'. The survey will be initialized for reading if mode is "r" or writing if mode is "w". The 'id' is used to qualify parameters so that multiple surveys may be defined from the same parameters. A survey needs to be created only once. It can be opened and closed as many times as needed afterwards.

This routine allocated dynamic memory for use by the survey. When the survey is no longer needed, the program may call guDestroySurvey() to free this memory.

Returns a pointer to the survey on success and NULL otherwise.

void guDestroySurvey(GuSurvey *survey)

Frees all dynamic memory allocated by guCreateSurvey().

int guOpenSurvey(GuSurvey *survey)

Opens a survey. Note that the number of samples per trace, specified in survey->nsamples, defaults to zero, which means 'read from reel header'. Output surveys don't read a reel header, so programs should ensure nsamples is set. For example:

GuSurvey *out;

out = guCreateSurvey("out", argv, "w");
if (out->nsamples == 0) {
	/* either return an error or set out.nsamples */
}
guOpenSurvey(out);

void guCloseSurvey(GuSurvey *survey)

Closes a survey. Every opened survey should be closed when it is no longer needed.

int guReadTrace(GuSurvey *source, char *trace)

Reads a trace from an input survey. Returns -1 on error, 0 on end-of-media, +1 on success, and +2 on success with a null trace. This allows the program to loop such as:

int main()
{
	GuSurvey *survey;
	char trace[10000];

	survey = guCreateSurvey("in", ++argv, "r");
	guOpenSurvey(survey);
	while (guReadTrace(survey, trace) > 0)
		/* process trace */;
	guCloseSurvey(survey);
}

int guWriteTrace(GuSurvey *dest, char *trace)

Writes a trace to an output survey.

void guSurveyHelp(void)

Lists all survey parameters and their meanings. Useful for programs with a help option.

int guTraceSize(GuSurvey *survey)

Returns the number of bytes per trace, including the trace header and data. This is useful, for example, when allocating space for traces.

int guCopyTrace(GuSurvey *is, GuSurvey *os, char *it, char *ot)

Copy input trace 'it' to output trace 'ot', given that 'it' came from survey 'is' and 'ot' is going to survey 'os'. Reformat trace headers and data if necessary.

GuSegyHeader *guGetSEGYHeader(GuSurvey *survey)

Returns a pointer to the space used for reading and writing reel headers. Reel headers are automatically read from and written to surveys; the program does not need to request it. This routine is provided in case a program wants to examine or modify the reel header. If a non-SEG-Y reel header is used (in other words, if reel_headers is not 3200,400), this routine returns NULL.

This routine can be called anytime after the survey is defined. For an input survey, a header will not be read until the survey is opened, so the pointer returned by this routine should not be used until after the survey has been opened. For an output survey, a header will be written when the survey is opened, so the header pointed to should be set before the survey is opened.

For output surveys, the header is initially null (all zeros). If the program wishes the header to contain values, it must set them itself.

void guCopySurveyHeader(GuSurvey *dest, GuSurvey *source)

Copies the reel header from source to dest. This routine can be used to set the header that guOpenSurvey() will write to an output survey. For example:

guOpenSurvey(survey_in, 0);
guCopySurveyHeader(survey_out, survey_in);
guOpenSurvey(survey_out, 1);

This routine will copy whatever reel headers have been specified in the surveys' parameters.

void guMakeEBCDICHeader(GuSegyHeader *hdr)

This routine fills in the EBCDIC reel header of 'hdr'. Currently, it justs puts in the SEG-Y standard template, without filling in any values.

void guGetTraceKeys(GuSurvey *survey, char *trace, int key[])

Gets key values from trace header and puts them in 'key'. Note that the number of keys retrieved is survey->nkeys.

void guSetTraceKeys(GuSurvey *survey, char *trace, int key[])

Sets key values in trace header to those in 'key'. Note that the number of keys stored is survey->nkeys.

int guSurveyNum(GuSurvey *survey, int k)

Returns the number of selected items for key k, where key 0 is the primary key, key 1 is the secondary key, and key 2 is the tertiary key. Be sure k is less than the number of keys specified by survey->nkeys.

Pick Routines

The header file defines two types for horizon picking, GuPoint and GuPick:

typedef struct {
	int key[3];	/* header keys of point */
	int sample;	/* sample number of point */
	int interp;	/* true if point is interpolated */
} GuPoint;

typedef struct {
	char name[20];	/* name of horizon */
	int thickness;	/* line thickness for display */
	unsigned long color;	/* color for display */
	int nalloc;	/* number of points allocated */
	int nused;	/* number of points used */
	GuPoint *point;	/* sequential array of points */
} GuPick;

The following routines aid in pick handling.

GuPick *guReadPicks(char *filename, char *pickname, int *npicks, int all)

Read picks from a file. If all is nonzero, read all points, including interpolated points, otherwise read only points picked by the user. If pickname is NULL, read all picks from the file, otherwise read just the one specified by pickname. Returns number of picks read in npicks if npicks is non-NULL. Returns pointer to list of pick structures (which will be allocated) on success, and NULL otherwise. To free the dynamic memory, use guFreePick() on each pick followed by free() on the returned pointer.

int guWritePicks(char *filename, char *groupname, GuPick *pick, int npicks)

Write a set of picks to a file.

void guNewPick(GuPick *pick, char *name, int thickness, unsigned long color)

Initializes a pick structure (with no picks). Does not allocate the structure, just initializes values.

int guPickPoint(GuPick *pick, int key[3], int sample, int interp)

Add a point with the specified keys to the pick structure (at the end of the point list). Interp should be zero for user-picked point and nonzero for interpolated point.

void guUnpickPoint(GuPick *pick)

Remove the last point added to the pick structure.

void guFreePick(GuPick *pick)

Free any pick points associated with the pick. Does not free the pick structure itself. The pick structure can be used again (such as with guPickPoint()) as if it had just been initialized.

Device Routines

The survey abstraction sits on top of a lower layer, the device layer. Most programs can ignore this lower layer but it is documented here for completeness.

The header defines the following constants for device flags:

It also defines the following combinations of flags:

The header defines the GuDevice type, which includes the following fields:

typedef struct {
	char **name;		/* file names/tape labels */
	char *user;		/* remote user name or NULL */
	char *host;		/* remote host name or NULL */
	unsigned int flags;	/* device flags (see above) */
	unsigned int megs;	/* max. megabytes per item */
	int nitems;		/* # files or tape labels */
	int recsize;		/* bytes per data record */
	int nhdrs;		/* number of headers */
	int *hdrsize;		/* size of each header */
	char *hdr;		/* space for all headers */
	...	/* includes other private fields */
} GuDevice;

The following routines act on devices.

int guOpenDevice(GuDevice *dev)

Opens a device. The GuDevice fields described above must be initialized correctly. The fields may be examined, but should not be changed, after the device has been opened.

The device name field of the GuDevice structure contains a list of names. For disk files, these are the full path names of the files that make up the data set. For tape drives, these are the labels of all the tapes that make up the data set.

The host and user fields are used to specify a remote device. If host is NULL, the device is local, otherwise host specifies the computer on which the device is located. If user is NULL, the local user name will be used on the remote machine, otherwise, user specifies a user name to use on the remote machine. Remote permissions are checked against the /etc/hosts.equiv and ~/.rhosts files as, for example, rlogin(1C) does.

The nitems field is the number of disk files or tape labels.

The flags field is the bitwise-OR of the various device flag constants. For example, if flags = GuTape|GuRead, then the device is an input tape drive.

The megs field is the maximum number of megabytes that can be stored on one output disk file or tape. When this maximum is reached, the library will advance to the next item.

The recsize field is the number of bytes per data record.

The data set is assumed to have nhdrs=N headers, whose sizes are hdrsize[0] ... hdrsize[N-1]. When a device is opened for input (output), the headers are all consecutively read into (written from) hdr.

If the device type is set to GuDisk, the data set is considered to exist in a set of disk files. Multiple disk files are supported so that a single data set can be larger than the maximum file size. The data set stretches sequentially across the disk files named. Each disk file begins with a copy of the headers. On input, a new file is opened if the current one is at end-of-file. On output, a new file is opened if the current one reaches the output size limit 'megs'.

If the device type is set to GuTape, the data set is considered to exist in a set of tapes. The data set stretches sequentially across the tapes named. Each tape begins with a copy of the headers. For input tapes, GU will return the header blocks from the first tape in a set and ignore the rest. For output tapes, GU will write the same header blocks to the beginning of each output tape. On input, a new tape is mounted when two file marks are found (single file marks are ignored). On output, a new tape is mounted when the output size limit 'megs' is reached. If an error occurs reading a record, the read routine will backspace and try again up to three times; if it still gets an error, it will try reading the next record; if three records fail, it returns error.

If the device flag GuEject is set, the tape drive will be put offline when it is closed.

Short records will be handled in one of three ways: with GuErrorShort, an error condition will be returned; with GuIgnoreShort, the record will be skipped; and with GuPadShort, the record will be padded to the desired length with zeros.

Long records will be handled similarly: with GuErrorLong, an error condition will be returned; with GuIgnoreLong, the record will be skipped; and with GuTruncLong, the record will be truncated to the desired length.

Four tape handling systems are supported: user, operator, robotics, and stacker. Operator tape handling is used on SX machines. Robotics tape handling is used if the GuCarousel flag is set. Stack-loader tape handling is used if the GuStacker flags is set. User tape handling is used otherwise. Robotics tape handling works only with Lago DataWheel Exabyte tape carousels, and only if the library has been configured appropriately. With user tape handling, the user will be asked to mount and dismount tapes. In interactive mode, the user will be prompted at the user's terminal. In batch mode, tape requests are made via e-mail (the mail(1) command). A mail message will be sent to the user at the machine to which the device is connected asking the user to mount the tape and respond with the 'respond' command. Note that if the tape drive is a remote device, it will be accessed in batch mode, and mail messages will be sent to the remote host.

If the GuHigh device flag is set, then high density tape drives will be used, otherwise low density tapes will be used. This applies only to operator and carousel tape handling.

A device is remote if its host field is not NULL. Remote transfers connect to the 'gud' daemon, an eternal process that handles requests for remote data. A request for remote data may be denied either because permissions are not granted to the specified user and host, or because the daemon is not running. Remote devices are always accessed in batch mode. Other than that, and the added time of transferring data, they appear the same to the user as local devices.

int guSetDeviceRecord(GuDevice *dev, int recsize)

Sets the record size for the device to recsize bytes. This routine may be used after the device has been opened, but before the first i/o.

void guCloseDevice(GuDevice *dev)

Closes the specified device.

int guReadRecord(GuDevice *dev, char *buf)

Reads one data record from the device into buf. Returns 0 on success, -1 on error, and +1 on end-of-media.

int guWriteRecord(GuDevice *dev, char *buf)

Writes one data record from buf to the device.

int guLocalHost(char *hostname)

Returns nonzero if hostname is NULL or if hostname is the local host.

String Routines

The GU library has several routines for manipulating strings.

double guScanBytes(char *str)

Returns a number scanned from 'str', which is assumed to specify a number of bytes and can use K, M, or G to abbreviate kilobytes, megabytes, and gigabytes. For instance, guScanBytes("1K") is 1024. This allows the user to enter byte sizes in a familiar form. The byte size is returned as a double-precision real number, even though byte counts are always integers, because doubles can hold numbers larger than two gigabytes.

char *guBytesToString(double bytes)

Converts a byte count to a printable form. For instance, guBytesToString(2048) is "2 Kbytes".

int guStringYes(char *str)

Returns 1 if string is affirmative (yes, on, true, etc.), 0 if string is negative (no, off, false, etc.), and -1 if unable to tell. If str is NULL, this routine will read the string from the user.

int guStringEqual(char *str1, char *str2)

Returns nonzero if str1 and str2 are the same, ignoring case. This is similar to the string library function strcasecmp, which is not available on all machines.

int guStringWords(char *in, char ***words)

Given a space- or comma- separated list of words in 'in', allocates a null-terminated array of null-terminated strings, one string for each word. This routine will overwrite 'in'. When 'words' is no longer needed, it can be freed with the guFreeWords() routine described below. guStringWords() returns the number of words found.

For example:

	char in[] = "Hello world!";
	char **out;

	guStringWords(in, &out);
	/* now,	out[0] = "Hello"
		out[1] = "world!"
		out[2] = NULL */
	guFreeWords(out);

void guFreeWords(char **words)

Free memory allocated by guStringWords().

User Interaction Routines

The GU library tries to facilitate user interaction.

The GU header defines the floating-point constants GU_KILO, GU_MEGA, GU_GIGA, and GU_TERA as powers of two (GU_KILO = 1024.0, GU_MEGA = 1024.0 * 1024.0, etc.).

The following routines are geared towards improving user interaction.

int guBatch()

Returns nonzero if the calling process is running in batch mode, and zero if the calling process is running in interactive mode. Batch mode means the program is running in the background or has been submitted to a batch queue.

void guResources(int level)

Keeps track of elapsed time and CPU usage for the process. The level determines the action taken: GU_START reads the computer clock; GU_INCREMENTAL prints the incremental elapsed time and CPU usage since the last call; and GU_CUMULATIVE prints the cumulative elapsed time and CPU usage since the first call.

void guFirstName(char *userid, char *name)

Puts the first name of the specified user into 'name'. The userid may be a user login id or NULL, which specifies the current user. The first name of the user (such as "Ken" or whatever) will be read from the password file and put into 'name'. This allows a program to be really user-friendly:

	char name[30];
	guFirstName(NULL, name);
	printf("Hi, %s, what's happenin'?\n", name);

char *guNow(void)

Returns a pointer to a string containing the current date and time followed by a newline.

void guError(char *fmt, ...)

Print an error message with printf(3)-style formats. The default message handler prints the arguments to stderr with the prefix 'error:'.

The advantages of using the GU message routines are that error messages are simplified, for example,

	(void)fprintf(stderr, "error: bad value\n");
becomes
	guError("bad value");
and applications can provide their own message handler (for example, to print messages in an X window).

void guWarn(char *fmt, ...)

This is like guError() but used for warnings instead of errors (by default, it prints with the prefix 'warning:').

void guSystemError(char *fmt, ...)

This is like guError() but used for system errors. By default, it prints the current error message from the system error list. This is useful after a system call (such as read(2) or write(2)) fails.

void guSystemWarn(char *fmt, ...)

This is like guSystemError() but used for system warnings.

void guDebugMsg(char *fmt, ...)

This is like guError() but used for debug messages.

void guSetDebug(int level)

Set a debug level to be used in conjunction with guDebug() below. Note that this will be called by guGlobalParams() described below.

void guDebug(int level, (char *fmt, ...))

A macro for printing debug messages. If the constant NDEBUG is defined, this macro expands to nothing, so that debug code can be removed easily. If NDEBUG is not defined, this macro calls guDebugMsg() if the debug level is greater than or equal to 'level'. For example,

	guDebug(3, ("just opened %s", filename));
prints
	debug: just opened /me/myfile
if the debug level is three or greater.

void guDefaultMessageHandler(char *msg, int msgtype, char *sysmsg)

The default GU message handler. Any application-specific message handlers will have the same calling structure: 'msg' is the message passed to the message routine (guError() etc.), 'msgtype' is GU_WARNING, GU_ERROR, or GU_DEBUG, and 'sysmsg' is the system error message or NULL if there was no system error.

void guSetMessageHandler(void(*)(char*, int, char*))

Overrides the default message handler. After this call, future calls to guError() etc. will pass their messages to the specified subroutine rather than the default one.

Type Conversion Routines

The GU library is designed to convert arrays from one data type to another. An enumerated type, GuType, enumerates possible data types:

The header file declares the type GuConverter for use with type conversion. GuConverter is a pointer to a void function.

The following type conversion routines are available.

void guToEBCDIC(char *buf, int n)

Converts 'n' characters in 'buf' from the ASCII character set to the EBCDIC character set.

void guFromEBCDIC(char *buf, int n)

Converts 'n' characters in 'buf' from the EBCDIC character set to the ASCII character set.

GuType guScanType(char *str)

Returns the enumerated constant equivalent to str, or GU_NONE if unknown. For example, guScanType("int32") is GU_INT32.

char *guTypeName(GuType type)

Returns the name of an enumerated constant. For example, guTypeName(GU_INT32) is "int32 (32-bit signed integer)".

int guSizeOf(GuType type)

Returns the number of bytes in a value of the specified type.

GuConverter guGetConverter(GuType t1, GuType t2)

Get a function which will convert values from type t1 to type t2. Returns pointer to the conversion function if the desired conversion is implemented and NULL otherwise. Not all possible conversions are implemented (in particular, no conversion from a larger type to a smaller type is implemented).

The conversion function returned will have the form:

	void cvt(void *a1, void *a2, int n);

where a1 contains n values of type t1, and on return a2 will have n values of type t2.

Parameter Parsing Routines

The GU header defines the GuParameter type for the parameter parsing routines:

typedef struct {
	char *name;	/* parameter name */
	char *def;	/* default parameter value */
	char *addr;	/* location to hold parameter value */
	int flags;	/* used internally by library */
} GuParameter;

The following routines are available for parameter parsing.

int guParseParams(char *id, char **argv, GuParameter params[])

This routine parses a list of user-supplied parameters. The program must first define its parameters with a GuParameter array:

/*
	Declare character array variables to hold parameter values.
*/
char velocity[20], units[20];

/*
	Define parameters. The fields are:
		parameter name,
		default parameter value,
		character array to hold parameter,
		0 (always zero)
	The last parameter must be NULL.
	Default values cannot contain spaces.
*/
static GuParameter params[] = {
	"velocity", "4000", velocity, 0,
	"units", "ft/sec", units, 0,
	NULL
};

This array can then be used with the program's command-line arguments to set the parameters:

int main(int argc, char **argv)
{
	++argv;
	...
	guParseParams("in", argv, params);
	...
}

This routine will initialize parameters specified on the command line or in a file specified on the command line, but it will not prompt for parameters if that has been requested (for example, velocity=?).

int guPromptParams(GuParameter params[])

In batch mode, this routine does nothing. In interactive mode, it goes through a list of parameters and prompts for those that need to be prompted for. It prints the prompt "Enter a value for parameter:" where parameter is the parameter name (for example, velocity). It can be called after guParseParams(), as in:

guParseParams("in", argv, params);
guPromptParams(params);

int guParamNeedsPrompt(GuParameter *param)

Returns nonzero if the specified parameter needs prompting. This is useful for programs that wish to examine each parameter separately instead of using guPromptParams().

int guGlobalParams(char *id, char **argv)

Parses the following commonly-used parameter from argv.

debug=0
Sets the debug level for use with the debug message routines.

Sample Program

The following program copies traces from an input survey to an output survey. Its command line looks like: copy in.names=mytape1 out.names=mytape2.

#include "gu.h"

int main(int argc, char **argv)
{
	GuSurvey *in, *out;	/* input and output surveys */
	char trace[10000];	/* the trace to be copied */

		 /* skip program name in argument list */
	++argv;

		/* define surveys from command line */
	in = guCreateSurvey("in", argv, "r");
	out = guCreateSurvey("out", argv, "w");

		/* open the input survey */
	guOpenSurvey(in);

		/* make sure #samples is specified */
	if (out->nsamples == 0)
		out->nsamples = in->nsamples;

		/* open the output survey */
	guOpenSurvey(out);

		/* copy the data */
	while (guReadTrace(in, trace) > 0)
		guWriteTrace(out, trace);

		/* close the surveys */
	guCloseSurvey(in);
	guCloseSurvey(out);

		/* free survey memory */
	guDestroySurvey(in);
	guDestroySurvey(out);
}

Pick Format

The pick format used by the GU library is similar to the format used by VoxelGeo for 'polylines' (faults and wells). Picks are stored in an ASCII file, and more than one pick can be in the file. The file format generally is:

	GROUP: gname
		PICK: pname
			Thickness: t
			Color: c
			POINT: pk sk tk sn i
			...
		END PICK: (pname)
		...
	END GROUP: (gname)

gname is the name of the group of picks, such as the data set being picked. It is irrelevant. pname is the name of the individual pick, such as the horizon number. t is an integer line thickness. c is a hexadecimal number in the format AAGGBBRR where AA is an opacity value, GG is green intensity, BB is blue intensity, and RR is red intensity; intensities and opacities range from 00 (none/transparent) to ff (full/opaque). A 'POINT' on the pick is specified by the header keys pk, sk, and tk, and the sample number sn, all integers. i is zero if the user picked the point and nonzero if the point was interpolated.

The ellipsis (...) means that there may be any number of 'POINT:' specifications per pick, and any number of 'PICK:' specifications per group. There can only be one 'GROUP:' specification per file.

The 'Thickness:' and 'Color:' specifications are optional, with a default of 1 and ff00000 (black) respectively.


Chapter IV. Administrator's Guide

The GU toolkit was developed by Ken Gaillot Jr. at the Geotechnology Research Institute of the Houston Advanced Research Center (HARC/GTRI).

The source code is written for UNIX-based operating systems, and has been tested on the following platforms:

It should run on similar systems with little or no modification.

The GU installation hierarchy consists of a source code directory with the following components:

The total source code distribution takes about 600 Kilobytes of disk space. Other more advanced programs using the GU library are also available.