The data for the Segy widget is specified as a filename of a dataset stored in the Segy format. All information regarding the size and type of this dataset is extracted directly from the file.
The Segy widget supports trace selection by a primary key which may be one of Trace, Trace Shot Sequence Number (TSSN), Shot Point Identifier (SPID), or Common Depth Point (CDP). A secondary key of Common Depth Point Trace (CDPTR) can be specified for pre-stack traces that have a primary key of CDP.
#include <stdio.h>
#include <math.h>
#include <Xm/Xm.h>
#include <Xm/RowColumn.h>
#include <Xm/Form.h>
#include <Xm/Separator.h>
#include <Xm/PushBG.h>
#include <Xm/ScrolledW.h>
#include <Xint/Seismic.h>
#define NSAMPLE 500 /* number of samples per trace */
#define NTRACE 100 /* number of traces */
#define k_num_controls 1
#define k_exit 0
/* Declare subroutines */
void BuildUI();
/* Declare callback .. User control pushbuttons */
static void ControlsProc(Widget, int, XtPointer);
/* Declare global variables */
Widget toplevel_widget;
int i, j, n;
Arg arg[20];
/***
*** Main
***/
main(argc, argv)
int argc;
char *argv[];
{
XtAppContext app_context;
n = 0;
toplevel_widget = XtAppInitialize (&app_context, "Example", NULL, 0,
&argc, argv, NULL,arg, n);
BuildUI ();
XtRealizeWidget(toplevel_widget);
XtAppMainLoop(app_context);
}
/***
*** BuildUI
***/
void BuildUI ()
{
Widget main_form; /* contains all other widgets */
Widget scrolled_window; /* contains the Seismic widget */
Widget seismic_widget; /* for displaying the trace data */
Widget sep; /* separator widget ID */
Widget controls_box;
Widget controls_pb[k_num_controls];
static char *controls_pb_names[] = {"Exit"};
/* array for the keys - it must remain allocated as long as it is
attached to the Seismic widget */
static XintSeismicKeyRec key_info[NTRACE];
/* array to contain the trace data - it is not copied by the widget
and must remain allocated as long as the Seismic widget exists */
static float trace[NTRACE][NSAMPLE];
/* array containing information about the seismic section - it is not
copied by the widget and must remain allocated as long as the
Seismic widget exists */
static XintSeismicDataRec data_info;
float scale = .25;
float tpi = 25;
/* Create form to contain all other widgets */
n = 0;
XtSetArg(arg[n], XmNwidth, 400); n++;
XtSetArg(arg[n], XmNheight, 500); n++;
main_form = XtCreateManagedWidget("main_form", xmFormWidgetClass,
toplevel_widget, arg, n);
/* create separator */
n = 0;
XtSetArg(arg[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg(arg[n], XmNbottomOffset, 50); n++;
sep = XtCreateManagedWidget("sep", xmSeparatorWidgetClass,
main_form, arg, n);
/* create a ScrolledWindow widget */
n = 0;
XtSetArg(arg[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(arg[n], XmNtopOffset, 0); n++;
XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(arg[n], XmNleftOffset, 0); n++;
XtSetArg(arg[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg(arg[n], XmNrightOffset, 0); n++;
XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
XtSetArg(arg[n], XmNbottomWidget, sep); n++;
XtSetArg(arg[n], XmNbottomOffset, 20); n++;
XtSetArg(arg[n], XmNscrollingPolicy, XmAUTOMATIC); n++;
scrolled_window = XtCreateManagedWidget("scrolled_window",
xmScrolledWindowWidgetClass,
main_form, arg, n);
/* generate the synthetic traces */
for (j=0; j<NTRACE; j++) {
for (i=0; i<NSAMPLE; i++) trace[j][i] = sin((float) (i+j)/10.);
key_info[j].skey = j%10 + 1; /* this is the channel number */
key_info[j].pkey = j/10 + 1; /* this is the shot number */
/* pakey and sakey can contain any F.P. value you want. */
/* Here skey and pkey values are used to display the channel */
/* number and the trace number as annotations. */
key_info[j].pakey = (float) key_info[j].pkey;
key_info[j].sakey = (float) key_info[j].skey;
}
/* fill the structure that describes the dataset to the widget */
data_info.data = (XtPointer) &trace[0][0];
data_info.data_format = XintFLOAT_DATA_FORMAT;
data_info.key_info = key_info;
data_info.ntrace = NTRACE;
data_info.starting_time = 0;
data_info.sample_rate = 4.e-3;
data_info.nsample = NSAMPLE;
data_info.data_type = XintTIME_DATA;
/* create the seismic widget */
n = 0;
XtSetArg(arg[n], XmNplotTitle,
"Seismic example using\nSine function data"); n++;
XtSetArg(arg[n], XmNdataRec, &data_info); n++;
/* we set primaryKeyName and secondaryKeyName to non NULL values */
/* to tell we want to use both keys for trace selection */
XtSetArg(arg[n], XmNprimaryKeyName, "Shot"); n++;
XtSetArg(arg[n], XmNsecondaryKeyName, "Trace"); n++;
/* we want to display trace 1 to 8 of every other shot */
XtSetArg(arg[n], XmNprimaryKeyIncrement, 2); n++;
XtSetArg(arg[n], XmNsecondaryKeyEnd, 8); n++;
/* we want to see both primary and secondary annotations */
XtSetArg(arg[n], XmNprimaryAnnotationName, "SHOT"); n++;
XtSetArg(arg[n], XmNsecondaryAnnotationName, "CHAN"); n++;
/* we want to annotate every 5th trace */
XtSetArg(arg[n], XmNsecondaryAnnotationIncrement, 5); n++;
/* we set gapKeyName to a non NULL value to indicate that */
/* we want a gap between shots */
XtSetArg(arg[n], XmNgapKeyName, "shot"); n++;
/* set the scale factor and traces per inch (pass the address *.
/* instead of the value for floating point resources). */
XtSetArg(arg[n], XmNscale, &scale); n++;
XtSetArg(arg[n], XmNtracesPerInch, &tpi); n++;
XtSetArg(arg[n], XmNautoMarginAdjust, XintADJUST_ALL); n++;
seismic_widget = XtCreateManagedWidget("seismic_widget",
xintSeismicWidgetClass,
scrolled_window, arg, n);
/* use default change panel provided in library */
XtAddCallback(seismic_widget, XmNchangePanelCallback,
XintSeismicChangePanelCallback, NULL);
/* create controls box */
n = 0;
XtSetArg(arg[n], XmNspacing, 15); n++;
XtSetArg(arg[n], XmNorientation, XmHORIZONTAL); n++;
XtSetArg(arg[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg(arg[n], XmNrightOffset, 20); n++;
XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(arg[n], XmNleftOffset, 20); n++;
XtSetArg(arg[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg(arg[n], XmNtopWidget, sep); n++;
XtSetArg(arg[n], XmNtopWidget, sep); n++;
XtSetArg(arg[n], XmNtopOffset, 10); n++;
XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg(arg[n], XmNbottomOffset, 10); n++;
controls_box = XtCreateManagedWidget("controls_box",
xmRowColumnWidgetClass,
main_form, arg, n);
/* create control pushbuttons */
n = 0;
XtSetArg(arg[n], XmNpushButtonEnabled, True); n++;
XtSetArg(arg[n], XmNmarginWidth, 4); n++;
XtSetArg(arg[n], XmNmarginHeight, 4); n++;
for (i=0; i < k_num_controls; i++) {
j = n;
XtSetArg(arg[j], XmNlabelString,
XmStringCreateLtoR(controls_pb_names[i], XmSTRING_DEFAULT_CHARSET));
j++;
controls_pb[i] = XtCreateManagedWidget("control_buttons",
xmPushButtonGadgetClass,
controls_box, arg, j);
XtAddCallback(controls_pb[i], XmNactivateCallback, ControlsProc,
(XtPointer)i);
}
}
/***
*** ControlsProc
***/
static void ControlsProc(Widget widget, int client_data,
XtPointer call_data)
{
if (client_data == k_exit) exit (0);
}
The output generated by example seismic_1.c is shown below:

Figure 15: Output produced by example seismic_1.c.
#include <stdio.h>
#include <Xm/Xm.h>
#include <Xm/RowColumn.h>
#include <Xm/Form.h>
#include <Xm/Separator.h>
#include <Xm/PushBG.h>
#include <Xint/Scroll.h>
#include <Xint/Segy.h>
/* Declare subroutines */
void BuildUI();
/* Declare global variables */
Widget toplevel_widget;
int i, j, n; /* counters */
Arg arg[20]; /* XtArgs */
/***
*** Main
***/
main(argc, argv)
int argc;
char *argv[];
{
XtAppContext app_context;
n = 0;
toplevel_widget = XtAppInitialize (&app_context, "Example", NULL, 0,
&argc, argv, NULL,arg, n);
BuildUI ();
XtRealizeWidget(toplevel_widget);
XtAppMainLoop(app_context);
}
/***
*** BuildUI
***/
void BuildUI ()
{
Widget int_scroll; /* contains the Seismic widget */
Widget segy_widget; /* for displaying contents of SEG-Y file */
float traces_per_inch;
/* create a Scroll widget */
n = 0;
XtSetArg(arg[n], XmNwidth, 500); n++;
XtSetArg(arg[n], XmNheight, 500); n++;
int_scroll = XtCreateManagedWidget("int_scroll",
xintScrollWidgetClass,
toplevel_widget, arg, n);
/* create the segy widget */
traces_per_inch = 7.0;
n = 0;
XtSetArg(arg[n], XmNplotTitle, "Segy Example Using Stacked Data");;n++;
XtSetArg(arg[n], XmNplotType, XintPOSITIVE_COLOR_FILL +
XintNEGATIVE_COLOR_FILL + XintWIGGLE); n++;
XtSetArg(arg[n], XmNcolorScale, XintCOLOR_SCALE_LEFT); n++;
XtSetArg(arg[n], XmNcolormapFile, "seg.cmp"); n++;
XtSetArg(arg[n], XmCColorScaleSize, 400); n++;
XtSetArg(arg[n], XmNtracesPerInch, &traces_per_inch); n++;
XtSetArg(arg[n], XmNsegyFilename, "segy1.dat"); n++;
XtSetArg(arg[n], XmNautoMarginAdjust, XintADJUST_ALL); n++;
segy_widget= XtCreateManagedWidget ("segy_widget",
xintSegyWidgetClass,
int_scroll, arg, n);
XmAddTabGroup(segy_widget);
/* add callback procedure defined in the INT library for */
/* displaying default change panel */
XtAddCallback(segy_widget, XmNchangePanelCallback,
XintSegyChangePanelCallback, NULL);
}
The output produced by example segy_2.c is illustrated below:

Figure 16: Output produced by example segy_2.c.
The overlay option is also supported by the Segy widget class. You can specify the overlay data for a Segy dataset using resource XmNoverlaySegyFilename or resource XmNoverlayData. It that second case, you must make sure that the size and number of traces contained in the overlay is equal to that of the Segy filename.
XtAddCallback(seismic_widget, XmNchangePanelCallback,
XintSeismicChangePanelCallback, NULL);
You can also register your own resource editor callback.

Figure 17: Default Segy Resource Editor Panel.
XtVaSetValues(segy, XmNplotType, XintWIGGLE,
XmNinterpolationMode, XintQUADRATIC_INTERPOLATION,
NULL);
The data range to be displayed defines the horizontal axis. It is specified by the user through the primary key and secondary key resources. These allow the user to refer to the traces in familiar terms, such as Common Depth Point number and Trace number. The key values are converted internally by the Seismic widget to unique trace sequence numbers. INT objects use the trace sequence numbers to identify locations on the horizontal axis of the trace display. The two functions, XintSeismicTraceToKey and XintSeismicKeyToTrace, convert from a trace sequence number to key values and the reverse, respectively. Other functions convert a trace sequence number and time (XintSeismicTraceTimeToPoint) or key values and time (XintSeismicKeyTimeToPoint) to a location in the user coordinate system. The trace sequence number, key values and time for a location in the user coordinate system may be found with the XintSeismicPointToKeyTime function.
The vertical axis is defined by specifying as resource values the number of inches per second (or inches per kilofeet or kilometers) and the starting and ending time (or depth) of the trace samples to be displayed. These values can be changed as needed to redefine the time (or depth) range of the samples currently displayed using Seismic resources XmNstartingTime and XmNendingTime.
Functions are provided in the CompBase and the Seismic widget class for converting a location in the user coordinate system to and from the device coordinate system.
...
start = 0;
end = ntraces * pixels_per_trace + 1 + 2 * log_width;
width = end - start + 1;
/* create segy widget */
n = 0;
XtSetArg(arg[n], XmNplotTitle, "Stack Line\n 128-B"); n++;
XtSetArg(arg[n], XmNprimaryKeyEnd, ntraces); n++;
XtSetArg(arg[n], XmNsegyFilename, "goliad.stk"); n++;
XtSetArg(arg[n], XmNautoMarginAdjust, XintADJUST_ALL); n++;
XtSetArg(arg[n], XmNtracePositionArray, trace_positions); n++;
XtSetArg(arg[n], XmNhorizontalStart, &start); n++;
XtSetArg(arg[n], XmNhorizontalEnd, &end); n++;
XtSetArg(arg[n], XmNimageWidth, width); n++;
XtSetArg(arg[n], XmNplotType, XintCOLOR_FILL); n++;
XtSetArg(arg[n], XmNcolormapFile, "seg.cmp"); n++;
XtSetArg(arg[n], XmNscale, &scale); n++;
segy = XtCreateManagedWidget("segy", xintSegyWidgetClass,
segy_scroll, arg, n);
...
The following code sample illustrates how to create two Segy widgets which share the same colormap.
Widget segy1, segy2;
XintColorRec *color_record;
...
/* create first segy widget */
segy1 = XtVaCreateManagedWidget("segy1", xintSegyWidgetClass, parent,
XmNcolormapFile, "seg.cmp",
XmNplotType, XintCOLOR_FILL,
XmNsegyFilename, "segy1.dat", NULL);
/* extract color record */
XtVaGetValues(segy1, XmMcolorRecord, &color_record, NULL);
/* create second segy widget */
segy2 = XtVaCreateManagedWidget("segy2", xintSegyWidgetClass, parent,
XmNcolorRecord, color_record,
XmNplotType, XintCOLOR_FILL,
XmNsegyFilename, "segy2.dat", NULL);
...
In this example, the colormap is allocated directly by the first Segy widget. You could also create the color record directly, using function XintReadColormap (see EditColormap widget) and function XintImageCreateColorRecord as illustrated below:
Pixel *pixels;
int ncolors;
int err_code;
...
pixels = XintReadColormap(parent, "seg.cmp", &ncolors, &err_code);
if (pixels) {
color_record = XintImageCreateColorRecord(pixels, ncolors);
/* create first segy widget */
segy1 = XtVaCreateManagedWidget("segy1", xintSegyWidgetClass,
parent,
XmNcolorRecord, color_record,
XmNplotType, XintCOLOR_FILL,
XmNsegyFilename, "segy1.dat", NULL);
...
} else {
/* error allocating colors */
...
}
EditObject callback XmNareaSelectionCallback can be used to let the end-user specify the rectangular area used for zooming. Grid function XintGridZoom can be used to zoom both a Seismic or Segy widget as described above.
The Seismic and Segy widgets can also be used to generate pixmaps or images that can be used by the Movie widget to build animations. See function XintSeismicGetInfoForMovie for extracting information used to build a Movie frame from a seismic display.