You are on page 1of 665

ProMAX Developers

Programming Guide Contents


Introduction 1
Quick Start 3
Overview of a ProMAX Process 4
Creating your own Directory Hierarchy 5
Writing a Menu 6
Installing the Menu 7
Overriding the Default ProMAX Files 8
Writing a ProMAX Program 10
Viewing Online Documentation 11
Writing Helpfiles 12
Self-guided Tutorial 13
Support Documentation 15
System Overview 17
Your Development Directory 18
Tool Anatomy 19
Programming Exercises: Simple Tools (amp_ratio) 20
amp_ratio Exercise 1: Adding Trace Headers 21
Menus 22
Global Parameters 22
amp_ratio Exercise 2: ordered parameter files 22
amp_ratio Exercise 3: time gates and tables 23
Debugging 24
C Programming Environment 25
Tool Types 26
Programming Exercise: Ensemble Tools (AVO) 27
Programming Exercise: Panel Tools 29
Programming Exercise: Input Tools 30
Programming Exercise: IPC Tools 31
System Overview 33
ProMAX Organization: Areas, Lines, and Flows 34
The User Interface: The Flow Builder 36
Menu Files 37
Flow Execution 38
Super Executive 38
Executive 39
Executive 51

Other Docs

Known Problems

Contents2

Devlopers Programming Guide

System Architecture 52
Headers and Global Variables 53
Input Tools 54
Re-entrancy 55
Common Blocks and Parms Structures 56
Executive Functions 57
Communication between Tools 58
OPF Database 59

Make System 61
Working with ProMAX Systems 62
Getting Started 63
System Administrator Setup 63
User Setup 65
Converting to the New System 69
Understanding the Directory Structure 70
$PROMAX_HOME/port/include/make/ 70
$PROMAX_HOME/port/bin/ 73
$PROMAX_HOME/sys/bin/ 74
$PROMAX_HOME/port/src/exe/exec/ 76
Customizing the System 77
Toggling Products: .promax 78
Adding a New Tool 81
Making Your New Executable 84
Incorporating New Functionality 87
Creating Menus 88
Adding a ProMAX Menu 89
Changing Files 91
Understanding the Makefile System 94
C++ Template Instantiation 94
Terms and Variable Descriptions 95
Makefile Techniques 117
Directory Structure 121
Directory Hierarchy 122
Machine-dependent Directories 125
Directory Naming Conventions 126
Product-dependent Subdirectories 127
Third-party Software 128
Recompilation - GNU Make 129
Makefile Rules 130
Makefile Options 131
User and Master Versions 132
Master Versions for Landmark Clients 134
C Environment 135
Other Docs

Known Problems

Contents3

Devlopers Programming Guide

C Process Components 136


C and FORTRAN Links 137
Calling a FORTRAN Routine from a C Routine 137
Calling a C Routine from a FORTRAN Routine 137
Global Parameters 139
Trace Header Index Values 139
Re-Entrancy 140
Tool Types 141
Executive Tools 142
Simple Tools 145
Ensemble Tools 147
Panel Tools 148
Single Buffer Tools 153
Double Buffer Tools 156
Complex Tools 157
Stand-alone Tools 161
IPC Tools 163
IPC Tool Details 164
IPC Tool Debugging 165
Global Parameters 167
Overview of Global Parameters 168
Common Blocks and C Structure Descriptions 169
Ordered Parameter Files 171
Overview of the ProMAX Database 172
Standard Orders 176
Trace Headers 179
Overview of Trace Headers 180
Definition and Usage of Standard Header Entries 184
Alphabetical Reference of Trace Header Entries 184
Sequential Reference of Trace Header Entries 185
Parameter Tables 197
Overview of Parameter Tables 198
Structure of ProMAX Tables 198
Table Rules 200
Table Interpolation 200
X Values in Tables 204
Table Extrapolation 205
Table Subroutine Categories 206
Examples of Table Routines 208
FORTRAN Code Examples 208
C Code Examples 213
Other Docs

Known Problems

Contents4

Devlopers Programming Guide

Memory Management 219


Overview of Memory Management 220
C Memory Management 221
Multi-dimensional Arrays 221
Multi-dimensional Routine Names 223
References 225
FORTRAN Memory Management 226
mem.inc 226
RSPACEz and ISPACEz 227
Big Vector Routines 228
Debugging with dbx 229
Overview of dbx 230
System Review 231
Debugging 233
Writing to the packet.job File 233
Creating an Executable for dbx 233
Running dbx 234
Menus 237
Overview of ProMAX Menus and Landmark Lisp 238
Parts of a ProMAX menu 239
Menu Heading 240
Parameter Specifications 240
exec_data 242
Rules 243
Tips on Writing Menus 246
Use Examples 246
Keep it Simple 246
Usable Lisp Functions 247
Lisp Primitives 247
Access & Assignment Functions 250
ProMAX Lisp Extentions 252
Parameter Menu System 254
Parameter Keywords 255
Parameter Types and Attributes 255
Including Other Menus 266
Rules and Context Sensitivity 266
pwin 276
Example Macro: Display Shots with AGC 278
Helpfiles 283
FrameMaker-formatted Helpfiles 284
Starting FrameMaker 284
Creating a New Helpfile 284
Editing a Helpfile 284
Other Docs

Known Problems

Contents5

Devlopers Programming Guide

Working with FrameMaker Files 285

Helpfile Organization 288


Example Helpfile 289
Theory 289
Usage 290
References 290
Parameters 291
Interactive Display 292
Common Error Messages 292
Customizing the User Interface 293
Hypertext 294

Code Standards 295


C Coding Standards 296
ProMAX C Routine Documentation 297
FORTRAN Coding Standards 299
General Text File Format 300
Variable Naming and Declarations 301
C preprocessor 302
Comments 303
White Space 304
Code Structure 304
Miscellaneous 305
Purify 305
ProMAX Fortran Routine Documentation 305
Portable Code 307
Man Page Reference 309
Using the Man Pages 310
Finding what you want 311
Appendix: Expanded Directory Structure 313
Expanded Directory Structure 314
Appendix: C Programming Examples 325
Example Include Files 326
cglobal.h 327
cpromax.h 336
Example Simple Processes 345
simple.menu 346
simple.c 347
ampRatio.c 349
Appendix: Simple Tool Examples 357
amp_ratio.menu 358
amp_ratio.inc 359
Other Docs

Known Problems

Contents6

Devlopers Programming Guide

amp_ratio.f 360
ampRatio.c 367
Appendix: Ensemble Tool Examples 375
AVO Ensemble Tools 376
avo.menu 377
avo.inc 378
avo.f 379
avoC.c 383
Trace Interpolation Tools 388
prestk_interp.menu 389
prestk_interp.inc 390
prestk_interp.f 391
prestk_interp.c 393
Appendix: Panel Tool Examples 397
panel_test.menu 398
panel_test.inc 399
panel_test.f 400
panelTest.c 402
Appendix: Single Buffer Tool Examples 405
ens_define.menu 406
ens_define.inc 407
ens_define.f 408
interp_sb.menu 412
interp_sb.c 413
Appendix: Double Buffer Tool Examples 417
semblance.menu 418
semblance.inc 420
semblance.f 421
interp_db.menu 427
interp_db.c 428
Appendix: Complex Tool Examples 433
transform.menu 434
transform.inc 435
transform.f 436
transform.c 439
Appendix: Input Tool Examples 445
sine_wave.menu 446
sine_wave.inc 448
sine_wave.f 449
sineWave.c 455
Other Docs

Known Problems

Contents7

Devlopers Programming Guide

Appendix: Disk Iteration Examples 463


sc_amp.menu 464
sc_amp.inc 465
sc_amp.f 466
disk_iter.menu 469
disk_iter.c 470
Appendix: Stand-alone Tool Examples 473
prestack.menu 474
prestack.f 475
Makefile_prestack 480
poststack.f 481
Makefile_poststack 484
poststack.c 485
vel_io.f 488
Appendix: IPC Tool Examples 495
IPC Menu Code 496
IPC C Code 497
IPC FORTRAN Code 499
amp_ratio Menu Code 503
ampRatio C Code 505
amp_ratio FORTRAN Code 511
Appendix: Global Include File Examples 519
global.inc 520
cglobal.h 526
Appendix: Ordered Parameter File Examples 537
db_disp.f 538
comp_opf.menu 545
comp_opf.c 548
Appendix: Lisp Menu Example 551
EXAMPLE.menu 552
Appendix: C Library Summary 557
Error Routines 559
Control Functions 560
Parameter Input 561
Configuration 562
Database 563
Memory Allocation/Management 567
Trace Headers 569
Trace Muting 570
Velocity (Geophysical Routines) 571
Other Docs

Known Problems

Contents8

Devlopers Programming Guide

Vector Routines 572


Parameter Lists 573
Packet Files 574
Parameter Interpolation 575
Unix Interface 576
IPC Tools 577
Parameter Tables 580
PVM 585
Matrix Functions 588
Interpolation Routines 590
Math Functions 594
Signal Processing 596
Plotting 598
Data Structures 599
Sorting and Searching 602

Appendix: FORTRAN Library Summary 603


Area/Line(Survey)/Flow 605
Configuration 608
Database Orders 609
Domain Mapping 611
Miscellaneous 1 612
Trace I/O 613
Trace Executive 614
Trace Headers 615
Memory Management 616
Mute/Kill 617
Statics 618
Summing 619
Error Routines 620
Parameter Tables 622
Tables Obsolete 624
Parameter Interpolation 625
Parameter Lists 626
String Decoding 628
Miscellaneous 2 629
Parameter Input 631
Packet Files 632
Character Routines 633
Seg-Y Disk 634
Geophysical Routines 635
Signal Processing 637
Disk I/O 640
SEG Vector Routines 641
Resource Reporting 647
UNIX Interface 648
Other Docs

Known Problems

Contents9

Devlopers Programming Guide

Index 651

Other Docs

Known Problems

Developers Programming Guide

Introduction

This Programmers Guide is written and designed to help you


create ProMAX software modules. It assumes that you are
familiar with large software system architecture, such as setting
up a make system and accessing parameter tables. It provides
instructional text for newer ProMAX programmers and serves
as a reference book for experienced ProMAX developers.

Organization
We divided this manual into chapters and sections that discuss
the key processes of the ProMAX system. In general, this
consists of:

environment setup and testing

tools and tool building

We added extensive Appendices to include:

an expanded directory structure

source code examples

C and FORTRAN library summaries

Documentation Conventions
We use the following documentation conventions in this
manual:

Other Docs

Boldface represents menu commands, push-button


options, and keystrokes.

Courier

refers to text that you should type into a


command line and represents program code listings. When
a line of text or code is longer than we can print on one line
in this manual, we use the UNIX standard of a backslash (\)
at the end of the line to indicate that it continues on the
next line.

Known Problems

Developers Programming Guide

Hypertext represents hyperlink-active text; click on this red


text to go to related information.

Italics emphasizes key terms and concepts and refers you


to other documents, chapters, or sections.

[Italics inside brackets] represent dummy parameters;


replace the brackets and their contents with your
user-specific information.

Text enclosed in a box signifies a warning, caution, or note.


A warning or caution warns you when you could lose data
or crash your system. A note emphasizes an important
issue.
Example
This is an example of the box we use for warnings, cautions, and
notes.

We suggest that you read:

Other Docs

the Quick Start chapter first for a brief overview of


ProMAX IPC processes if you want to implement new
code without investing time in learning the other parts of
the ProMAX processing system

the Self-Guided Tutorial chapter first if you are interested


in a step-by-step course in writing ProMAX software
processes

the System Overview chapter first if you want an overall


understanding of the ProMAX system. You should then be
able to determine how this manual can further help you.

Known Problems

Developers Programming Guide

Quick Start

This chapter is designed to give a programmer a quick overview


of a particular type of ProMAX processing process, the IPC
(Inter-Process Communication) tool. It should allow you to
implement some new code without investing much time in
learning other parts of the ProMAX programming system. If
you have previous experience with ProMAX programming, this
chapter may be all that you need to get a program running on
the ProMAX system. If this is not enough to get you going, the
Self-Guided Tutorial chapter takes you step-by-step through a
ProMAX programming course.

Topics Covered in this Chapter:

Other Docs

Overview of a ProMAX Process


Creating your own Directory Hierarchy
Writing a Menu
Installing the Menu
Overriding the Default ProMAX Files
Writing a ProMAX Program
Viewing Online Documentation
Writing Helpfiles

Known Problems

Overview of a ProMAX Process4

Developers Programming Guide

Overview of a ProMAX Process


There are three parts to writing a ProMAX process:

the menu

the program

the helpfile

The menu is the window that the User Interface pops up to let a
user enter parameters for your program. The program is the
code that actually runs. The helpfile hopefully tells people how
to use your process without them having to call you too much.
There are two classes of ProMAX programs: inline flow tools
and stand-alones. Inline flow tools process data as it streams by
in a flow; examples are AGC, FK filter, and migrations. Inline
flow tools do not contain an asterisk in the Processes list. Standalone tools either read their own data, as occurs with random
data access, or do not need data, as occurs with velocity
manipulation. Stand-alone tools include such processes as the
interactive velocity editor, interactive velocity analysis, and
some of the statics programs. These tools do contain an asterisk
in the Processes list.
There are two types of inline flow tools: IPC tools and executive
tools. IPC tools used to be called socket tools. This Quick Start
chapter will only show you how to write an IPC tool. This is a
relatively new approach which we recommend for many
applications, especially if you are just getting started.
Developing IPC tools is significantly quicker and simpler than
developing non-IPC tools, at little performance cost. If you are
an expertfor example, if you have taken a ProMAX
programming courseyou may decide to write inline flow tools
using executive tools.

Other Docs

Known Problems

Creating your own Directory Hierarchy5

Developers Programming Guide

Creating your own Directory Hierarchy


To help give you some order to your ProMAX programming,
we have a recommended directory hierarchy for you to create in
your home directory. Use the Makeadvance program, which is
actually a shell script that is in $PROMAX_HOME/port/bin to
create this directory hierarchy in your home directory. The
environmental variable $PROMAX_HOME is the path to
where your ProMAX software is installed. The default setting
during installation for $PROMAX_HOME is /advance. The
Makeadvance command produces a mirror of the
$PROMAX_HOME directory hierarchy, but without any of the
files. This will let you work on ProMAX modules under your
home directory.

Other Docs

Known Problems

Writing a Menu6

Developers Programming Guide

Writing a Menu
The menu file is an ASCII file that is interpreted on the fly by
the User Interface. Writing a menu is simple enough that you
should be able to do this using the ProMAX menu files
delivered with your system as examples. The menus are in
$PROMAX_HOME/port/menu/promax. A good example to
start with is vdatum.menu; see also EXAMPLE.menu.
vdatum.menu is an example of a menu for a an IPC tool. Most
menus in the system, such as agc.menu, are for inline flow tools
that are non-IPC tools. The only difference between these two
menus occurs at the beginning of the exec_data section of the
menu. You should be able to tell the minor differences between
a IPC tool and a non-IPC tool, so you can still use all the menus
as examples.
An example of a menu of for a stand alone module is
autostat.menu. Again, the only difference between this type of
menu and others occurs at the beginning of the exec_data
portion of the menu.
We recommend that you write your menu in your mirror of
$PROMAX_HOME/port/menu/promax under your home
directory; that is, under
~/$PROMAX_HOME/port/menu/promax.
Menus are actually written in Lisp. If you write menus often,
you will notice that you are starting to learn Lisp. For more
information on writing menus, refer to the Menus chapter. To
test the menus you write, use the pwin program which is in
$PROMAX_HOME/sys/bin. If you are an emacs user, type
pwin my.menu and you should be in familiar surroundings. If
you are not an emacs user, type pwin my.menu t and bring up
your favorite editor in another window; you can create, debug,
and edit the menu using your editor. After you write your edits
to disk, click with the mouse in the pwin window and you will
see the sample menu updated to reflect your changes. If you
have syntax errors in your menu, pwin will generally print the
line number containing the syntax error.

Other Docs

Known Problems

Installing the Menu7

Developers Programming Guide

Installing the Menu


Once you have written a menu that you are happy with, you
have to install it in the ProMAX list of menus that appears in the
User Interface. We recommend that you copy the file
$PROMAX_HOME/port/menu/promax/Processes to
~/$PROMAX_HOME/port/menu/promax/Processes, which is
the 2D list of menus. The 3D list lives in
$PROMAX_HOME/port/menu/promax3d. Now add your menu
to the appropriate category. It should be straight forward how to
do this by looking at the file. Be sure you do not use the .menu
suffix.

Other Docs

Known Problems

Overriding the Default ProMAX Files8

Developers Programming Guide

Overriding the Default ProMAX Files


You need to tell the User Interface where to find your personal
ProMAX files: your new Processes file, menu, executable, and
helpfile. Edit or create a .promax file in your home directory to
look like this (replace your home directory for /mnt/stof):
(quote
((:product
; This is a comment
("P" "ProMAX"
".:/mnt/stof/promax/1998.6/rs6000/exe"\
; executables
"/mnt/stof/promax/1998.6/port/menu/promax:\
promax" ; menus
"/mnt/stof/promax/1998.6/port/menu/promax
/Processes" ; Processes file
"promax:/mnt/stof/promax/1998.6/port/help\
/promax" ; helpfiles
"" ; miscellaneous files (use default)
"" ; data area (use default)
t)
("p" "Prospector"
""
"prospector"
"prospector/Processes"
"prospector"
""
""
t)
("3" "3D Promax"
".:/mnt/stof/promax/1998.6/rs6000/exe"
"/mnt/stof/promax/1998.6/port/menu/promax3d:\
promax3d"
"/mnt/stof/promax/1998.6/port/menu/promax3d\
/Processes"
"promax3d"
""
""
t)
))
)

Remember that a backslash (\) at the end of a line indicates that


the line of code is longer than we can print on one line of this
manual and, therefore, continues on the next line; you should
type it all as one line without the backslash. Also, you can use a
~ rather than typing out your home directory.

Other Docs

Known Problems

Overriding the Default ProMAX Files9

Developers Programming Guide

Note that specifying /mnt/stof/promax/1998.6/menu:promax


creates a search path, separated by a :, for menus. Also note
that just specifying promax or . refers to the default master
directory tree such as /advance/port/menu/promax. You can use
a . only for the executables master directory; for the others,
you must use promax. Thus, this search path above looks first in
your home directory, and then in the master location.
When you now start the user interface by typing promax or
$PROMAX_HOME/sys/bin/promax, the User Interface should
read your personal Processes file, and you should see your new
tool in the list of Processes. You should be able to bring your
menu into a flow and parameterize it.
You can supply any number of product stanzas in your personal
.promax file, just so long as the initial single character strings,
e.g. P and 3, are unique. The User Interface will then
display your list under the Products menu item in the Flow
window and you can select any of them with the mouse prior to
building or editing a flow. This avoids having to exit the User
Interface in order to switch between development and/or
production environments.
Finally, it is important to remember that the User Interface
looks at the setting of the environment variable new_menu to
determine the menu init behavior. If new_menu=t, then the User
Interface will re-initialize the menu every time it is displayed. If
new_menu=f, then the flow builder will only read files once.
This means if you modify the processes file or a menu file after
starting the flow builder, it will not see your changes.
Furthermore, if you add a tool to a flow, the corresponding
menu file will be saved with the flow, and the menu file will not
be read again when the flow is accessed again. Setting
new_menu=t is a big help in testing menus and should be part
of the ProMAX programmers environment. This setting slows
down the User Interface because the menu files are reread;
therefore, it is not recommended for the typical production
processing environment.

Other Docs

Known Problems

Writing a ProMAX Program10

Developers Programming Guide

Writing a ProMAX Program


To examine a sample IPC tool, written in C, look in
$PROMAX_HOME/port/src/exe/c_socket and
$PROMAX_HOME/port/src/exe/ampRatio. A sample
FORTRAN IPC tool is in
$PROMAX_HOME/port/src/exe/f_socket and
$PROMAX_HOME/port/src/exe/amp_ratio. Each of these
directories contain sample menus, although you should copy the
menus to a more proper location, such as your own menu
directory. Sample FORTRAN standalone programs are in
$PROMAX_HOME/port/src/exe/stand_alone.
A good portion of this manual deals with creating in-line tools
that are executive tools, not IPC tools. To compile and link these
programs, go to ~/$PROMAX_HOME/port/src/c_socket. Then
type
/$PROMAX_HOME/sys/bin/gmake

which should compile and link the sample code. The executable
produced by this make will reside in
~/$PROMAX_HOME/rs6000/exe. For more information on the
Make System, refer Make System chapter. For more description
on IPC tools or stand-alone programs, see the Tool Types
chapter.
If you copy this directory and start making modifications to the
code, you will need to change the name in the Makefile to
match the name of your directory.
You can change your product file to include your home
directory in the search path for ProMAX executables. See the
description in the product file.
If you install your working source code under the
$PROMAX_HOME tree, you can do a gmake there and your
executable will be placed under the standard ProMAX
executable path, $PROMAX_HOME/sys/exe. You could do
your development under the $PROMAX_HOME directory tree
rather than in your home directory, but we discourage this. It
will become a maintenance hassle when many developers work
in that area.

Other Docs

Known Problems

Viewing Online Documentation11

Developers Programming Guide

Viewing Online Documentation


All ProMAX subroutines are accessible from either FORTRAN
or C. We have online manual pages for these subroutines, which
you can access by typing
$PROMAX_HOME/port/bin/aman tblToMatrix

The aman command supports the -k option; to find all C


subroutines for dealing with tables, type
aman -k table | fgrep C routine

For a quick summary of the ProMAX subroutines, type


aman c_promax

or
aman f_promax

Other Docs

Known Problems

Writing Helpfiles12

Developers Programming Guide

Writing Helpfiles
Documentation is an important part of the ProMAX system.
You should write a helpfile for your new process if it is going to
be used in a production processing environment. At Landmark,
we use Adobe FrameMaker to generate and edit most of our
online and printed software documentation. For more
information, see the Helpfiles chapter, or contact any member
of the Documentation Department for assistance.

Other Docs

Known Problems

13

Developers Programming Guide

Self-guided Tutorial

This chapter is designed to be used as a guide for programmers


who want to learn to write ProMAX software modules. The
tutorial directs you through a sequence of chapters to read and
specific exercises to work on in order to learn the parts of the
system.

Topics Covered in this Chapter:

Support Documentation
System Overview
Your Development Directory
Tool Anatomy
Programming Exercises: Simple Tools (amp_ratio)
Debugging
C Programming Environment
Tool Types
Programming Exercise: Ensemble Tools (AVO_exer)
Programming Exercise: Panel Tools
Programming Exercise: Input Tools
Programming Exercise: IPC Tools

Materials Needed for this Tutorial:

Other Docs

This Programmers Reference Manual

The ProMAX 2D Reference Manual

The FORTRAN Programmers Reference Manual or the C


Programmers Reference Manual, depending on your
programming language preference. These manuals are
summarized in the C Library Summary and FORTRAN
Library Summary appendices.

Known Problems

14

Developers Programming Guide

Access to a computer on which ProMAX and the ProMAX


Development Environment have been installed. In addition,
the computer must have an editor program, such as vi or
emacs, to allow you to create new files, as well as a C or
FORTRAN compiler.

To use this tutorial, simply read through each section and follow
the reading and programming exercise assignments. The
specific reading and exercise assignments are highlighted as
follows:

Now do this.
Before you get started, please note that this chapter refers to the
environmental variable $PROMAX_HOME, which is the path
name of the directory under which ProMAX is installed. Ask
your system administrator for help in setting up your ProMAX
environment if he or she has not already done so.

Other Docs

Known Problems

Support Documentation15

Developers Programming Guide

Support Documentation
The online C or FORTRAN Programmers Reference Manual
contains documentation on hundreds of subroutines that are
available in the ProMAX system. We have summarized these
subroutines in the C Library Summary and FORTRAN Library
Summary appendices..

Take a few minutes now to skim through the C or FORTRAN library


summaries to become familiar with the subroutine categories, such
as Trace Headers and Parameter Input. To get a even better overview of the manual, read through the individual subroutine names
and descriptions.
We discuss only a small percentage of the available subroutines
in this tutorial, so it is up to you to study the library to get the
maximum use from it.
You will also want to refer to the ProMAX Reference Manual.
This manual provides basic information about the ProMAX
system from the users point of view, along with additional
information about Parameter tables and other parts of the
database. We will give you specific reading assignments in
these chapters at the appropriate times.
Finally, the ProMAX routines are also documented in the online
manual pages. You can access these manual pages by using the
aman command. For example, to view the documentation for
the ProMAX routine tblCopy, type:
aman tblCopy

from the command line of the computer. Your path must include
$PROMAX_HOME/port/bin.
To see a name and short description of all table routines, type
aman -k tbl

Try typing aman tblCopy to see if your environment is set up properly


for using the aman online documentation.
If a message is returned saying that there is no manual entry for
tblCopy, contact your system administrator for help in setting
environment variables.

Other Docs

Known Problems

Support Documentation16

Developers Programming Guide

Another aman command allows you to see all ProMAX


subroutine names by category. Type
aman c_promax

to see all ProMAX C routines by category, or


aman fortran_promax

to see all ProMAX FORTRAN routines by category.

Other Docs

Known Problems

System Overview17

Developers Programming Guide

System Overview
The primary function of ProMAX is to create, modify, and
execute processing flows. A flow is a sequence of processes
which are used to manipulate seismic data. Flows are built by
selecting processes from a Processes List. A typical flow
contains an input process, one or more data manipulation
processes, and a display and/or output process.
Some of the chapters in this manual provide basic information
on how the system components work together and introduce
ideas that are present throughout the rest of this tutorial. Others
describe the specific processes of the ProMAX system. Because
you will be writing new menus which appear as part of the User
Interface, you should have a basic familiarity with the selection
of menu parameters at the User Interface level.

Turn to the chapter entitled Working with ProMAX in the ProMAX 2D


Reference Manual. Read the sections entitled Getting Started and
Building a Flow. These sections provide a brief overview of Areas,
Lines, and Flows.

Read the System Overview, Executive, and Directory Structure in


this manual.
If you are already familiar with the User Interface, the ProMAX
data directory structure, tables, and datasets, you may skip these
chapters.

Other Docs

Known Problems

Your Development Directory18

Developers Programming Guide

Your Development Directory


In order to develop ProMAX software, a particular directory
structure must exist under the programmers home directory.
The following exercises will help you create this directory
structure.

Read the Make System chapter. Complete the Makeadvance exercise in the User Setup section; be sure you can complete the Makeexec exercise. Contact your system administrator if the computer
refuses to allow you to complete everything discussed in the chapter.

Be sure to read the Adding A New Tool section of the Tool Types
chapter. This section provides a recap of the critical components of
a new processing tool and shows how they work together.

Other Docs

Known Problems

Tool Anatomy19

Developers Programming Guide

Tool Anatomy
Before you actually get started on the programming exercises,
you first need to understand the structure of the ProMAX tools.

Read the Executive Tools section of the Tool Types chapter. You do
not need to read beyond this section, since the remainder of the
chapter will be assigned later in the tutorial.
This assigned reading section provides an overview of the
structure of most ProMAX processes, including the processes in
the programming exercises in this tutorial.

Other Docs

Known Problems

Programming Exercises: Simple Tools (amp_ratio)20

Developers Programming Guide

Programming Exercises: Simple Tools (amp_ratio)


The exercises in this tutorial consist primarily of example
programs to which you add code as a way of learning the
important parts of ProMAX programming. The first such
program is called amp_ratio.f for FORTRAN programmers, and
ampRatio.c for C programmers. The functionality of the C and
FORTRAN versions is the same, so the program will in general
be referred to as amp_ratio.
amp_ratio is an example of a simple tool. A simple tool
operates on a single trace at a time. amp_ratio operates on a
single trace by sliding two windows down the trace, taking the
ratio of powers in the windows, and outputting the ratio as a
sample at the beginning of the upper window. This is a crude
first break picker, since the peak value of the output trace is
normally at approximately the first break time. While this
routine is not high tech by any means, the programming
exercises involving amp_ratio demonstrate four important
features of ProMAX Programming:

the general mechanics of adding a tool

adding and manipulating trace headers

the use of the ordered parameter files

the use of tables to store time gates

The FORTRAN programming exercises that demonstrate these


last three features are amp_ratio1.f, amp_ratio2.f, and
amp_ratio3.f, respectively. Working code which contains
solutions to all three of these programming exercises can be
found in amp_ratio.f. The corresponding C programming
exercises and code is ampRatio1.c, ampRatio2.c, ampRatio3.c
and ampRatio.c.

To begin, move to your own maxtool/amp_ratio directory by typing


the following command on the command line:
cd ~/$PROMAX_HOME/port/src/lib/maxtool/amp_ratio

If you are programming in C, copy the .c files from the system


amp_ratio directory to your own directory by typing:
cp $PROMAX_HOME/port/src/lib/maxtool/amp_ratio/*.c .

Other Docs

Known Problems

Programming Exercises: Simple Tools (amp_ratio)21

Developers Programming Guide

If you are programming in FORTRAN, copy the .f and .inc files


from the system amp_ratio directory to your own directory by
typing a command similar to the one above.

Set the access permissions to the files by typing:


chmod 644 *.*

Next you will need to copy the menu files into your personal menu
directory. To do this, go to your own menu directory by typing:
cd ~/$PROMAX_HOME/port/menu/promax

then type the following command:


cp $PROMAX_HOME/port/src/lib/maxtool/amp_ratio/*.menu .

Set the permissions so that you can edit the files by typing:
chmod 644 *.menu

amp_ratio Exercise 1: Adding Trace Headers


The first amp_ratio exercise involves getting a first break pick
time from the amp_ratio program, getting a quality estimate of
the first break pick time, and placing those values into a trace
header.

Read the Trace Headers chapter.


Next, edit amp_ratio1.f (or ampRatio1.c) so that the first break time
and first break quality information can be read into the trace header
for each trace. You can find solutions in the file amp_ratio.f or
ampRatio.c.

If you do not know how to compile and link the code into a new
exec.exe, review the Make System chapter.
Try your new program!
Remember to add the path to amp_ratio1.menu to your
Processes list. Review the Make System chapter if necessary.
Also remember that you need to have a .promax file set up in
your directory in order to tell ProMAX where to look for your
Processes file and where to find the executable code that you
have created. The .promax file is also discussed in the Make
System chapter.

Other Docs

Known Problems

Programming Exercises: Simple Tools (amp_ratio)22

Developers Programming Guide

Menus
A ProMAX menu is a file which controls how menu parameters
appear to the user.

Read the Menus chapter.


Copy the EXAMPLE.menu file to your own menu directory by typing
the following on the command line:
cd ~/$PROMAX_HOME/port/menu/promax
cp $PROMAX_HOME/port/menu/EXAMPLE.menu .

Use the pwin program described in the Menus chapter to experiment with menu parameters in EXAMPLE.menu.

Global Parameters
There are many numerical variables that are related to a dataset,
such as the number of samples per trace and the number of trace
headers that exist for each trace. ProMAX has a global include
file that you can access to easily get this information.

Read the Global Parameters chapter. C programmers can then look


at:
$PROMAX_HOME/port/include/cglobal.h

and/or read the C Environment chapter for more information.

amp_ratio Exercise 2: ordered parameter files


The next amp_ratio exercise involves putting the first break
information from the previous exercise into the ordered
parameter files in the database.

Read the Ordered Parameter Files chapter.


Edit amp_ratio2.f or ampRatio2.c to add parameters to the TRC
(trace) ordered parameter file; fill those database locations with the
appropriate information. Add the necessary code to the menu file to
allow the option of writing to the database.
You might notice that there is already code in amp_ratio2.f and
ampRatio2.c to take care of the trace headers.

Other Docs

Known Problems

Programming Exercises: Simple Tools (amp_ratio)23

Developers Programming Guide

Remember to change the Processes list to point to the right


menu since there is a different menu for amp_ratio1 and
amp_ratio2.

Run Makeexec on your new program and try it out.


Run the database display program and see the first break pick
times.

amp_ratio Exercise 3: time gates and tables


The final amp_ratio exercise is to limit the time window for
which the first break is searched. In the previous example, the
entire trace was searched for the first break. The start and end
times of the analysis window can be controlled through use of
ProMAX parameter tables which are stored in the database.

Read the Parameter Tables chapter. You can find additional information can be found in a chapter with the same name in the ProMAX
Reference Manual.

Edit amp_ratio3.f or ampRatio3.c; use ProMAX parameter tables to


limit the time window for which the first break is searched. Edit the
menu to allow the option to use the time gates and to get the time
gates from the database.

Other Docs

Known Problems

Debugging24

Developers Programming Guide

Debugging
Most full-time programmers find that use of a debugger speeds
up their code development. Use of the program dbx with
ProMAX requires a few special considerations, primarily
related to the packet.job file.

Read the Debugging with dbx chapter. Practice using the debugger
on one of the amp_ratio or ampRatio routines.

Other Docs

Known Problems

C Programming Environment25

Developers Programming Guide

C Programming Environment
The system level code of ProMAX is largely written in
FORTRAN, although most new ProMAX module development
is now in C and C++. The C programming environment actually
lies on top of the FORTRAN environment; therefore, there are a
few things that the C programmer should know about, including
some conveniences that have been developed for programming
in C.

Read the C Environment chapter.

Other Docs

Known Problems

Tool Types26

Developers Programming Guide

Tool Types
Before you continue on with other programming examples, you
need to know about other kinds of processing tools. As you
learned earlier in this chapter, the program amp_ratio is an
example of a simple tool, which is a processing tool that only
processes one data trace at a time. There are several other types
of tools that make handling multiple traces very convenient.

Read the Tool Types chapter. Pay particular attention to the responsibilities that each tool has in both the init and exec subroutines,
such as setting global variables and trace header values that the
trace executive uses.

Other Docs

Known Problems

Programming Exercise: Ensemble Tools (AVO)27

Developers Programming Guide

Programming Exercise: Ensemble Tools (AVO)


This section involves programming with ensemble tools.
Ensemble tools operate on bundles of traces.

Go to your personal maxtool directory:


cd ~/$PROMAX_HOME/port/src/lib/maxtool

Copy the avo_exer directory from the $PROMAX_HOME directory


tree by typing the following on the command line:
cp -r $PROMAX_HOME/port/src/lib/maxtool/avo_exer .

This routine is an AVO (Amplitude Variation with Offset)


module. The intent of this routine is that a CDP ensemble,
sorted by the absolute value of offset, is input into the exec
subroutine as a 2D array. The routine fits a least squares straight
line to the amplitude versus offset graph for each time sample in
the input array (see the following figure).
Least Squares Fit Line
Intercept of
LSF Line
Amplitude
Sample amplitude
at an offset

Offset
Least Squares fit line through Amplitude versus Offset Data
A single data trace is output for each CDP gather that is input to
the routine. The sample value at time T on an output trace is
either the slope or the zero-offset intercept of the least squares
curve shown in the figure above. A menu parameter allows the
user to select either slope or intercept as the output.

Other Docs

Known Problems

Programming Exercise: Ensemble Tools (AVO)28

Developers Programming Guide

Edit amp_ratio1.f or ampRatio1.c; input code where the comment


lines direct you to do so. A working solution to the exercise is in
amp_ratio.f and ampRatio.c.
Remember to change your tools_to_add file and Makefile
before running Makeexec. The entry in tools_to_add will look
like this:
AVO_EXER same panel

Note that the tool type is panel. This is because ensemble tools
have the same calling arguments as panel tools and are inserted
in the same part of the toolcall.f file.
A further example of an ensemble tool is in
$PROMAX_HOME/port/src/lib/maxtool/prestk_interp, which
outputs more traces in an ensemble than are input.

Other Docs

Known Problems

Programming Exercise: Panel Tools29

Developers Programming Guide

Programming Exercise: Panel Tools


Recall from the Tool Types chapter that panel tools are used to
process 2D arrays of traces that are too large to fit into memory
at one time. The 2D array is processed in pieces and then
blended back together by the trace executive. The next
programming example is a panel tool in which a 2D panel of
traces is given to the exec subroutine. The exec subroutine sets
the value of each sample in the input array to a constant value;
for example, all sample values are set to 2.0. The sample values
of the next panel input are set to a value that is 1.0 more than the
previous panel. The input from the menu controls how large a
panel will be and how many edge traces will be blended with
adjacent panels. This lets you experiment with panel parameters
and see the result on the screen. When using Screen Display or
Trace Display to see the data, use the Entire Screen option for
scaling the data traces so that the differences in trace amplitudes
can be seen.

Go to your maxtool directory and copy the panel directory from the
main system maxtool directory via the following commands:
cd ~/$PROMAX_HOME/port/src/lib/maxtool
cp -r $PROMAX_HOME/port/src/lib/maxtool/panel .

Edit the file panel_test.f or panelTest.c where the comments direct


you to do so. A working solution to this exercise is in panel_test.f or
panelTest.c.

Remember to change your tools_to_add file and Makefile before


running Makeexec. The entry in tools_to_add will look like this:
PANEL_TEST same ensemble

Also remember to change your Processes file before starting ProMAX so that the new menu will be read.

Other Docs

Known Problems

Programming Exercise: Input Tools30

Developers Programming Guide

Programming Exercise: Input Tools


An input tool is, by default, the first processing tool in a flow. It
is the tool that feeds trace data to the rest of the flow. The
exercise for an input tool can be found in
$PROMAX_HOME/port/src/lib/maxtool/sine_wave

The sine_wave.f and sineWave.c programs generate traces and


give them to the trace executive to be passed along to other
modules. The traces output from sine_wave consist of a set of
summed sine waves of user-specified frequency.

Copy the sine_wave directory to your own maxtool directory (see the
previous examples on how to copy a directory). Edit sine_wave1.f or
sineWave1.c and fill in the missing code where the comments indicate code needs to be added.
The entry in the tools_to_add file looks like this:
SINE_WAVE same complex

A working solution to this problem is in sine_wave.f and


sineWave.c. If you have problems with this module, review the
Tool Types chapter in this manual, paying special attention to
the responsibilities of an input tool, such as global variables and
headers. Then review the section on complex tools in that same
chapter, paying attention to the modes, in particular
EX_FLUSHMODE and EX_QUITMODE.

Other Docs

Known Problems

Programming Exercise: IPC Tools31

Developers Programming Guide

Programming Exercise: IPC Tools


An IPC Inter-Process Communication) Tool is a special type of
tool that allows the trace executive to pass data to and from a
separate unix process or separate piece of executable code. IPC
tools used to be called socket tools.

Read the IPC Tools section of the Tool Types chapter.


Copy the directory $PROMAX_HOME/port/src/exe/f_socket or
$PROMAX_HOME/port/src/exe/c_socket to your own directory tree;
that is, $~/$PROMAX_HOME/port/src/exe/f_socket or c_socket.
Notice that you are not in the maxtool directory where all work
has been done until now. The src/exe directory is for programs
that are not linked to the Trace Executive, or said another way,
tools that are not called from toolcall.f.
This exercise is just a demonstration of how to Make an IPC
tool executable. There is a file in the c_socket and f_socket
directories called Makefile. The Makefile contains, among other
things, the name of the output executable. The name is specified
where the Makefile states:
name = c_socket

The name of the executable must match the name of the


directory in which the Makefile resides. The Makefile also
contains a list of the object files that need to be used.

Make the IPC tool by simply typing gmake in the directory where
Makefile resides. Run the program by putting an entry in the Processes file for the path to the menu.
You can see another example of an IPC tool in
$PROMAX_HOME/port/src/exe/ampRatio for C programmers,
or in $PROMAX_HOME/port/src/exe/amp_ratio for
FORTRAN programmers. These examples show the amp_ratio
program in the form of IPC tools. The Makefiles and menus are
included and can be compiled and used in a processing flow.

Other Docs

Known Problems

Programming Exercise: IPC Tools32

Other Docs

Developers Programming Guide

Known Problems

33

Developers Programming Guide

System Overview

This chapter provides an overview of ProMAX. It describes the


directory structure of the system and the User Interface.

Topics covered in this chapter:

Other Docs

ProMAX Organization: Areas, Lines, and Flows


The User Interface: The Flow Builder
Menu Files
Flow Execution
Super Executive
Executive

Known Problems

ProMAX Organization: Areas, Lines, and Flows34

Developers Programming Guide

ProMAX Organization: Areas, Lines, and Flows


The primary function of ProMAX is to create, modify, and
execute processing flows. The program is built upon three levels
of organization: areas, lines, and flows. An area can represent
any grouping of seismic lines, but it is usually used as a
prospect level collection of seismic lines. A line (in 2D) or
survey (in 3D) usually represents a single seismic line or survey
in the tradition sense. A flow is a sequence of processes which
are used to manipulate seismic data. Flows are built by selecting
processes from a Processes list. A typical flow contains an input
process, one or more data manipulation processes, and a display
and/or output process.
Before we describe the system software any further, it is useful
if we first describe the directory structure of the system,
particularly the data files (see the ProMAX Directory Structure
illustration at the end of this chapter). The ProMAX home
directory defaults to /promax/1998.6, but you can re-specify
this via the environmental variable PROMAX_HOME. Beneath
the ProMAX home directory is a subdirectory named data/,
which you can also be re-specify with the environmental
variable PROMAX_DATA_HOME (see the ProMAX Data
Directory Structure illustration at the end of this chapter).
Any directory or symbolic link within the data/ subdirectory is,
by definition, an area. Any subdirectory or symbolic link
beneath an area subdirectory is, by definition, a line or a survey.
ProMAX expects a line to be a collection of data that can be
described by a single geometry. Most of the actual data files
reside at the line or survey directory level (see the Dataset
Components, Ordered Database Files, and Parameter Tables
illustrations at the end of this chapter). Traces, trace headers,
Ordered Parameter Files, and Parameter Tables, such as
velocities, first break picks, mutes, gates, trace kills, also reside
at this level.
Any subdirectory beneath a line or survey subdirectory
represents a further subgrouping, namely a flow. The flow
subdirectory contains all of the files related to a particular
processing flow, such as the saved binary job flow and the
runtime job output (see the Flow Components illustration at the
end of this chapter).

Other Docs

Known Problems

ProMAX Organization: Areas, Lines, and Flows35

Developers Programming Guide

There is an exception to the rules that govern the existence of


areas, lines, and flows in the database: any subdirectory with a
period in the name is ignored to facilitate the customization of
the database to contain non-ProMAX files.

Other Docs

Known Problems

The User Interface: The Flow Builder36

Developers Programming Guide

The User Interface: The Flow Builder


What people have come to know as ProMAX is sometimes
called the User Interface, but is more correctly called the flow
builder. This is the very top level of the system (see the System
Overview illustration at the end of this chapter). If you are
familiar with the previous generations of the processing system,
the flow builder is analogous to the editor that was used to build
jobs in those previous generations. In fact, the flow builder is
just a very specialized editor; it actually has no notion of
geophysics built into it. Its primary purpose is to present menus
and accumulate a collection of parameters, write those
parameters to disk, and then launch programs that will use the
parameters. The ProMAX Flow Builder Window Map
illustration (at the end of this chapter) sketches the various flow
builder menus, and the Flow Builder illustration (at the end of
this chapter) shows an screen image of the Flow Menu where
jobs are actually built and executed.

Other Docs

Known Problems

Menu Files37

Developers Programming Guide

Menu Files
In order for the flow builder to know how to present parameters
to the user, it must read menu specification files, which are also
called menu files. Menu files are closely integrated with the
underlying processing tools; both are usually written by the
same author. Within the menu files, programmers specify what
parameters should exist, what their properties aresuch as
parameter type, default value, and descriptionand how they
interrelate. Experience has shown that good menu parameter
specification evolves to the point of approaching a language; at
Landmark, we use Lisp, a language with suitable features. The
resulting menu specification is extremely well-suited to
handling traditional problems, such as context-sensitive hiding
of unused parameters, and is clearly one of the cornerstones of
ProMAXs success. Please refer to the Menus chapter for
further discussion of ProMAX menu specifications.

Other Docs

Known Problems

Flow Execution38

Developers Programming Guide

Flow Execution
When a user clicks on the Execute button on the Flow Menu,
the first step that the flow builder performs is to write all of the
parameters to disk in the form of a packet file. A packet file is
analogous to the ASCII job deck that existed in older systems,
except that it is binary in form and cannot be modified by any
editor except the flow builder. This protects the integrity of the
contents. The flow builder writes the packet file into the flow
directory that was created when the user constructed a new flow
or copied an existing flow. After the flow builder writes the
packet file, it executes the following shell command:
super_exec.exe packet_file host_name

Super Executive
The preceeding shell command launches the Super Executive,
or super exec for short. The flow builder executes this Super
Executive shell immediately, unless the job was submitted to a
queue. The Super Executive supplies the command line with the
path to the packet file and the name of the host on which the
flow builder is running. The Super Executive is, in a sense,
similar to the flow builderit is restricted in purpose and has no
notion of geophysics built into it. It is responsible for seeing
that the intended processing actually happens so the flow
builder can go off and do something else, like build another
flow.
The Super Executive first checks for the presence of multiple
tasks within the packet file. For example, if there are multiple
serial input steps in a flow, the Super Executive subdivides the
packet file and executes the separate jobs sequentially. In
addition, the Super Executive checks to see if a job should be
run on another host. It also performs other tasks, such as
expanding certain macrosfor example, the Parameter Test
in what we could loosely describe as filtering the packet file.
The Super Executive knows how to do most of these things
because it receives instructions from programmers via special
parameters that are included in the menu files, and are therefore
included in the packet file.
Some of the functionality within the Super Executive could be
included in the flow builder without changing the behavior of

Other Docs

Known Problems

Flow Execution39

Developers Programming Guide

the system. The exception is that the Super Executive waits on


the completion of the tasks that it spawns, rather than spawning
them in the background. This enables it to spawn processes
sequentially if required, and makes the spawning of one
subprocess contingent on completion of the previous one. It
also allows the Super Executive to report the completion status
of any process back to the flow buildereven processes that are
not strictly part of the ProMAX product.
After the Super Executive modifies the packet file, it writes a
new packet file in a scratch directory and launches the process
that does the actual work. In a normal processing flow, the form
of this command is:
exec.exe packet_file host_name PID

Executive
The preceeding command launches the Executive, or exec for
short. The Executive supplies the command line with the path to
the packet file, the name of the host on which the flow builder is
running, and the process ID of the Super Executive. If the
processing flow contains stand-alone or other special tools, the
correct path to the process which was specified in the menu file
is substituted for exec.exe. The full path to the process can vary
with release and may also be controlled by the user via the
Alternate Executive directive.
The Executive includes the actual processing tools, such as
gain, decon, filter, etc. Ordinary processing tools are not
separate programs, but are rather a set of routines that are linked
together in the Executive. Tools can be single trace input and
output types or one of a number of multi-trace types (see the
Processing Pipeline illustration at the end of this chapter). The
primary function of this document is to provide you with
information on how to add functionality to the Executive.
You will see the terms exec and Executive used frequently in
this document. They are often used interchangeably, but we will
restrict the term exec to refer literally to the program named
exec.exe, and the term Executive to refer to the body of
software that surrounds the actual processing tools and handles
the flow of data within the pipeline.

Other Docs

Known Problems

Flow Execution40

Developers Programming Guide

Each processing tool that is linked into the Executive must have
two parts: an initialization routine and an execution routine. The
initialization routine checks the input parameters for validity,
sets global parameters (if appropriate), creates header entries,
allocates memory, and other miscellaneous tasks that must be
performed before traces can be processed. The execution
routine is ideally a narrow-minded routine that simply processes
the traces and headers. Both routines are surrounded by the
Executive, which does everything it can to make life easy for
the initialization and execution routines.

Other Docs

Known Problems

Flow Execution41

$PROMAX_HOME

Developers Programming Guide

/sys

/bin
promax
promax3d
promaxvsp
/frame
/exe
/sdi
exec.exe
super_exec.exe /(3rd party softwar
*.exe
/plot
/lib
lib*.a
/help
promax2d.ps
promax3d.ps
promaxvsp.ps
(Manuals)

/port

/promax
*.lok (Frame helps
*.help (ASCII help
/promax3d
/promaxvsp

/menu
promax
promax3d
promaxvsp
/misc
*.rgb (colormaps)
ProMAX defaults
/etc
config_file
product
pvmhosts
qconfig
/scratch
/queues
/area1
/data
(or $PROMAX_DATA_HOME)

/line1

ProMAX Directory Structure

Other Docs

Known Problems

Flow Execution42

Developers Programming Guide

PROMAX_DATA_HOME
Area

/data

/area1
DescName
Project

Parameter Tables

Trace Headers

Line

/line1
DescName
12345678CIND
12345678CMAP

17968042TVEL
317490267TGAT
22783694TFBP
36247238TMUT

/12345678
HDR1
HDR2
TRC1
TRC2
/flow1
DescName (ASCII)
TypeName (ASCII)
job.output (ASCII)
packet.job (Binary)
job.output (Binary)
/flow2

Flow

/OPF.CDP (CDP)
#s0_OPF_CDP.GEOMETRY.C_S
#s0_OPF_CDP.GEOMETRY.ELE

Ordered Parameter
Files database

/OPF.CHN (Channel)
OPF60_CHN
OPF60_CHN.GEOMETRY.FOLD
OPF60_CHN.GEOMETRY.SLOOKUP

/OPF.ILN (Inline-3D)
/OPF.LIN (Line)
/OPF.OFB
/OPF.PAT (Pattern)
/OPF.SIN (Source)
/OPF.SRF (Surface Station)
/OPF.TRC (Trace)
/OPF.XLN (Crossline)
/OPF.XLN (Crossline-3D)

ProMAX Data Directory Structure

Other Docs

Known Problems

Flow Execution43

Developers Programming Guide

Traces

Trace
Headers

Misc.
Map

Dataset Components

Line
Units
X Ref
Y Ref
Lo Cut
Hi Cut
Total # of CDPs
etc.
Source
X Coord
Y Coord
Chans
Uphole
Static
Elevation
etc.

Trace
FB Pick
Offset
Static
etc.
Surface Location
Fold
X Coord
Y Coord
Static
Datum Vel
etc.

Channel
Static
Amplitude Com
etc.

CDP
Fold
X Coord
Y Coord
Elev
Nearest SRF
Elev Static
etc.

Other Docs

Offset
Bin Center
Mean Offset
etc.

Known Problems

Flow Execution44

Developers Programming Guide

Mutes

Gates

Surg Mutes

Kills

Reversals

Horizons

Velocities

Etc....

Ordered Database Files


Parameter Tables

Flow
Directory

Packet File
(packet.job)

Job Output
(job.output)

DescName

TypeName

Flow Components
Other Docs

Known Problems

Flow Execution45

Developers Programming Guide

Job Builder
(promax.exe)
Batch
Queue
Super Executive
(super_exec.exe)

Stand-alone
Programs

Executive
(exec.exe)
Tool Caller
AGC

Diskread

NMO

Line Database
Information
(datasets, parameter tables,
ordered database files, etc.)

Mute
Filter

Packet File

System Overview

Other Docs

Known Problems

Flow Execution46

Developers Programming Guide

ProMAX Flow Builder Window Map

Other Docs

Known Problems

Flow Execution47

Developers Programming Guide

Windows
Overlap

Area: XXXXXX
Line: YYYYYY
Flow: ZZZZZZ

Edit Flow

Seismic Datasets

Other Docs

Processes

Window
Overlay
Parameter Tables

Known Problems

Flow Execution48

Developers Programming Guide

Global OptionsProcessing Flow

Flow Builder

Other Docs

Known Problems

Flow Execution49

Developers Programming Guide

Input
Data

FK Filter
Gain
Running Mix
Mute
Stack
NMO

Output
Data

Single Trace Processes

Multi-Trace Processes

Processing Pipeline

Other Docs

Known Problems

Flow Execution50

Other Docs

Developers Programming Guide

Known Problems

51

Developers Programming Guide

Executive

This chapter describes the architecture and functions of the


Executive system.

Topics covered in this chapter:

Other Docs

System Architecture
Headers and Global Variables
Input Tools
Re-entrancy
Common Blocks and Parms Structures
Executive Functions
Communication between Tools
OPF Database

Known Problems

System Architecture52

Developers Programming Guide

System Architecture
The ProMAX Executive is a pipeline system. In this system,
traces are dropped into the flow one at a time by the input tool
(see the Processing Pipeline illustration at the end of the System
Overview chapter). Individual traces continue to drop through
the flow until they encounter a multi-trace processing tool. The
trace executive collects all of the necessary traces for the
multi-trace processing tool and returns the traces back to the
flow when the tool is finished.
There are a variety of tool types; each type is designed to
minimize the coding required to implement the necessary trace
handling. These tool types range from simple, single-trace
input/output tools, to multi-trace input/output tools of a variety
of natural trace groupings, and finally to complex tools that
facilitate the ultimate user control of trace buffering. Please see
the Tool Types chapter for a description of each tool.
The Executive creates an essentially isolated environment for
each tool. It manages most of the tedious duties of trace and
trace header I/O, data buffering, initialization of global
variables, and other miscellaneous tasks. The following sections
describe these duties.

Other Docs

Known Problems

Headers and Global Variables53

Developers Programming Guide

Headers and Global Variables


At run time, each tool is presented with a list of active headers
and a set of initialized global variables. The header list contains
the description, format, and size of all headers that are valid at
that step in the flow. The global parameters can be categorized
as static or volatile. The static type of global parameters are
typically geometry-related: the number of CDPs, minimum and
maximum station number, maximum offset in data, etc. The
volatile type of globals, named global run time or run time
variables, refer to variables that can change from step to step
within the flow: sample rate, trace length, sort order, maximum
ensemble size, etc.
Headers can be added or deleted and run time variables changed
at any step in the flow; for example, resampling changes the
sample rate and trace length. Because of this, the Executive
actually keeps a separate copy of headers and run time globals
for every step in the flow. In a sense, then, the environment
changes dynamically as traces pass from tool to tool. Please see
the Global Parameters and Trace Headers chapters for details
on these subjects.
It is important to note, however, that the global run time
attributes cannot change within a process or tool. In other
words, while the sample rate, sort, trace length, and maximum
ensemble size can all change from tool to tool, they can not
change from trace to trace, such as by shot position within a
tool. Please review the list of run times in the Global
Parameters chapter.

Other Docs

Known Problems

Input Tools54

Developers Programming Guide

Input Tools
The primary responsibility for setting the globals and
establishing the current header list is assigned to the first tool in
the flow, which by definition is an input tool. All input tools
must retrieve the current state of headers and run time variables
from the input ProMAX dataset and must make these available
to subsequent tools. The input tool must also retrieve the
remaining static global variables from the Ordered Parameter
Files (geometry). If your input tool is reading a non-ProMAX
(foreign) dataset or creating data, you are responsible for
retrieving the necessary data from whatever source and creating
all possible header and global values. See the Input Tool
Examples in the Appendix for code examples.

Other Docs

Known Problems

Re-entrancy55

Developers Programming Guide

Re-entrancy
Another related issue that the Executive manages is the issue of
re-entrancy. As mentioned above, the Executive attempts to
isolate each tool in such a way that the programmer codes his
tool as if it is the only one in the flow. There is no need to worry
about a ProMAX user putting your tool in the flow multiple
times, which could create confusion over which set of
parameters goes with which instance of the tool. Nor is there
need to worry about two tools coincidentally sharing identical
menu parameters or internal local variables. The Executive
assures that each tool can only access menu parameters from its
corresponding menu in the flow; it offers protection for
duplicate variables.

Other Docs

Known Problems

Common Blocks and Parms Structures56

Developers Programming Guide

Common Blocks and Parms Structures


The Executive manages a SAVED_PARMS COMMON block
for each tool for FORTRAN code, or a parms structure for C
code. The n FORTRAN COMMON block or C parms structure
stores variables that need to be passed from the initialization
routine to the execution routine, or local variables that must
retain their values between each call of the Executive routine.
Clearly this must be accomplished by swapping a separate
COMMON block in and out of memory for each step in the
flow. Again, the application programmer can develop a routine
as if it is the only tool and with a single COMMON block. The
FORTRAN SAVED_PARMS COMMON block must be fixed
in size to accommodate memory swapping. Currently the size is
limited to 1000 4-byte words. If your application requires more
than a small fraction of this, you are probably misusing the
space by passing arrays instead of pointers or indexes to the
FORTRAN RSPACE memory array.
As described in the Executive section of the System Overview
chapter, each tool consists of two FORTRAN or C routines: the
initialization (or init) routine, and the execution (or exec)
routine. The Executive runs each of the init routines in the flow
once. The exec routines are cycled through many times until all
of the traces are processed through the pipe. The init routine is
responsible for reading menu parameters, making any one-time
calculations, resetting run time parameters (for example,
changing the maximum ensemble size to one if stacking), and
creating/deleting headers entries. Remember, changing the
status of the headers or global run time parameters must be
done in the init routine in order for other init routines to be
aware of the change. This is one of the few situations where you
must consider what happens before or after your application.

Other Docs

Known Problems

Executive Functions57

Developers Programming Guide

Executive Functions
The exec routine does the actual trace processing. The
Executive passes traces and headers to the exec routine in
buffers and expects the processed traces to be in the same
buffers when exiting the routine. If the tool is a multi-trace type,
the Executive will allocate the memory necessary to accumulate
the proper trace grouping, then free the memory after that group
of traces is processed and passed to the next tool. This memory
management is done automatically without any coding at the
tool level. Often you will need to dynamically allocate
additional memory within the tool to hold temporary results.
This is supported both in FORTRAN and C, but it is assumed
that such memory will be de-allocated upon exiting the exec
routine. Remember that many tools could comprise a flow: your
tool could be repeated many times. After exiting your
multi-trace exec routine, it might be some time before the
remaining flow is executed and traces are again accumulated
and passed to your exec routine. This is another situation where
you must consider the entire flow instead of simply your
application. It is assumed system-wide that two ensembles will
fit comfortably in memory. However, tools that require many
ensembles, multiple copies of ensembles, or large collections of
stacked traces should buffer traces on disk or process panels of
traces.

Other Docs

Known Problems

Communication between Tools58

Developers Programming Guide

Communication between Tools


As previously discussed, tool-to-tool isolation makes the
programming environment simple, and the Executive does this
task well. However, inter-tool or inter-process communication
is necessary. Tools that change the sample rate, trace length, kill
a trace, statically shift a trace, etc., need to communicate this
change to processes later in the flow or in a subsequent flow.
Trace headers move with the data, and are an excellent way to
tag traces with information that may be required for a future
process. Headers move through the flow and are stored on disk
or tape upon output. Run time global parameters are also an
excellent vehicle for communicating global changes in the data.
As with headers, they move through the flow and are stored
with the traces upon output. However, these global parameters
cannot change from one trace to the next within a tool.

Other Docs

Known Problems

OPF Database59

Developers Programming Guide

OPF Database
The Ordered Parameter Files database is another form of
inter-tool communication. Refer to the Ordered Parameter Files
chapter for a definition of this database. It is typically used to
communicate information that is global to all datasets within
the line; field geometry data is a good example. Convenience is
a governing factor in choosing the form of communication that
is used. For example, geometry information that is placed in the
Ordered Parameter Files database can be conveniently accessed
by stand-alone programs that do not wish to read trace data.

Other Docs

Known Problems

OPF Database60

Other Docs

Developers Programming Guide

Known Problems

61

Developers Programming Guide

Make System

This chapter provides an overview of the ProMAX make


system.

Topics covered in this chapter:

Other Docs

Working with ProMAX Systems


Getting Started
System Administrator Setup
User Setup: Aliases, Makeadvance, Makeexec
Converting to the New System
Understanding the Directory Structure
Customizing the System
Toggling Products: .promax
Adding a New Tool
Making Your New Executable
Incorporating New Functionality
Creating Menus
Adding a ProMAX menu
Changing Files
Understanding the Makefile System

Known Problems

Working with ProMAX Systems62

Developers Programming Guide

Working with ProMAX Systems


The ProMAX file and recompilation systems allow large groups
of programmers to develop and maintain software for multiple
machine types from a single master copy of source code. Some
important features of these systems are:

Other Docs

All Landmark software lies beneath a single directory, e.g.


/promax/1998.6/, in subdirectories with standard UNIX
names like bin/, include/, lib/, and src/. We will henceforth
refer to this directory as the environment variable
$PROMAX_HOME.

To support concurrent development, each programmer has


a subset of $PROMAX_HOME (containing the files they are
working on) in their home directory.

Machine-dependent subdirectories of $PROMAX_HOME


enable a single file server or programmers home directory
to contain executable programs and libraries for all
machine types supported by Landmark.

Software is organized to facilitate the evolution of


Landmark products, such as ProMAX, ProMAX VSP, and
ProMAX 3D.

Third-party software is organized to facilitate distribution


(if permitted) to Landmark clients and to avoid conflicts in
file names among different third-party vendors.

GNU make (gmake) is used to build executable programs


and libraries and is provided with the ProMAX developer
kit.

Programmers write Makefiles, one for each program or


library, with compilation, link and installation commands
that may be customized without affecting other programs.

Makefiles used at Landmark are designed to be used by


Landmark clients.

Source code can be compiled and linked from one location


for all machine types supported by Landmark.

Known Problems

Getting Started63

Developers Programming Guide

Getting Started
The following sections describe the System Administrator and
User setup.

System Administrator Setup


The following steps must be performed after installing the
ProMAX release to configure the Development Environment.
These steps help ensure that you will have little trouble when
attempting that first compile and link.

Modify the $PROMAX_HOME/port/include/make/master.make file


1.

Change the line atopdir := /promax/1998.6 to be the


absolute path to your $PROMAX_HOME directory. An
example might be:
atopdir =: /Landmark/ProMAX/1998.6

2.

Change the line utopdir := $(HOME)/promax/1998.6 to


be the path where each developer will build and use his
own copy of the ProMAX development tree. An example
might be:
utopdir=: $(HOME)/Landmark/ProMAX/1998.6

Generally, Landmark recommends the above convention of


making each users development path parallel the master
installation path.
3.

Verify the line ctopdir := is blank. Typically you will leave


this field blank. This is used when clients have in-house
software which they want to be able to link with Landmark
libraries, or if they have their own special versions of the
Landmark libraries which should take precedence over the
standard Landmark libraries.

Additional Setup Step


For each platform on which your company develops, review the
corresponding [machine type].make file located in

Other Docs

Known Problems

Getting Started64

Developers Programming Guide

$PROMAX_HOME/port/include/make/. Such files are supplied


for the following machine types:

crayymp
rs6000
sgimips
sgimips4
solaris

The [machine type].make file should point to the default


locations of such things as compilers, include files, and
libraries; however, if your system has these located in
nonstandard places, you will have to edit the appropriate
[machine type].make file to reflect this.

Solaris Users
If your target development machine type is solaris, each
development machine should have a symbolic link from /bin/cc
to the location of your companys C compiler. This is used by
the gmake system to figure out what platform you are on; it
determines this via the extra DEFINES that each platforms C
compiler sends in by default.
To get the C compiler to be recognized on Solaris, you need to
create the following symbolic link:
ln -s /opt/SUNWspro/bin/cc /bin/cc

Automounter Users: If your development directories tend to


be automounted, the makefile system sometimes has difficulty
in determining what atopdir really is. It figures this out via the
lines:
atopdir := /promax/1998.6
atopdir := $(shell cd

$(atopdir); /bin/pwd)

If you suspect that you have a discrepancy here, cd to


atopdirin this case /promax/1998.6and type /bin/pwd. If it
is an automounted directory, it should return the actual path,
something like /tmp_mnt/promax/1998.6. If it returns
/promax/1998.6, you may have a problem which might be
solved a number of ways:

Other Docs

Hard mount the ProMAX master directory.

Known Problems

Getting Started65

Developers Programming Guide

Change /bin/pwd to a pwd program which returns the


proper path.

Change the definition of atopdir to reflect the automounted


version.

User Setup
The following sections describe the User setup.

Creating Aliases, Makeadvance, Makeexec


To use the make system, complete the following four steps if
you have not already done so (this assumes that you have
already installed the release distribution). Substitute
/promax/1998.6 with whatever directory your system
administrator used to install the release. Because most ProMAX
development and testing is done using the Unix ksh command
interpreter, including all Makefile and shell script commands,
Landmark recommends you employ ksh for developing your
own ProMAX modules as well. It is normally straightforward to
develop under other command interpreters and the following
instructions include settings for several popular alternatives to
the ksh.
1.

Place the release toplevel directory into environment


variable PROMAX_HOME.
For csh/tcsh users this line might look like:
setenv PROMAX_HOME /promax/1998.6

For ksh/zsh/sh users this line might look like:


export PROMAX_HOME=/promax/1998.6

2.

Other Docs

Add $PROMAX_HOME/sys/bin and


$PROMAX_HOME/port/bin to your path (or PATH) in your
~/.cshrc (or ~.profile, depending on your shell and what
files it looks for upon login). csh looks for a .cshrc; tcsh
looks for a .tcshrc (if it cannot find one of these, it uses a
.cshrc); zsh looks for a .zshrc; sh and ksh use .profile. If
you are unsure of which shell you are using, the command
env | grep SHELL should tell you.

Known Problems

Getting Started66

Developers Programming Guide

For csh/tcsh users this line might look like:


set path = ($path /promax/1998.6/sys/bin \
/promax/1998.6/port/bin)

For ksh/zsh/sh users this line might look like:


export PATH=$PATH:/promax/1998.6/sys/bin:\
/promax/1998.6/port/bin)

3.

Add the following lines to your ~/.cshrc, ~/.tcshrc,


~/.zshrc, or ~/.profile file.
Csh/tcsh users:
alias gmake '$PROMAX_HOME/sys/bin/gmake \
-I$PROMAX_HOME/port/include/make'
alias Makeexec '$PROMAX_HOME/port/bin/Makeexec \
-I$PROMAX_HOME/port/include/make'

Ksh/sh/zsh users:
alias gmake='$PROMAX_HOME/sys/bin/gmake \
-I$PROMAX_HOME/port/include/make'
alias Makeexec='$PROMAX_HOME/port/bin/Makeexec \
-I$PROMAX_HOME/port/include/make'

This tells gmake and Makeexec where to look for included


files.

Other Docs

4.

Csh users should type source .cshrc (or .profile) to reset


your aliases and paths. Ksh users should type the command
. .kshrc to reset their aliases and paths.

5.

Type Makeadvance. This will make a User development


tree under your home directory. In addition to making lots
of directories, Makeadvance will also put a Makefile into
your ~/advance/port/src/exe/exec/ as well as your
~/advance/port/src/lib/maxtool/ directory. You should
study the two Makefilesthey are short because they
include other files that do most of the work. (The other files
are in $PROMAX_HOME/port/include/make/.)

6.

From somewhere in your ~/$PROMAX_HOME/port/src/


directory, type Makeexec. This will take a while.

Known Problems

Getting Started67

Developers Programming Guide

Makeexec invokes a script that makes any or all variants of


the ProMAX exec.exe files. It simply cds to

~/$PROMAX_HOME/port/src/exe/exec, where the


Makefile for exec.exe resides, and does a gmake with the
arguments that you provide to Makeexec.
FORTRAN or C toolcall: By default, Makeexec builds
and compiles a FORTRAN version of toolcall, toolcall.f.
By setting the option language=C for the Makeexec
command, that is Makeexec language=C ..., Makeexec
builds and compiles a C version of toolcall, toolcall.c. This
allows the building of exec.exe without a FORTRAN
compiler.

Understanding What Happens


Because exec.exe depends on libraries, such as libmaxtool*.a,
in addition to files like toolcall.f or toolcall.c, the first thing
Makefile does is check the libraries to see if it should try to
update them. To help Makefile make this decision:

if a Makefile exists in the src directory for the library, then


it ensures that the library is up-to-date by changing to that
directory and running gmake; or,

it uses the master version of the library and assumes that it


is up-to-date.

When you run Makeexec the first time, the Makefile in your
~/$PROMAX_HOME/port/src/exe/exec/ directory finds the
Makefile in your ~/$PROMAX_HOME/port/src/lib/maxtool/,
cds to that directory, and does a gmake. Because you do not
have any of the libmaxtool*.a or libmaxtool*.so libraries in
your User version of ~/$PROMAX_HOME/, the Makefile in
~/$PROMAX_HOME/port/src/lib/maxtool/ will create these
libraries for you. This is the time-consuming part of running
Makeexec the first time: the libmaxtool* libraries are big and
you do not have them yet.

First-time compilation
Unlike the Master version of
$PROMAX_HOME/port/src/lib/maxtool/, your User version
does not (yet) contain any source code. Therefore, the Makefile
simply copies the libraries

Other Docs

Known Problems

Getting Started68

Developers Programming Guide

$PROMAX_HOME/[machtype]/lib/libmaxtool* over into your


~/$PROMAX_HOME/[machtype]/lib/ directory. Note that
machtype varies, depending on which platform you are
making on. It is rs6000 on the IBM, sgimips or sgimips4 on the
Silicon Graphics, crayymp on the Cray, and solaris on systems
running Solaris 2.x. After your own libmaxtool* libraries have
been built, your toolcall.f or toolcall.c will be created and
compiled and your exec.exe will be linked. The toolcall is
created by the script $PROMAX_HOME/port/bin/buildtoolcall.
This script looks at the file
$PROMAX_HOME/port/src/exe/exec/tools.db, then deletes
any entries found in
~/$PROMAX_HOME/port/src/exe/exec/tools_to_delete, then
adds any tools found in
~/$PROMAX_HOME/port/src/exe/exec/tools_to_add.
Based on the arguments to Makeexec or gmake, the buildtoolcall
script will then build a
~/$PROMAX_HOME/port/src/exe/exec/toolcall.f FORTRAN
file (default), or a
~/$PROMAX_HOME/port/src/exe/exec/toolcall.c C file if
buildtoolcall is invoked from gmake or Makeexec with
language=C. The new toolcall source file will then be compiled
and linked into a working
~/$PROMAX_HOME/[machtype]/exe/exec.exe executable.

Nth-time compilation
You can run Makeexec from anywhere within your
~/$PROMAX_HOME/port/src/ hierarchy. In particular, you
can run it inside your
~/$PROMAX_HOME/port/src/lib/maxtool/xxx/ directory,
where you have just finished modifying the source code for
your latest and greatest new tool.
For new exec tools, you must specify the source files for each
new tool in the newsrcs variable in your
~/$PROMAX_HOME/port/src/maxtool/Makefile.

Other Docs

Known Problems

Converting to the New System69

Developers Programming Guide

Converting to the New System


Normally, it is sufficient to copy source files and Makefiles from
your previous user development tree into your new user tree to
build them under the new system. You will probably want to
rexamine your Makefile(s), if any, for local dependencies.
Landmark has created several Makefile examples in
$PROMAX_HOME/port/include/make to assist in creating
Makefiles for new tools or reworking older Makefiles for
improved compatibility.

Other Docs

Known Problems

Understanding the Directory Structure70

Developers Programming Guide

Understanding the Directory Structure


Before dealing with the details of the development system, it is
essential to have a basic understanding of the directory structure
in which it functions. A few of the files and directories of
interest in the development system include:

$PROMAX_HOME/port/include/make/
$PROMAX_HOME/port/bin/
$PROMAX_HOME/sys/bin/
$PROMAX_HOME/port/src/exe/exec

$PROMAX_HOME/port/include/make/
This directory contains the makefile header files which are used
to set up for various possible configurations. It also contains
sample makefiles for a library or stand-alone executables. The
following table summarizes these files.
$PROMAX_HOME/port/include/make/ Files
File

Description

master.make

This is the file which is responsible for setting up the basic variable structures
representing the clients directory structure. This file can be included instead
of advance.make if all you need from your makefile include are variables
containing paths to advance things. In this respect, it serves as a lightweight
header include.

advance.make

This header file includes master.make and sets up anything which is constant
among all platforms such as Canned Command Sequences. It also includes
$machtype.make to import its platform dependent information.

$machtype.make

This represents the header file containing the platform dependent information
such as preprocessing, compiling, and link commands. As this varies
dramatically from system to system, Landmark provides some reasonable
defaults. Even so, clients installing ProMAX will probably need to modify
this file to reflect their particular system setup.

simple.make

A simple makefile used to compile one or more executables into the current
directory.

compile.test

A simple makefile used in conjunction with


$PROMAX_HOME/port/bin/ctest which allows you to compile source files
into executables.

libmaxtool.example

An example user makefile for the maxtool[1-3] libraries. This file is used by
Makeadvance to create a user environment.

Other Docs

Known Problems

Understanding the Directory Structure71

Developers Programming Guide

$PROMAX_HOME/port/include/make/ Files (Continued)


File

Description

exec.example

An example makefile for the executive. This file is used by Makeadvance to


create a user environment.

stand_alone1.example

An example makefile for a stand-alone module. This file is used by


Makeadvance to create a user environment.

stand_alone2.example

An example makefile for a stand-alone module utilizing the maxprog.make


template.

maxprog.make

A template or recipe for building an ordinary stand-alone executable.


maxprog.make is merely a series of includes of other smaller granularity
actions. Thus, if maxprog.make does not work well a large number of
applications, it is possible to create a new template without having to rewrite
each part.

maxprog++.make

A template, similar to maxprog.make, which links via the C++ compiler.

Makefile_example_*

Sample makefiles for creating new modules under the bin, exe, and lib user
port/src development subdirectories.

The following examples use files from this directory.

Example: simple.make
This makefile example uses simple.make to compile into the
current directory.
1.

cd $HOME

2.

mkdir simpletest

3.

cd simpletest

4.

Edit Makefile to look like:


srcs1 := a.c b.c
srcs2 := c.c d.f
exec1 := abtest
exec2 := cdtest
include simple.make

5.

Edit a.c to look like:


#include <stdio.h>
a() {printf(a()\n);}

Other Docs

Known Problems

Understanding the Directory Structure72

6.

Developers Programming Guide

Edit b.c to look like:


#include <stdio.h>
b() {a(); printf(b()\n);}
main() {b();}

7.

Edit c.c to look like:


#include <stdio.h>
c_() {printf(c()\n);}

8.

Edit d.f to look like:


SUBROUTINE D
CALL C
WRITE(*,*)D()
RETURN
END
PROGRAM D
CALL D
END

9.

Type gmake. The executables abtest and cdtest should be


compiled in the current directory.

Example: compile.test
This makefile example uses compile.test.
1.

cd $HOME

2.

mkdir compiletest

3.

cd compiletest

4.

Edit a.c to contain:


#include <stdio.h>
main() {printf(Hello World From a.\n);}

5.

Edit b.f to contain:


PROGRAM MAIN
WRITE(*,*) HELLO WORLD FROM MAIN()
END

6.

ctest a b should compile executables a and b corresponding

to your source code a.c and b.f.

Other Docs

Known Problems

Understanding the Directory Structure73

Developers Programming Guide

Example: maxprog.make
For this makefile example, maxprog.make might look like:
include
include
include
include
include
include
include
include
include
include

advance.make
exe_setup.make
exe_top.make
depend.make
exe_link.make
exe_f77_compile.make
exe_ansic_compile.make
exe_cxx_compile.make
exe_clean.make
phony.make

You might decide that you need a version of maxprog.make,


such as maxprog++.make; this operates just as maxprog.make,
except that the C source code is compiled via the K&R C
compiler by default. In this case, all you have to do is copy
maxprog.make to krc_maxprog.make and substitute
"include exe_ansic_compile.make" for
"include exe_krc_compile.make".

$PROMAX_HOME/port/bin/
This directory contains portable scripts which can be run from
the command line. The following table summarizes these
scripts.
$PROMAX_HOME/port/bin/ Files
Script

Description

Auto_test

A script which automates quality control testing on various platforms.

Makeadvance

A script which sets up a user development environment.

Makeexec

A script which creates a user version of the executive.

Setqueues

A script which allows users to toggle between NQS and LPD queues.

adoc

A script which allows users to read documentation.

aman

A script which allows users to get online man pages.

Promax

A script which is used to bring up the user interface.

makewhatis

A script which is used to make the whatis/windex for man pages. Must be
executed from the man directory.

checkin2

A script which is used to check in a previously checked out Landmark sccs file.

checkout2

A script which is used to check out an Landmark sccs file.

Other Docs

Known Problems

Understanding the Directory Structure74

Developers Programming Guide

$PROMAX_HOME/port/bin/ Files (Continued)


Script

Description

testFlows

Another script which is used for automated testing.

buildtoolcall

A script which is used to build toolcall source in FORTRAN or C. It is normally


called from the Makefile but may also be invoked from the command line.
buildtoolcall accepts as an optional first command line argument -C; this switch
instructs buildtoolcall to build C code instead of the default FORTRAN.

app

A small script which preprocesses, adding $PROMAX_HOME/port/include and


$PROMAX_HOME/port/include/private to your include paths.

pvmcleanup

A script which kills and cleans up after stray pvm daemons.

pvmdbx.sh

A script which is invoked by an xterm by the generic debugger script. It starts


the debugger and waits when it exits to prevent the window from closing.

Makelink

A script which is used to create a link from a file in a users directory to the
corresponding file in the $PROMAX_HOME directory.

Nmgrep

A utility used for extracting information from object files.

Fid

A simple utility used to print out include dependencies in a file.

$PROMAX_HOME/sys/bin/
This directory contains non-portable scripts which can be run
from the command line. The following table describes these
scripts.
$PROMAX_HOME/sys/bin/ Files
Script

Description

amakedepend

Landmarks version of makedepend. Generates dependencies for use with the


Makefile system.

aviewer

Landmarks command-line interface to FrameViewer.

copycat

A program which runs every 1/2 hour and takes the tape catalog files and copies
them to another directory. It ensures that there is always an uncorrupted version
of the tape catalog database handy.

ctags

A program used to generate tag files for vi.

ctar

A program similar to UNIX tar except that it understands the notion of


secondary storage. It uses the advance tape catalog optionally.

emacs

An editor provided by the Free Software Foundation.

etags

A program used to generate tag files for emacs files.

Other Docs

Known Problems

Understanding the Directory Structure75

Developers Programming Guide

$PROMAX_HOME/sys/bin/ Files (Continued)


Script

Description

gmake

AKA Gnu Make. Gnus version of the make utility.

ll

AKA lisp listener. A lisp interpreter implementing Landmarks lisp. Useful for
rule writers wanting to check syntax.

lmdown

A flexlm program for taking a lmgrd daemon down.

lmgrd

The flexlm licensing daemon.

lmreread

A program causing the lmgrd daemon to reread a license.dat file.

lmstat

A program which outputs statistics pertinent to licensing.

nmapmgr

NQS tool for building and maintaining the machine ID database.

nqs_promax

The ProMAX accounting daemon which may also be used as an alternative to


rsh (if rsh is not available).

perl

Perl version 5.000. Practical Extraction and Reporting Language. A program


used to interpret Perl scripts. Many of the scripts, including the installation
script, are written in Perl. Perl provides powerful text manipulation mechanisms
and is also strong in the area of process management.

pixmap

A program used to build pixmaps. Useful if you are using the agX libraries.

pkt_dump

A program used to display a packet file to standard out.

promax

Landmarks 2D GUI.

promax3d

Landmarks 3D GUI.

promaxvsp

Landmarks VSP GUI.

ptt

A program used to generate an ascii version of packet.job, which can then be


read into an editor, modified. ttp can then be called to translate the ascii file back
to a packet.job.

pwin

A menu interpreter/editor allowing menus to be created interactively.

qdel

NQS routine (see man pages).

qdev

NQS routine (see man pages).

qjob

NQS routine (see man pages).

qlimit

NQS routine (see man pages).

qmgr

NQS routine (see man pages).

qpr

NQS routine (see man pages).

qstat

NQS routine (see man pages).

qsup

NQS routine (see man pages).

tamsh

A tcl/motif interpreter/shell. This allows the creation of tcl scripts which contain
motif widgets. This is a powerful homegrown version based upon Jan
Newmarchs TclMotif.

Other Docs

Known Problems

Understanding the Directory Structure76

Developers Programming Guide

$PROMAX_HOME/sys/bin/ Files (Continued)


Script

Description

tcat

A program used to manage the tape catalog system.

tcatd

A daemon which performs transactions on a tape catalog.

tclsh

A tcl interpreter/shell.

tkperl

Perl 5.000 with the Tk and ReadLine extensions. This version of perl allows
users to create scripts which have graphical user interfaces.

ttp

A program used to translate a ptt ascii file back into a packet.job.

$PROMAX_HOME/port/src/exe/exec/
The directory contains the executives makefile as well as
listings of base tools, tools to add, and tools to delete. The
following table summarizes this directorys contents.
$PROMAX_HOME/port/src/exe/exec/ Files
Item

Description

Makefile

The makefile for the executive.

tools.db

A base listing of inline tools which will be incorporated into the executive.

tools_to_add

A listing of inline tools to add to the executive. Users may, and should, have a
personalized version of this file.

tools_to_delete

A listing of inline tools to delete from the executive. Users may streamline their
personal version of the executive with this file.

Other Docs

Known Problems

Customizing the System77

Developers Programming Guide

Customizing the System


Much of the system can be customized via the environmental
variable; that is, the path to most files and directories can be
re-specified. The name of the environmental variable is always
the path name, with the slashes replaced by underscores, every
character promoted to upper case, and _HOME appended.
Note that the rules are the same regardless of whether the file is
an ordinary file or a directory (even though intuition might
suggest that the environmental variable should end in _PATH
for ordinary files, instead of _HOME). Some of the important
ProMAX environmental variables are:

Other Docs

PROMAX_HOME
PROMAX_DATA_HOME
PROMAX_PORT_MENU_HOME
PROMAX_PORT_MENU_PROCESSES_HOME
PROMAX_SYS_EXE_HOME
PROMAX_ETC_CONFIG_FILE_HOME
PROMAX_QUEUES_HOME
PROMAX_ETC_PVMHOSTS_HOME
PROMAX_SCRATCH_HOME
PROMAX_SCRATCHX1_HOME
PROMAX_SCRATCHX2_HOME
...

Known Problems

Toggling Products: .promax78

Developers Programming Guide

Toggling Products: .promax


Parts of the system can also be customized via the .promax file
in the users home directory. This method allows customization
by product and facilitates toggling between products without
exiting the Flow Builder. The Flow Builder will build a .promax
file in your home directory the first time you exit the User
Interface.
For the programmer, the .promax file is the best way to control
the development environment. A search path mechanismfor
executables, menus, and help filesdirects the flow builder to
use the files in your personal directories before searching in the
standard installation or other directories. In this way, you can
maintain your own parallel ProMAX system. To override the
standard paths, the ~/.promax file must contain a stanza of the
following form:
(:product
("P" "ProMAX 2D" "entry3" "entry4" "entry5" "entry6" \
"entry7" "entry8" t)
("p" "Prospector" "entry3" "entry4" "entry5" "entry6" \
"entry7" "entry8" t)
("3" "ProMAX 3D" "entry3" "entry4" "entry5" "entry6" \
"entry7" "entry8" t) )

Entry3 is the absolute or relative pathname to the directory


containing the executable files for the product. If specified as a
relative pathname, it will be appended to
$PROMAX_SYS_EXE_HOME. The executable directory is
common to all Landmark products. There are no
product-specific subdirectories. The default entry would be
blank, directing the flow builder to the standard ProMAX /exe
subdirectory typically defined by the environmental variable
$PROMAX_SYS_EXE_HOME. For your development
environment, the following entry may be preferred:
"~/[$PROMAX_HOME]/rs6000/exe/:[$PROMAX_HOME]/rs6000/exe"

This entry will cause a search of your exe directory for exec.exe
(or other executables) and the system exe directory next. For
this specific case you could use:
"~/[$PROMAX_HOME]/rs6000/exe/:."

The . following or preceding the colon denotes the system


default as specified by environmental variables.

Other Docs

Known Problems

Toggling Products: .promax79

Developers Programming Guide

The preceeding entry assumes that you are working on an IBM


RS6000 machine. If you are developing code across multiple
hardware platforms, a more general entry is
"~/[$PROMAX_HOME]/[$PROMAX_HOME]/port/bin/Machtype/exe
:."

which allows the return of the machine type (solaris, rs6000,


etc.) into the stanza so that you do not need to worry about
which machine you are working on; therefore, the correct
executable will be used.
Entry4 is the absolute or relative pathname to the directory
containing the menu files. If specified as a relative pathname, it
will be appended to $PROMAX_PORT_MENU_HOME. The
menus for each product are divided into subdirectories under
the main directory defined by $PROMAX_PORT_MENU_HOME.
For example, a default entry for the ProMAX 2D product would
be "promax", directing the flow builder to
$PROMAX_PORT_MENU_HOME/promax for menus. For your
development environment, the following entry may be
preferred:
"~/[$PROMAX_HOME]/port/menu/promax/:\
[$PROMAX_HOME]/port/menu/promax"

or
"~/[$PROMAX_HOME]/port/menu/promax/:promax"

This entry will cause a search of your menu directory for


custom menus and the system menu directory next.
Entry5 is the absolute or relative pathname to the Processes
file. The Processes list is different for each product; by default
the Processes file resides with the product menus. This entry
generally will be the same as the menus with /Processes
appended. A similar search mechanism outline for menus
(Entry4) can be employed except that the path must include the
Processes file name as this is a single file instead of a group of
menus or helps. For example:
"~/[$PROMAX_HOME]/port/menu/promax/Processes:\
promax/Processes"

Entry6 is the absolute or relative pathname to the directory


containing the help files. If specified as a relative pathname, it

Other Docs

Known Problems

Toggling Products: .promax80

Developers Programming Guide

will be appended to $PROMAX_PORT_HELP_HOME. The helps


for each product are divided into subdirectories under the main
directory defined by $PROMAX_PORT_HELP_HOME. For
example, a default entry for the ProMAX 2D product would be
"promax", directing the flow builder to
$PROMAX_PORT_HELP_HOME/promax for help files. For
your development environment, the following entry may be
preferred:
"~/[$PROMAX_HOME]/port/help/promax/:promax"

This entry will cause a search of your help directory for custom
helps and the system help directory next.
Entry7 is the absolute or relative pathname to the directory
containing the misc files. If specified as a relative pathname, it
will be appended to $PROMAX_PORT_MISC_HOME. As with the
executable directory, there is no product level subdivision of
misc files. The misc/ level files control configuration aspects
such as color tables and are rarely redirected. However, if
desired, search path control is done in the same manner as that
for the executables, Entry3, above.
Entry8 is the absolute or relative pathname to the directory
containing the primary data storage files. If specified as a
relative pathname, it will be appended to
$PROMAX_DATA_HOME. The data directory is also not divided
by products, nor is a search path supported in the .promax file.
The following examples demonstrate product stanzas in the
.promax file:
Standard:
(:product ("P" "ProMAX" "" "promax" "promax/Processes"\
"promax" "" "" t)
("v" "ProMAXVSP" "" "promaxvsp" "promaxvsp/Processes"\
"promaxvsp" "" "" t) )

Custom:
(:product ("P" "ProMAX" "/disk2/exe" "promax"\
"promax/Process" "promax" "" "" t)
("p" "Prospector" "" "prospector" "/home/joe/processes"\
"prospector" "" "/advance/mydata" t) )

Please refer to the ProMAX Reference Manual for further


discussion of the .promax file.

Other Docs

Known Problems

Adding a New Tool81

Developers Programming Guide

Adding a New Tool


In ProMAX, the menu file controls what parameters are
presented to the user. The help file provides textual/graphical
help during parameterization. The initialization routine checks
the input parameters for validity and generally tries to
accomplish any tasks that are performed on a one-time basis.
The execution routine performs the actual trace processing. The
include file provides communication between the initialization
routine and the execution routines, and facilitates re-entrancy.
Nine generic steps are required to add a new processing tool to
the system and see the results. In typical chronological order
they are:

Creating or copying a source file that contains an


initialization phase and an execution phase.

Creating or copying an include file (if using Fortran).

Creating a modified version of tools_to_add for new tools.

Compiling and linking the source code via Makeexec.

Creating or copying a new menu.

Adding an entry to the Processes file.

Restarting the flow builder.

Parameterizing a flow, including the new tool and the


Alternate Executive directive.

Executing the flow.

The following steps outline the process for adding a new tool,
using the amp_ratio tool as an example.
1.

Build a parallel directory tree within your home directory.


% cd (go to your $HOME directory)
% Makeadvance (builds entire Landmark directory tree
beneath $HOME)
% chmod -R a+rw ~/$PROMAX_HOME (give read/write
permissions to all files)

Other Docs

Known Problems

Adding a New Tool82

Developers Programming Guide

2.

Copy needed source code into directories.


% cd ~/$PROMAX_HOME/port/src/lib/maxtool
% mkdir amp_ratio (creates a subdirectory for
new 'amp_ratio' tool)
% cd amp_ratio
% cp $PROMAX_HOME/port/src/lib/maxtool\
/amp_ratio/amp_ratio1.f .
% cp $PROMAX_HOME/port/src/lib/maxtool/amp_ratio\
/amp_ratio1.inc .
% cd ~/$PROMAX_HOME/port/menu/promax
% cp $PROMAX_HOME/port/src/lib/maxtool/amp_ratio\
/amp_ratio1.menu .

3.

Add new tool to Makefile.


% cd ~/$PROMAX_HOME/port/src/lib/maxtool
% [edit] Makefile
newsrcs :=amp_ratio/amp_ratio1.f
(Path is relative to Makefile subdirectory)
[exit editor, saving Makefile]

4.

Update toolcall source (toolcall.f or toolcall.c).


% cd ~/$PROMAX_HOME/port/src/exe/exec
% more tools.db (Toolcall database. Just look,
dont touch.)
% [edit] tools_to_add
AMP_RATIO
same
simple
[save file]

5.

Create a new executable (exec.exe).


% cd ~/$PROMAX_HOME/port/src
% Makeexec (Builds toolcall.f. Compiles it)

or
% Makeexec language=C (Builds toolcall.c.\
Compiles it)
% cd ~/$PROMAX_HOME/rs6000/exe
% ls -l (File called exec.exe should now exist)

6.

Add the new tool to your Processes list. (Be sure to


configure your .promax file as shown earlier.)
% cd ~/$PROMAX_HOME/port/menu/promax
% cp $PROMAX_HOME/port/menu/promax/Processes .
% [edit] Processes
under "Amplitude" section add the entry:
("Amp ratio" "amp_ratio1")
[save file]

Other Docs

Known Problems

Adding a New Tool83

Developers Programming Guide

7.

Run the new tool within ProMAX.


% promax (start ProMAX User Interface)
Add Amp Ratio to a flow
Execute the flow
Minimize the ProMAX User Interface window.

8.

Iteratively make changes to the source code.


% [edit] ~/$PROMAX_HOME/port/src/lib/maxtool\
/amp_ratio/amp_ratio1.f
% Makeexec
[Try it out in ProMAX]

Other Docs

Known Problems

Making Your New Executable84

Developers Programming Guide

Making Your New Executable


After you add new functionality, you must be sure that you can
make the exec. The following AMP_RATIO example
demonstrates the steps to complete to accomplish this:
1.

Move to the tools subdirectory in your advance/ directory


tree:
% cd ~/$PROMAX_HOME/port/src/lib/maxtool
% mkdir amp_ratio
% cd amp_ratio
% cp $PROMAX_HOME/port/src/lib/maxtool/amp_ratio\
/amp_ratio1.f .
% cp $PROMAX_HOME/port/src/lib/maxtool/amp_ratio\
/amp_ratio1.inc .
% chmod +rw *

2.

Add an entry to your


~/$PROMAX_HOME/port/src/exe/exec/tools_to_add file
(this file is used to make
~/$PROMAX_HOME/port/src/exe/exec/toolcall.f or
toolcall.c, which contains the glue between the Executive
and the individual tools):
% [edit] ~/$PROMAX_HOME/port/src/exe/exec/\
tools_to_add

AMP_RATIO is a simple tool (see the Tool Types chapter).


Search for AGC and add a similar entry for AMP_RATIO
so that the file looks like this:
AMP_RATIO same simple

Note that the source code file name, amp_ratio1.f, and the
subroutine name, amp_ratio, may be different. Be sure the
name listed in the tools_to_add file truly reflects the name
of the init and exec phases.
3.

Add an entry to the tools Makefile:


% [edit] ~/$PROMAX_HOME/port/src/lib/maxtool/\
Makefile

Other Docs

Known Problems

Making Your New Executable85

Developers Programming Guide

Search for newsrcs and add another line listing the new
.f file so that the file looks like this (do not forget the
backslash continuation mark):
newsrcs := \
amp_ratio/amp_ratio1.f

4.

Remake the exec:


% Makeexec

(build and compile a toolcall.f)

or:
% Makeexec language=C(build

and compile a toolcall.c)

or, directly using gmake:


% cd ~/$PROMAX_HOME/port/src/exe/exec
% gmake [language=C](build and compile toolcall.f

or .c)

Step 4 should produce the file exec.exe in the directory


~/$PROMAX_HOME/[machtype]/exe/ where [machtype]
reflects the type of machine that you are working on (such as
sgimips4 or solaris).

The Details
The following things happened when you typed Makeexec:

Other Docs

1.

The Makeexec script cdd to your


~/$PROMAX_HOME/port/src/exe/exec directory and
spawned the Makefile there with the same arguments that
you gave Makeexec.

2.

~/$PROMAX_HOME/port/src/exe/exec/Makefile
included the master version of this Makefile to be executed.
This ensures that your local Makefile always reflects the
changes made to the master version
$PROMAX_HOME/port/src/exe/exec/Makefile.

3.

$PROMAX_HOME/port/src/exe/exec/Makefile decides
that this is a User make. It checks the following directories

Known Problems

Making Your New Executable86

Developers Programming Guide

for existence and whether or not a Makefile is present in


each of:

~/$PROMAX_HOME/port/src/lib/maxtool
~/$PROMAX_HOME/port/src/lib/maxutil
~/$PROMAX_HOME/port/src/lib/maxexec
~/$PROMAX_HOME/port/src/lib/uiutils
~/$PROMAX_HOME/port/src/lib/agfc

If a Makefile is present, the makefile ensures that the


library is up to date by cding to the directory and
spawning the Makefile with the same arguments that were
given to Makeexec.
If no Makefile is found, it is assumed that you will link
with the client or master version of the library.
4.

Other Docs

After ensuring/assuming that the libraries are up to date,


$PROMAX_HOME/port/src/exe/exec/Makefile respawns
itself so it can see if the exec.exe really needs to be remade.
Depending on the answer it will either report that the
exec.exe is up to date or re-link a new exec.exe in the
~/$PROMAX_HOME/[machtype]/exe/ directory.

Known Problems

Incorporating New Functionality87

Developers Programming Guide

Incorporating New Functionality


By following the preceeding steps, you successfully made a
new version of the exec and added new functionality. However,
you might be disappointed to find that the ProMAX Flow
Builder is still unaware of your achievement. We will return to
this example after a discussion about customizing ProMAX
menus.
In the Executive section of the System Overview chapter, we
discussed how each tool must have an initialization and
execution routine. A menu file must also exist if you hope to do
more than admire the new executable. Menu files are used to
specify what parameters should exist, what their properties are
(such as their type, default value, and description), and how
they interrelate. Without a menu file, the flow builder has no
idea how to capture and output the parameters that will make
your new processing tool operate.
The flow builder reads and interprets the menu files at runtime
(they are not compiled). However, before the flow builder can
know what menu files to read, it must read a list of available
menus in what is known as the Processes file. The Processes
file is product specific and is located in
$PROMAX_HOME/port/menu/[product]/. You will need a
custom copy of the Processes file in order to reference your new
tools without altering the production system and to avoid
interfering with other developers.

Other Docs

Known Problems

Creating Menus88

Developers Programming Guide

Creating Menus
The User Interface looks at the setting of the environment
variable new_menu to determine the menu init behavior. If
new_menu=t, then the User Interface will re-initialize the menu
every time it is displayed. If new_menu=f, then the flow builder
will only read files once. This means if you modify the
processes file or a menu file after starting the flow builder, it
will not see your changes. Furthermore, if you add a tool to a
flow, the corresponding menu file will be saved with the flow,
and the menu file will not be read again when the flow is
accessed again. Setting new_menu=t is a big help in testing
menus and should be part of the ProMAX programmers
environment. This setting slows down the User Interface
because the menu files are reread; therefore, it is not the default
setting for the typical production processing environment.
The menu file contains the description of parameters and rules
that control what the User Interface presents. Menu files are
written in Lisp and are interpreted at run time (no compilation is
necessary). No Lisp programming experience is necessary,
however. The syntax is simple and there are abundant examples
in the directory $PROMAX_HOME/port/menu (see files
ending with the extension .menu). In most cases, it is easiest to
find existing parameters in the system that are similar to those
that you wish to use, and then cut and paste them into a new file.
While you are creating the new menu file, it is a good idea to
use an editor that has parentheses checking, since mismatched
parentheses are the most common source of errors.
A utility program called promenu exists for debugging menu
files. After the menu file is near completion, use promenu to
adjust cosmetic features and to test the menu rules (if they exist
in your menu file). The program promenu takes the menu file as
a command line argument; therefore, if your menu file is named
testtool.menu, the command would be:
% $PROMAX_HOME/sys/bin/promenu testtool.menu

Each time you change the menu file, use File->Reread to


reflect any changes made to the menu file in the editor.

Other Docs

Known Problems

Adding a ProMAX Menu89

Developers Programming Guide

Adding a ProMAX Menu


To use a tool, such as the simple tool AMP_RATIO (see the
chapter entitled Tool Types), you must do two things: 1) make
the flow builder aware of the menu file, and 2) direct execution
to the new exec.exe that you made. You can accomplished this
with the following steps:
1.

Exit the flow builder if it is already running.

2.

Copy the production Processes file into your development


tree and make it writable. The commands will look similar
to this:
% cd
% cp $PROMAX_HOME/port/menu/promax/Processes\
~/$PROMAX_HOME/port/menu/promax/Processes
% chmod +w ~/$PROMAX_HOME/port/menu/promax/Processes

3.

Add an entry to your Processes file:


% [edit] ~/advance/port/menu/promax/Processes

Search for agc and add another line for AMP_RATIO :


(Automatic Gain Control agc)\
(Amplitude Ratio \
/home/joe/prog_course/src/amp_ratio/
amp_ratio ) \
(Time-Variant Scaling tvs)

Note that your entry is different; it includes the full path to


the menu file within your home directory. In the absence of
a full path, the flow builder assumes that the file resides in
the production menu directory. Also note that the .menu
extension of the file name is implied.
Alternatively, you can add your new menu without an
explicit path and use the search path facility in the .promax
file. For instance, you can direct the menu search to check
your personal menu directory first and the standard menu
directory next. In this case, the amp_ratio.menu file must
be copied to your menu directory.
4.

Other Docs

Redirect the flow builder to your custom version of the


Processes file. For future benefit, it is probably best to edit

Known Problems

Adding a ProMAX Menu90

Developers Programming Guide

the file ~/.promax and add a product stanza as discussed in


the Toggling Products section of this chapter.
5.

Restart the flow builder (that is, restart ProMAX).

6.

Create a new flow and add Disk Data Input, followed by


Amplitude Ratio and Screen Display. If Amplitude Ratio
does not show up at all in the list of tools, step 4 failed.
(Take a close look at your .promax file, and look at the file
$PROMAX_HOME/port/misc/misc_files/sys_ad/promax_dev.)

7.

Set the parameters for the individual steps in the flow. If


you are using the tutorial datasets, Raw shots with
geometry is a good input dataset. If you get an error
message when you attempt to parameterize Amplitude
Ratio, you have a typo in your Processes file. (Take a close
look at the path that you specified. Note that you cannot
use ~/prog_course/src/amp_ratio/amp_ratio as the path.)
The defaults for Amplitude Ratio and Screen Display
are fine.
You must also add a directive in your flow to alert the flow
builder to use your new exec.exe instead of the standard,
production version. This can be done by adding the tool
Alternate Executive anywhere in the flow.
Parameterization is simply entering an explicit path to
exec.exe, typically:
~/promax/1998.6/[rs6000,sgi,or...]/exe/exec.exe

Again, the best approach may be to direct the flow builder


to search your exe/ subdirectory first via the .promax file.
8.

Run the flow. You should see fairly dead-looking traces,


with a large peak where the first breaks once were.
AMP_RATIO transforms a trace by taking the ratio of the
amplitudes in two sliding gates (lower gate / upper gate).
When the lower gate is in the first break energy and the
upper gate is in the noise, the result is a large peak (this is
the beginning of a crude first break picker).

Please be sure to complete this exercise before moving on to be


certain that any and all idiosyncrasies in your release,
installation, and make environment are resolved.

Other Docs

Known Problems

Changing Files91

Developers Programming Guide

Changing Files
Several things must be done each time a new tool is added to the
ProMAX system. The following illustrations show files within
the ProMAX directory tree that need to be changed when a new
tool is added. The files that are changed frequently during the
development of a new tool are circled with a solid line; files that
are changed infrequently are circled with a dotted line. Other
files are shown, but if they are not circled you do not change
them. For example, the source code for an inline tool is found in
the directory path:
~/$PROMAX_HOME/port/src/lib/maxtool/your_tool
and the .c and/or .f files found in this directory are changed
frequently during development. The .promax file found in the
home directory is changed infrequently.
The first illustration shows files that need to be changed or
added when an inline tool (linked to the trace executive) is
added. The second illiustration shows files that must be changed
or added when a stand-alone or IPC (socket) tool is added to the
system. These charts have proven to be very useful when used
as a reminder of the file changes that are needed for a new tool.

Other Docs

Known Problems

Changing Files92

Developers Programming Guide

your advance directory


Makefile
. promax

lib

maxtool

exe

exec

your_tool

.c, .f

src
port

tools_to_add

menu

~/ $PROMAX_
HOME

promax
Processes
your_menu.menu

*.exe

exe
rs6000
lib

system libraries (libmaxtool*.a)

infrequently changed file


frequently changed file

Files to be changed for an inline tool

Other Docs

Known Problems

Changing Files93

Developers Programming Guide

. promax

exe

src

.c, .f

your_stand_alone

port
menu

~/ $PROMAX_
HOME

Makefile

promax
Processes
your_menu.menu

exe

* .exe

rs6000
lib

system libraries (libmaxutill*.a)

infrequently changed file


frequently changed file

Files to be changed for a stand-alone or IPC tool

Other Docs

Known Problems

Understanding the Makefile System94

Developers Programming Guide

Understanding the Makefile System


This section describes the Makefile system.

C++ Template Instantiation


One of the more difficult aspects of the Makefile system is C++
template instantiation due to the differences in the way it is
handled between the various platforms. Basically, there are two
different types of template instantiation among the platforms
Landmark currently supports.

Other Docs

Manual Template Instantiation - With the AIX xlC


compiler ProMAX employs manually instantiated
templates. That is, if you want the use of a template, you
must instantiate it yourself. This is pretty simple from the
Makefile perspective because the complexity is transferred
to the code, whose responsibility is to instantiate every
template it expects to use.

Automatic Template Instantiation - With Solaris and


IRIX C++ compilers, ProMAX uses automatic template
instantiation. While relieving programmer burden, this
complicates the Makefile. These systems work via a
template repository. This is the location of the instantiated
templates. These repositories are selected by the makefile
system. You can however, define these repositories
verbatim in your makefiles by setting the variable
CXXTEMPLATES to whatever repository or repositories
your application needs. For further information on how
templates are dealt with, read the entries on the various
variables associated with the use of C++.

Known Problems

Understanding the Makefile System95

Developers Programming Guide

Terms and Variable Descriptions


There are a number of variables of which the Makefile writer
should be aware. The following tables describe the general
terms and makefile conventions.
Terms
Term

Description

Canned Command
Sequence

A canned command sequence can be thought of as a predefined set of


commands. It is actually a recursively expanded variable which can span many
lines. As a result, automatic variables such as $@, $^ and so forth, expand to fit
the context in which they are used. For the sake of brevity, Canned Command
Sequences will be refered to as CCRs throughout this document.

Rule

A set of targets, dependencies and commands which describe how to create the
target(s). The make will look up and evaluate the rules for each of the
dependencies before evaluating the commands which the target(s) depend(s) on.
For a more detailed explanation of this, please refer to the GNU Make document
by Richard M. Stallman and Roland McGrath.
Example:
foo : bar1.o bar2.o
$(CC) $^ -o $@

Variable

A location in memory which contains information which may be used by rules,


CCSs or other variables. In general, the use of variables will increase the
porability of your makefiles. Variables may be set from the command line via
calls to the make utility. For example: gmake var1:=foo var2=var Refer to the
GNU Make document for further information.

Boolean Variable

A variable which may contain the string yes or no. It is used to figure out
exactly how the user wants certain things to be made.

Command Variable

A variable which contains a command. An example might be $(AR) which


might be /bin/ar on one platform and /usr/bin/ar on another. $(AR) can be thus
be used without regard to what platform the make is being run on.

Library Variable

A variable which contains the path to a library. The path may vary depending on
the context of the make.

Directory Variable

A variable which contains a path to a directory.

Makefile Variable

A variable which contains a path to a makefile.

CCS Rule Variable

A canned command sequence which assumes that it is called in a rule. As a


result, it may assume that certain automatic variable which are set in rules, are
set. (Ex: $@, $^, $(<D) etc...).
Example:
target : dependencies...
$(CCS_RULE_VARIABLE)

Other Docs

Known Problems

Understanding the Makefile System96

Developers Programming Guide

Terms (Continued)
Term

Description

CCS Function
Variable

A canned command sequence which returns a value. It may also assume that
certain values were set prior to calling the CCS Function Variable. These can be
thought of as the function arguments. For example:
function_results :=\ $(CCS_FUNCTION_VARIABLE)

Recursively
Expanded Variable

A variable which is assigned via =. Any variable references contained within it


are defined later. A recursively expanded variable can not be defined in terms of
itself.
Example: The Makefile
foo := foo
foobar = $(foo) $(bar)
bar := bar
all :
@echo FOOBAR: $(foobar)

Command Line Interaction:


% gmake
FOOBAR: foo bar

Simply Expanded
Variable

A variable whose assignment is performed at the time the assignment is found. It


can be defined in terms of itself.
Example: The Makefile:
foo := foo
foobar1 :=
bar := bar
foobar2 :=
all :
@echo
@echo

$(foo) $(bar)
$(foo) $(bar)
FOOBAR1: $(foobar1)
FOOBAR2: $(foobar2)

Command Line Interaction:


% gmake
FOOBAR1: foo
FOOBAR2: foo bar

Other Docs

Known Problems

Understanding the Makefile System97

Developers Programming Guide

Terms (Continued)
Term

Description

Command Line
Overridable Variable

Variables are by default, command line overridable. This means that when a
variable is set from the command line, it takes the command line value and
ignores the makefiles attempts to initialize or augment it. Unless stated
otherwise, it can be assumed that any given variable is command line
overridable.
Example: The Makefile:
# var is a simply expanded command line
# overwritable variable.
var := $(var) Makefile Value
all:
@echo VAR: $(var)

Command Line Interaction:


% gmake
VAR: Makefile Value
% gmake var=command line value
VAR: command line value

Command Line
Augmentable
Variable

A variable which will be augmented instead of overridden when set from the
command line.
Example:
# var is a simply expanded, command line
# augmentable variable.
override var := $(var) Makefile Value
all:
@echo VAR: $(var)

Command Line Interaction:


% gmake
VAR: Makefile Value
% gmake var=command line value
VAR: command line value Makefile Value

Conventions
The following list describes Makefile conventions.

Other Docs

1.

Solaris will stand for Solaris 2.6 (confusingly enough,


AKA SunOs 5.6) and higher.

2.

A statement such as (AIX, IRIX, Solaris) will mean that


this pertains only to AIX, IRIX and Solaris.

Known Problems

Understanding the Makefile System98

3.

A regular expression such as [A|B|]foo means Afoo, Bfoo,


or foo. The variable foo is assumed to be the base of Afoo
and Bfoo, or rather, Afoo and Bfoo inherit from foo. This is
explained in further detail below.

4.

When you see statements such as FOO->BAR, this means


that BAR inherits FOO. Or rather, BAR contains FOO.
Thus, anything which is set in FOO, will also be set in
BAR.

5.

Anytime you see something like (FOO1, FOO2)->BAR,


this will mean that BAR inherits from both FOO1 and
FOO2.

6.

Anytime you see something like FOO1->FOO2->BAR,


this will mean that BAR inherits from FOO2 and that
FOO2 inherits from FOO1. This construction is similar to
the statement (FOO1, FOO2) -> BAR with the difference
that we now know a little more about the hierarchy of the
variables in that we also know the relationship between
FOO1 and FOO2 as well. We may say that BAR directly
inherits from FOO2, FOO2 directly inherits from FOO1,
thus BAR indirectly inherits from FOO1.

7.

Variables whose names are prefixed with with either a, m


or nothing at all will be denoted with something like [a|m|].
These types of variables are paths to files and directories in
the Makefile system. For example, suppose we have a three
variables, representing three directories, afoodir, mfoodir
and foodir. Each variable is so similar in function that we
wished to document this as one variable. The variable
would appear as [a|m|]foodir. This should look familar to
those familiar with regular expressions. In addition, the
prefixes a and m have special signifigance. When
discussing variables of this nature, we will sometimes refer
to $path. For variables preceded with a, $path will be the
same value as the shell environmental variable
$PROMAX_HOME. For variables preceded with m,
$path will have the same value as $mtopdir. For variables
lacking the m or a prefix, $path will be either $mtopdir
or $utopdir, depending on the context of the make.

Other Docs

Developers Programming Guide

Variables preceded with an a signify that they are


Landmarks version of this variable. Since these types
of variables contain paths to directories or files, their
contents would represent Landmarks version of this

Known Problems

Understanding the Makefile System99

8.

Developers Programming Guide

directory or file. Clients of Landmark should not


concern themselves with these types of variables as
they are internal to Landmarks use of the Makefile
system.
Variables preceded with an m signify the master
version (or client version), of this variable. Their
contents would represent the master version of this
directory or file.
Variables not preceded with either an m or an a
are evaluated at the time the make is run. They are
interpreted by the context of the make. In a master
make context, the variable defaults to the master
version of the variable. In a user make context (that
is, when someone is performing a make in his home
directory), these variables default to the version of the
file or directory in the users home directory version
of the advance tree.

Variables whose names are prefixed with KRC, C, F, CXX,


or AMD or nothing will be denoted with something like
[KRC|C|F|CXX|AMD|Y|LEX|] prefixed before the
basename of the variable. The version of this variable
which does not have a prefix is said to be the base for all
the rest of the variables. The only exception to this rule are
the [a|m|] variables described previously in step 5. Thus,
given:
[KRC|C|F|CXX|AMD|Y|LEX]foo
we can assume:
foo -> (KRCfoo, Cfoo, Ffoo, CXXfoo, AMDfoo, Yfoo,
LEXfoo) or rather KRCfoo, Cfoo, Ffoo, CXXfoo,
AMDfoo, Yfoo, and LEXfoo all inherit from the base
variable foo.
In addition, the prefixes themselves having meaning.
Anything preceded with KRC will apply to the K&R C
compiler.

Other Docs

Known Problems

Understanding the Makefile System100

Developers Programming Guide

The following table describes each of the prefixes with


their meaning.
Variable Prefixes
Prefix

Meaning

KRC

These variables apply to K&R C preprocessing, compiling and linking


options.

These variables apply to ANSI C preprocessing, compiling and linking


options.

These variables apply to Fortran 77 preprocessing, compiling and linking


options.

CXX

These variables apply to C++ preprocessing, compiling, and linking options.

These variables apply to Yacc preprocessing and translation.

LEX

These variables apply to Lex preprocessing and translation.

AMD

These variables apply to the Amakedepend options. This is Landmarks


special version of the unix makedepend utility.
9.

The inheritance notation can be combined with the regular


expression notation to express several relationships more
efficiently. For example, a statement such as
[KRC|C|]foo -> [KRC|C|]bar can be used to express the
relationships KRCfoo -> KRCbar, Cfoo->Cbar, foo->bar.
Also note that there are a couple of implicit relationships:
bar->KRCbar, bar->Cbar, foo->KRCfoo, foo->Cfoo.
The following example illustrates a more subtle issue:
([KRC|]foo1, [KRC|C|]foo2) -> [KRC|C|]bar
This says:

(KRCfoo1, KRCfoo2) -> KRCbar


Cfoo2 -> Cbar (There is no Cfoo1)
(foo1, foo2) -> bar

We also know implicitly that:

Other Docs

a) foo1->KRCfoo1 (Cfoo1 does not exist)


b) foo2->(KRCfoo2, Cfoo2)
c) bar->(KRCbar, Cbar)

Known Problems

Understanding the Makefile System101

Developers Programming Guide

Variables
The following table describes the important makefile variables.
Makefile Variables
Variable

Type

Explanation

debug

Boolean Variable.

When set to yes, debug mode is


turned on.

profile

Boolean Variable.

When set to yes, profiling is


activated.

quantify

Boolean Variable.

When set to yes on a Solaris


machine, the code will also be
quantified. Quantify is a fancy
profiler available from Pure
Software.

purify

Boolean Variable.

When set to yes on a Solaris


machine, the code will be purified.
Purify is another product from
Pure Software, designed to detect
memory leaks.

[KRC|C|CXX|F|AMD|] INCPATH

Variables.

These variables hold the include


path(s) for [KRC|C|CXX|F|AMD|]
preprocessing. Note we are using
the regular expression format.

[KRC|C|CXX|F|] DEFINES

Variables.

These variables hold the defines for


[KRC|C|CXX|F|] preprocessing.

[KRC|C|CXX|F|AMD|] PPFLAGS

Variables.

These variables hold the


preprocessor flags for
[KRC|C|CXX|F|AMD|]
preprocessing.

[KRC|C|CXX|F|]
OPTIONS

Variables.

These variables are used to hold


options given to the
[KRC|C|CXX|F|AMD|] programs.

[KRC|C|CXX|F|]
OPTIMIZATION

Variables.

These variables are used to hold


the optimization options given to
the [KRC|C|CXX|F|] compilers. It
can be argued that this should be
part of the OPTIONS variable but
was split apart for the convenience
of efficiency minded developers.

Other Docs

Known Problems

Understanding the Makefile System102

Developers Programming Guide

Makefile Variables (Continued)


Variable

Type

Explanation

[KRC|C|CXX|F|AMD|Y|]FLAGS

Variables.

These variables are used to hold


flags given to the
[KRC|C|CXX|F|AMD|Y|]
programs.
([KRC|C|CXX|F|AMD|]\
OPTIONS,
[KRC|C|CXX|F|AMD|]\
OPTIMIZATION) ->
[KRC|C|CXX|F|AMD|]FLAGS

[KRC|C|CXX|F|]
LDFLAGS

Variables.

These variables are used to hold


any flags passed down to the
[KRC|C|CXX|F|] link phase, such
as directories to search for
libraries.

[KRC|C|CXX|F|]LIBS

Variables.

These variables hold a list of


libraries, specific to the compiler
being used, which are to be linked
when doing a [KRC|C|CXX|F|]
link.

[KRC|C|CXX|F|]
PRECOMPILE

Variables.

These are prepended to a


[KRC|C|CXX|F] compilation.
Purify and quantify take advantage
of these variables.

KRCC

Command Variable.

The command which invokes the


K&R C compiler.

CC

Command Variable.

The command which invokes the


ANSI C Compiler.

CXX

Command Variable.

The command which invokes the


C++ compiler.

FC

Command Variable.

The command which invokes the


Fortran 77 compiler.

CPP

Command Variable.

The command which invokes the C


Preprocessor. This is also used by
the other compilers, with the
exception of the fortran compiler.

FPP

Command Variable.

The comand which invokes the


Fortran Preprocessor.

SYSLIBS

Command Line
Augmentable Variable.

A list of system libraries to be used


to link executables (with the
exception of C++ executables).

SYSXXLIBS

Command Line
Augmentable Variable.

A list of system libraries to be used


to link C++ executables.

Other Docs

Known Problems

Understanding the Makefile System103

Developers Programming Guide

Makefile Variables (Continued)


Variable

Type

Explanation

XLIBS

Variable.

A list of X11 libraries with which


to link.

XMLIBS

Variable.

A list of Motif and X11 libraries


with which to link.

cxxlink

Boolean Variable.

When this is set to yes, it indicates


that a C++ executable is being
created. As a result, certain things
are set to their C++ defaults instead
of their C defaults.

shared_libs

Boolean Variable.

A boolean yes/no value. When


shared_libs is set to yes, libraries
and executables created will be
shared.

lib_suf

Variable.

lib_suf contains the library suffix.


It is usually .a.

master

Boolean Variable.

A boolean yes/no value which


indicates whether or not a master
make is occurring.

GET

Command Variable.

The command which performs an


SCCS get on a file or files.

ctopdir

Directory Variable.

The clients top directory.

utopdir

Directory Variable.

The users top directory, usually


$HOME/$PROMAX_HOME.

atopdir

Directory Variable.

Landmarks top directory. atopdir


should be the same as the
$PROMAX_HOME
environmental variable.

topdir

Directory Variable.

The effective top directory. In a


master make context, it will be the
same as mtopdir; in a user make
context, it will be utopdir; in an
advance master make context, it
will be atopdir. For Landmark,
mtopdir is the same as atopdir, a
fact which causes a small amount
of terminology confusion when
dealing with clients.

loadmap

Boolean Variable.

A boolean yes/no value which


determines whether or not a
loadmap is generated; traces which
function came from which library.

Other Docs

Known Problems

Understanding the Makefile System104

Developers Programming Guide

Makefile Variables (Continued)


Variable

Type

Explanation

mtopdir

Directory Variable.

This is the master top directory. It


is the same as ctopdir for clients.
For Landmark, it is the same as
atopdir (Landmark is its own
client).

AR

Command Variable.

The ar or library archiver


command.

ARCHIVE_REPLACE_FLAGS

Command Flags
Variable.

A variable containing the flags to


be given to AR when an archive
replace is to be done.

ARCHIVE_CREATE_FLAGS

Command Flags
Variable.

A variable containing the flags to


be given to AR when a library
archive is to be created.

AS

Command Variable.

The as command, AKA the


assembler.

RANLIB

Command Variable.

The ranlib command. On machines


without the ranlib command, it
replaces ranlib with touch.

RANLIB_TARGET

CCS Rule Variable.

A CCS which ranlibs the library


described in the target section of a
make dependency.

CXXTEMPLATES

Variable (SunOs,
Solaris, IRIX).

A variable which may contain a list


of template repositories. If
CXXTEMPLATES is set, the
makefile will not attempt to set the
repositories. Instead, it will rely on
the users definition of
CXXTEMPLATES.

Other Docs

Known Problems

Understanding the Makefile System105

Developers Programming Guide

Makefile Variables (Continued)


Variable

Type

Explanation

CXX_LINK

Command Variable.

A command which will C++ link


an executable. How this variable is
handle depends on whether the
compiler performs automatic
template instantiation.
Manual Template Instantiating
Compilers:
On platforms which require
manual instantiation of templates,
this command is simply a call to
the C++ compiler with
CXXLDFLAGS thrown in.
CXX_LINK -> (CXX,
CXXLDFLAGS)

Automatic Template Instantiating


Compilers
On auto instantiating machines, the
makefile system will use
CXXTEMPLATES to set the
template directory or directories. If
CXXTEMPLATES is not set, it
will attempt to determine what the
template repositories should be.
These repositories are determined
via the algorithm:
1. Get the list of object
dependencies.
2. Create a list, uobjlist, which
contains a list of all objects in the
dependency list whose base path
points to the users directory
utopdir.
3. Create a list, mobjlist, which
contains a list of all objects in the
dependency list whose base path
points to the master directory
mtopdir.
4. Create a list, aobjlist, which
contains a list of all objects in the
dependency list whose base path
points to the advance directory
atopdir.
(continued)

Other Docs

Known Problems

Understanding the Makefile System106

Developers Programming Guide

Makefile Variables (Continued)


Variable

Type

CXX_LINK (continued)

Explanation
(continued)
5. If uobjlist contains one or more
files, take the first object file and
replace the filename.o portion with
templates and prepend -ptr to the
string. Add this to the tail end of
our CXX_LINK canned command
sequence. Repeat this step with
mobjlist and aobjlist (in that order).
Thus, user directories get first
crack and being the read/write
template repository, then master
directories and advance directories
get last crack. Also note that if you
have object files coming from more
than one location in your user
directory, the object file listed first
in the dependency list will be the
one whose path is inherited by the
repository.
Thus, in cases such as this, list
object files which reside in the
location where you want the
template repository first.
CXX_LINK -> (CXX,
CXXPPFLAGS, CXXTEMPLATES
CXXLDFLAGS)

INSTANTIATE_CXX_TEMPLATES

Other Docs

CCS Rule Variable


(SunOs, Solaris, IRIX).

A CCS, valid on automatic


template instantiating platforms,
which ensures that all templates
are instantiated. Basically, it
attempts to link an executable with
the library being used. In the
process of attempting to create this
executable (which fails due to lack
of a main), the templates are
instantiated.

Known Problems

Understanding the Makefile System107

Developers Programming Guide

Makefile Variables (Continued)


Variable

Type

Explanation

COPY_CXX_TEMPLATES

CCS Rule Variable.

A CCS which you should not have


to worry about. This is called from
with the make to copy all
instantiated templates into a
temporary repository which
ARCHIVE_CXX_LIB[NS]
recognize and archive into their
respective libraries. This command
works differently depending on the
context of the make.
Master Context:
In a master context, a temporary
directory is created. Then, the
read/write template directorys
object files are copied into this
temporary directory and renamed
to Template1.o Template2.o and so
forth. When the
ARCHIVE_CXX_LIB[NS] CCSs
are called, they will ensure that
these template instantiations are
archived into the library currently
being built.
User Context
In a user context, a temporary
directory is created. Then a list of
template instantiation object files
are created based on the users
read/write template repository, the
master template repository, and
advance template repository.
Duplicate names are thrown out
and the result is saved to a new list
named files.
COPY_CXX_TEMPLATES then
loops over each entry of this list
and prepends a user, master, or
advance path to this base filename.
The user path will be prepended if
the user templates directory
contains this object file.
(continued)

Other Docs

Known Problems

Understanding the Makefile System108

Developers Programming Guide

Makefile Variables (Continued)


Variable

Type

COPY_CXX_TEMPLATES
(continued)

Explanation
(continued) If it does not, the
master template directory is
scanned for it. If the master
contains this template object file,
the master template repository path
is prepended to the base object
filename. Otherwise, the advance
template repository path is
prepended to the base template
object file. Thus we ensure that we
have a singular list of template
object files in which the users
directory overrides the master,
which in turn overrides the
advance definitions. At this point,
the object files are copied into the
temporary template directory
under the names Template1.o
Template2.o etc... and are archived
into the users personal library as
described in the master context.

ARCHIVE_CXX_LIB

CCS Rule Variable.

A CCS which will archive a shared


version of a C++ library. On
automatic template instantiating
platforms, the template
instantiations created via
INSTANTIATE_CXX_\
TEMPLATES and
COPY_CXX_TEMPLATES will
also be archived into the shared
library.

ARCHIVE_CXX_LIBNS

CCS Rule Variable.

A CCS which will archive a


nonshared version of a C++ library.
On automatic template
instantiating platforms, the
template instantiations created via
INSTANTIATE_CXX_\
TEMPLATES and
COPY_CXX_TEMPLATES will
also be archived into the nonshared
library.

machtype

Variable.

A string identifying the current


platform.

[a|m|]sysdir

Directory Variable.
$path/sys.

The top level of where the system


dependent files are kept.

Other Docs

Known Problems

Understanding the Makefile System109

Developers Programming Guide

Makefile Variables (Continued)


Variable

Type

Explanation

[a|m|]bindir

Directory Variable.
$path/sys/bin/.

The directory where the system


dependent command line
executables are kept.

[a|m|]aexedir

Directory Variable.
$path/sys/exe/.

The directory where the system


dependent executables are located.
These executables are generally
invoked via the
ProMAX/VSP/ProMAX3D\
/Prospector user interfaces.

[a|m|]libdir

Directory Variable.
$path/sys/lib/.

The directory where the system


dependent libraries are kept.

[a|m|]objdir

Directory Variable.
$path/sys/obj/.

The top level directory where the


object files are located.

[a|m|]objbindir

Directory Variable.
$path/sys/obj/bin/.

The directory where the object files


for the system dependent
executables are located.
Executables in this directory are
generally invoked via the
command line, interactively by the
user.

[a|m|]objexedir

Directory Variable.
$path/sys/obj/exe/.

The directory where the system


dependent object files (which
correspond to the executables in
[a|m|]exedir) are located.

[a|m|]objuidir

Directory Variable.
$path/sys/obj/ui/.

The directory where the object files


corresponding to the for user
interface are located.

[a|m|]objlibdir

Directory Variable.
$path/sys/obj/lib/.

The directory where the object files


corresponding to the various
libraries are located.

[a|m|]portdir

Directory Variable.
$path/port/.

The top level directory of the port


hierarchy. Files under here are
considered to be portable.

[a|m|]incdir

Directory Variable.
$path/port/include/.

The top level directory where the


include files are stored.

[a|m|]srcdir

Directory Variable.
$path/port/src/.

The top level directory for all the


portable source code.

[a|m|]srcbindir

Directory Variable.
$path/port/src/bin/.

The directory where the portable


source code corresponding to the
executables in [a|m|]bindir are
located.

Other Docs

Known Problems

Understanding the Makefile System110

Developers Programming Guide

Makefile Variables (Continued)


Variable

Type

Explanation

[a|m|]srcexedir

Directory Variable.
$path/port/src/exe/.

The directory where the portable


source code corresponding to the
executables in [a|m|]exedir are
located.

[a|m|]srclibdir

Directory Variable.
$path/port/src/lib/.

The directory where the portable


source code corresponding to the
libraries in [a|m|]libdir are located.

libmaxexec

Library Variable. $path\


/sys/lib/libmaxexec.a.

The library containing executive


($path/sys/exe/exec.exe) support
functions.

libmaxtool1

Library Variable. $path\


/sys/lib/libmaxtool1.a.

The library containing some of the


modules composing the executive.

libmaxtool2

Library Variable. $path\


/sys/lib/libmaxtool2.a.

The library containing some more


of the modules composing the
executive.

libmaxtool3

Library Variable. $path\


/sys/lib/libmaxtool3.a.

The library containing the rest of


the modules composing the
executive.

libmaxutil

Library Variable. $path\


/sys/lib/libmaxutil.a.

The library containing general


support routines.

libuiutils

Library Variable. $path\


/sys/lib/lib/libuiutils.a.

The library containing general


support routines used by the user
interface.

libmaxui

Libary Variable. $path\


/sys/lib/lib/libmaxui.a.

The library containing more


general support routines used by
the user interface.

libagfc

Library Variable. $path\


/sys/lib/libagfc.a.

The library containing the old cwp


routines used by the various
modules in the system.

libpar

Library Variable. $path\


/sys/lib/libpar.a.

A library providing a mechanism


for decoding command line
arguments.

libagX

Library Variable. $path\


/sys/lib/libagX.a.

A library contains C++ graphics


objects for OOP graphics design.

libagXi

Library Variable. $path\


/sys/lib/libagXi.a.

A library containing classes and


functions which are not quite ready
to be in libagX yet. libagXi is
internal to Landmark (denoted via
the suffix i).

Other Docs

Known Problems

Understanding the Makefile System111

Developers Programming Guide

Makefile Variables (Continued)


Variable

Type

Explanation

libagC

Library Variable. $path\


/sys/lib/libagC.a.

A library containing base template


as well as other objects used by the
agX graphics library.

libagCi

Library Variable.
$path/sys/lib/libagCi.a.

A library containing routines and


classes which are not quite ready to
be placed in libagC.

libeispack

Library Variable. $path\


/sys/lib/libeispack.a.

A library containing Landmarks


version of Lynn Kirlins eispack
library for K-L Transforms.

libGeom

Library Variable. $path\


/sys/lib/libGeom.a.

A library containing geometry


database routines.

libpagefile

Library Variable. $path\


/sys/lib/libpagefile.a.

A library containing the file


manipulation and access routines
used by the database.

libgeoquest

Library Variable. $path\


/sys/lib/libgeoquest.a.

A library containing Geoquest


routines used to interface with IES
on SunOS 4.1.x platforms.

libpvm

Library Variable. $path\


/sys/lib/libpvm.a.

A library containing Parallel


Virtual Machine routines used to
run certain jobs in parallel.

libXpm

Library Variable.

The color pixmap support library.

libpsplot

Library Variable.

The postscript plotting library.

libpp

Library Variable.

The library for creating a promax


path variable.

AGCLIBS

Collection of Libraries.

A list of advance libraries normally


linked with standalone
executables. AGCLIBS is a
convenience to Makefile writers.

MAXTOOLLIBS

Collection of libraries.

A list of maxtool libraries.


MAXTOOLLIBS is a convenience
to makefile writers.

libmaxtoolmake

Makefile Variable.

The location of the maxtool library


makefile.

libmaxutilmake

Makefile Variable.

The location of the maxutil library


makefile.

libmaxexecmake

Makefile Variable.

The location of the maxexec


library makefile.

libuiutilsmake

Makefile Variable.

The location of the uiutils library


makefile.

Other Docs

Known Problems

Understanding the Makefile System112

Developers Programming Guide

Makefile Variables (Continued)


Variable

Type

Explanation

libmaxuimake

Makefile Variable.

The location of the maxui library


makefile.

libagfcmake

Makefile Variable.

The location of the agfc library


makefile.

libagXmake

Makefile Variable.

The location of the agX graphics


library makefile.

libagXimake

Makefile Variable.

The location of the agXi library


makefile.

libagCmake

Makefile Variable.

The location of the agC library


makefile.

libeipackmake

Makefile Variable.

The location of the eispack library


makefile.

libGeommake

Makefile Variable.

The location of the Geom library


makefile.

libpagefilemake

Makefile Variable.

The location of the pagefile library


makefile.

libpvmmake

Makefile Variable.

The location of the pvm library


makefile.

libXpmmake

Makefile Variable.

The location of the Xpm library


makefile.

libpsplotmake

Makefile Variable.

The location of the psplot library


makefile.

libppmake

Makefile Variable.

The location of the pp library


makefile.

report

Boolean Variable.

A boolean yes/no value which


determines whether to report errors
in the make to a log file.

BACKUP

CCS Variable.

A routine which will backup the


target to a .bak file. This is
intended for use with
BACKUP_ON_ERROR.

BACKUP_ON_ERROR

CCS Rule Variable.

A routine which handles errors by


moving the backup back into the
original file (depends on BACKUP
and ERROR_HANDLER).

ERROR_HANDLER

CCS Rule Variable.

A routine which handles errors in


the make. Depending on how
report is set, it will log errors to a
file or simply report errors to the
screen.

Other Docs

Known Problems

Understanding the Makefile System113

Developers Programming Guide

Makefile Variables (Continued)


Variable

Type

Explanation

define_usrcs

CCS Function Variable.

A routine which will figure out


what the user source code actually
is. For a master make, it will be the
same value as $(srcs). For a user
make, it will look at $(srcs) and
then figure out which of those files
the user has and return that subset.
(Assumes that the user has set a
string srcs to contain a list of all
source code comprising the
executable or library.)

define_asrcs

CCS Function Variable.

A routine which will figure out


what the actual source code is. It
takes $(srcs) and replaces each file
in the $(srcs) list with the user
version, master version, or advance
version. If the user does not have
one of the files in his home
directory, the master directory is
scanned; if it does not exist there,
the advance version of the filename
is returned. For example, suppose
srcs = a.c b.f c.C and that a.c exists
in the master, advance and user
directory. Also suppose that b.f
exists in the master and advance
directories while c.C exists only in
the advance directory. A call
$(define_asrcs) will yield a string
$(path1)/a.c $(path2)/b.f
$(path3)/c.C where a.c points to
the users version, b.f to the master
version and c.C to the Landmark
version. (Assumes that the user has
set a string srcs to contain a list of
all source code comprising the
executable or library.)

define_uobjs

CCS Function Variable.

A routine, similar to the


define_usrcs routine, except that it
translates the directory to the
corresponding obj directory and
replaces the .c, .f or .C with .o.
(Assumes that the user has set a
string srcs to contain a list of all
source code comprising the
executable or library.)

Other Docs

Known Problems

Understanding the Makefile System114

Developers Programming Guide

Makefile Variables (Continued)


Variable

Type

Explanation

define_aobjs

CCS Function Variable.

A routine, similar to the


define_asrcs routine, except that it
translates the directory to the
corresponding obj directory and
replaces .c, .f, or .C with .o.
(Assumes that the user has set a
string srcs to contain a list of all
source code comprising the
executable or library.)

AMAKEDEPEND

CCS Rule Variable.

A CCS which will figure out what


the header file dependencies are
and output them to a file defined by
$(depend_include). It is include
file path is defined by
AMDPPFLAGS and the options
given to it can be augmented via
setting AMDFLAGS.

AMAKEDEPEND_TO_STDOUT

CCS Rule Variable.

A rule, similar to the


AMAKEDEPEND rule, except
that the output is sent to standard
output. This is useful when you
have multiple targets but want to
append the depedency output to a
single file.

ANSIC_COMPILE

CCS Rule Variable.

A CCS which takes an ANSI C


source file in the dependency and
compiles it into an object file using
the ANSI C compiler defined in the
variable CC. It applies CPPFLAGS
as well as CFLAGS in the
compilation. If an error occurs,
ERROR_HANDLER is invoked.

KRC_COMPILE

CCS Rule Variable.

A CCS which takes a K&R C


source file in the dependency and
compiles it into an object file using
the K&R C compiler defined in the
variable KRCC. It applies
KRCPPFLAGS as well as
KRCFLAGS in the compilation. If
an error occurs,
ERROR_HANDLER is invoked.

define_ugincs

Other Docs

Known Problems

Understanding the Makefile System115

Developers Programming Guide

Makefile Variables (Continued)


Variable

Type

Explanation

CXX_LINK

Command Variable.

This is a variable which invokes


the C++ compiler with
CXXLDFLAGS and
CXXPPFLAGS if your compiler
needs include paths in the link
phase as well. For compilers with
automatic template instantiation, it
will also set a template directory
corresponding to what is being
linked.

CXX_COMPILE

CCS Rule Variable.

A CCS which takes a C++ source


file in the dependency and
compiles it into an object file using
the C++ compiler defined in the
variable CXX. It applies
CXXPPFLAGS as well as
CXXFLAGS in the compilation. If
an error occurs,
ERROR_HANDLER is invoked.

F_COMPILE

CCS Rule Variable.

A rule which takes a Fortran 77


source file in the dependency and
compiles it into an object file using
the Fortran 77 compiler defined in
the variable FC. First, it
preprocesses the file into a *PP.f
file and then it compiles the PP.f
file. It applies FPPFLAGS, as well
as FFLAGS in the compilation. If
an error occurs,
ERROR_HANDLER is invoked.

YACC_COMPILE

CCS Rule Variable.

A CCS which takes a yacc source


file in the dependency and
translates it into C code, perhaps
with a header file yy.tab.h.
YACC_COMPILE applies
YFLAGS when yacc is applied. If
an error occurs,
ERROR_HANDLER is invoked.

LEX_COMPILE

CCS Rule Variable.

A CCS which takes a lex source


file in the dependency and
translates it into C code. If an error
occurs, ERROR_HANDLER is
invoked.

Other Docs

Known Problems

Understanding the Makefile System116

Developers Programming Guide

Makefile Variables (Continued)


Variable

Type

Explanation

AS_COMPILE

CCS Rule Variable.

A CCS which takes assembler


code and assembles it into an
object file. If an error occurs,
ERROR_HANDLER is invoked.

COPYFILE

CCS Rule Variable.

A CCS which takes a destination


file in the target and a source file in
the dependency. It then copies the
source file to the destination.

LINKFILE

CCS Rule Variable.

A CCS which takes a destination


link in the target and a source file
in the dependency. It then links the
destination link to the source file.

COPYLIB

CCS Rule Variable.

A CCS which takes a destination


library in the target and a source
library in the dependency. It then
copies the source library to the
destination library and ranlibs it.

ARCHIVE_REPLACE

CCS Rule Variable.

A CCS which takes a destination


library name in the target and a list
of object files in the dependency
list. It then performs an archive
replace of all the object files within
the target library. It then ranlibs the
library to update the SYMDEF
table. It applies the variable
ARCHIVE_REPLACE_FLAGS
when archive replacing.

ARCHIVE_CREATE

CCS Rule Variable.

A CCS which takes a destination


library name in the target and a list
of object files in the dependency
list. It first removes the old version
of the library, if it exists. It then
performs an archive create and
creates the target library. It them
ranlibs the library. It applies the
variable
ARCHIVE_CREATE_FLAGS
when archive creating.

MAKETARGETDIR

CCS Rule Variable.

A CCS which ensures that the


destination directory of the target
is present. If it is not present, then
MAKETARGETDIR will create
the directory.

Other Docs

Known Problems

Understanding the Makefile System117

Developers Programming Guide

Makefile Variables (Continued)


Variable

Type

Explanation

UPDATE_[libname]

CCS Rule Variables.

These CCSs correspond to the


UPDATELIB[libname] rules. The
difference is that
UPDATE_[libname] rules are used
by other routines
(UPDATE_LIBRARIES) to
automatically generate updated
libraries. The only difference from
their UPDATELIB[libname]
counterparts is the name. The
UPDATELIB[libname] macros are
in the process of being phased out.

UPDATE_LIBRARIES

CCS Rule Variable.

This is a macro which will update a


series of libraries (assumed to be
defined in libs).

cleanlib

Rule.

This rule will clean the library in


the corresponding library directory.

cleanexe

Rule.

This rule will clean the


executable(s) in the corresponding
executable directory.

cleanobjs

Rule.

This rule will clean the object files


in the corresponding object
directory.

Makefile Techniques
The following tips illustrate how the makefile system can be
used to solve common problems.

Creating the executable in a non-standard place


Sometimes you may wish to link the target executable in a
nonstandard place such as your current directory. This is useful
if you wish to debug an executable in your current directory
instead of supplying the somewhat cumbersome pathnames
common to the advance tree. To do this, simply supply the
variable exe which contains the path to the target executable
name.
gmake exe=./myexe

Other Docs

Known Problems

Understanding the Makefile System118

Developers Programming Guide

Compile without updating libraries


For a faster compile/link, you may supply the ul=no option.
This option tells the make to assume that the libraries you are
linking with are up to date, foregoing the time consuming
time/date stamp check for each library. Do not use this option if
you are concerned that the libraries in question are in fact not up
to date.
gmake ul=no

Creating an exec.exe which does not contain the


C++ extensions
Linking via the C++ compiler is slower than using the C
compiler due to the complexity that goes into linking in C++. If
you do not need any of the C++ functionality in your
executives, you may use the clink:=yes option in conjunction
with the utc rule to create an executable which does not
contain any of the C++ stuff. The first time you create your C++
executive, you must supply the utc rule. The utc rule tells the
makefile to Update The Toolcall. A new toolcall is created
which does not contain any of the C++ functionality. Having
updated the toolcall, successive makes need only give the
clink:=yes option. When switching back to a C++ based
executive, you must again provide the utc rule to update the
toolcall to once again provide the C++ functionality.
gmake clink:=yes utc

This will cause the C only toolcall to be created and link via the
C compiler.
gmake clink:=yes

This is how you can make from here on out. The utc is
necessary the first time only.
gmake utc

This is how you switch back to a C++ based executive.

Adding a library to the link without changing the Makefile


You may wish to add a library to the link without changing the
link line in the Makefile. To do this, you may supply the
SYSLIBS in the case of C linkage or SYSXXLIBS in the case

Other Docs

Known Problems

Understanding the Makefile System119

Developers Programming Guide

of C++ linkage. SYSLIBS and SYSXXLIBS enter the library in


question after the advance and X11 libraries and before the
system libraries. If you need the libraries to be inserted in a
different location, you will probably want to go into the
Makefile and edit the link. If not, XLIBS, CLIBS, CXXLIBS
and libs are also available.
gmake SYSLIBS:=libfoo.a
gmake SYSXXLIBS:=libC++foo.a

Debugging a make failure


Figuring out why your make is failing can be a painful
experience. These suggestions may help you debug your make
problems a bit faster.
gmake [options] -n >& file

This causes your make to output what it would have done to the
file file. You can now edit this file, adding and deleting
options to help figure out just why your make is failing.
Edit the compile/linking options to include the -v option
for verbosity.

This option may be -show in the latest SGI compilers. This will
cause the compiler/linker to go verbose helping you isolate
exactly which phase is going wrong.
You can add print statements to your makefile by doing
something like this:
foo := $(shell echo>&2 My Variable = $(My_Var))

Debugging a failed link


A failure to link is one of the most common make failures. To
assist in figuring just why your link is failing, Landmark has
provided the Nmgrep utility. The Nmgrep tool is a fairly
comprehensive library analysis tool; you should not have to
worry about all its bells and whistles. Perl 5.0 must be installed
for this tool to function properly. A few example usages of this
tool follows. To get a comprehensive help listing on this tool,
type Nmgrep -h
To show DEFs and REFs in $PROMAX_HOME/sys/lib:

Other Docs

Known Problems

Understanding the Makefile System120

Developers Programming Guide

Nmgrep

To show where any routines with trace in the name are


defined/referenced in $PROMAX_HOME/sys/lib.
Nmgrep trace

Using another compiler for this make only


You may wish to substitute the compiler temporarily for some
reason or another. CC, KRCC, CXX and FC correspond to the
default Ansi C, K&R C, C++ and Fortran compilers
respectively. Simply supply a definition for these to override the
default.
gmake CC=/usr/bin/cc
gmake CC=/usr/bin/cc CXX:=/usr/bin/CC

Other Docs

Known Problems

121

Developers Programming Guide

Directory Structure

This chapter describes the organization of the ProMAX


directories and files.

Topics covered in this chapter:

Other Docs

Directory Hierarchy
Machine-dependent Directories
Directory Naming Conventions
Product-dependent Subdirectories
Third-party Software
Recompilation - GNU Make
Makefile Rules
Makefile Options
User and Master Versions
Master Versions for Clients

Known Problems

Directory Hierarchy122

Developers Programming Guide

Directory Hierarchy
Everything we need to build our products, except for standard,
vendor-supplied software such as ANSI C include files, goes
under the single directory $PROMAX_HOME. For example, if
we need the latest X11R4 (or X11R5, ...) include files, and these
files are not supplied with all machine types we support, then
we put them in $PROMAX_HOME/port/include/X11/, instead
of /usr/local/include/X11/. Having everything under a single
directory makes it easier to find things during development and
maintenance, to build distribution tapes, and to save/recover
new/old releases of the software.
The next level of the hierarchy contains several directories
named after machine types, such as rs6000/. These directories
contain machine-dependent object code, libraries, and
executable programs. Software that does not depend on
machine type goes in port/. port/ contains everything necessary
to port our software to a new machine type.
The etc/ directory contains configuration files (such as the
ProMAX config_file) that may vary from machine to machine,
even when the machines are of the same type. Many sites will
also put their ProMAX data/ and scratch/ directories just
beneath $PROMAX_HOME, although these locations may
vary.
A listing of some of the more important, higher level directories
of theProMAX hierarchy follows. You may also refer to the
Expanded Directory Structure appendix.
$PROMAX_HOME

Other Docs

rs6000/ (sys/ -> rs6000/ on IBM RS/6000 machines)

bin/

exe/

lib/

obj/

bin/

Known Problems

Directory Hierarchy123

Developers Programming Guide

exe/

lib/

nodist/

lib/

.
decmips/ (sys/ -> decmips/ on DEC MIPS Rx000
machines)

Other Docs

rs6000/ (sys/ -> rs6000/ on IBM rs6000 machines)

sgimips/ (sys/ -> sgimips/ on SGI MIPS Rx000 machines)

sparc/ (sys/ -> sparc/ on SUN SPARC machines)

port/

bin/

misc/

menu/

promax/

prospector/

promaxvsp/

promax3d/

help/

promax/

prospector/

promaxvsp/

promax3d/

man/

Known Problems

Directory Hierarchy124

Other Docs

Developers Programming Guide

include/

src/

bin/

exe/

lib/

nodist/

etc/

data/

scratch/

include/

Known Problems

Machine-dependent Directories125

Developers Programming Guide

Machine-dependent Directories
Machine-dependent directories, such as rs6000/ (for IBMs
RS/6000) and decmips/ (for DECs MIPS-based machines) are
used for two reasons:
1.

They make it easy for programmers working in their own


version of the $PROMAX_HOME hierarchy to build and
test code on all platforms. The Makefile will put machinedependent files in the appropriate machine-dependent
subdirectories of a programmers home directory. The
Makefile rules determine machine type automatically, so
programmers rarely have to specify machine-dependent
directory names.

2.

They provide a standard way for groups with a single large


file server to support multiple platforms. To provide a
uniform look across different machines, system
administrators might do the following:
mount igor:/promax/1998.6/rs6000/ /promax/1998.6sys/
mount igor:/promax/1998.6/port/ /promax/1998.6/port/
on IBM RS/6000s that are NFS clients of a file server igor.
If igor is a SUN SPARCstation, then a symbolic link from
/promax/1998.6/sys/ to /promax/1998.6/sparc/ should be
created on igor so that the /promax/1998.6/sys/ file system
appears the same on all machines, including igor. Then,
users can add something like /promax/1998.6/sys/bin/ to
their PATH and forget about machine-dependent directory
names.
System administrators would not typically mount
igor:/promax/1998.6/etc/ remotely, because the
configuration files in /promax/1998.6/etc/ are likely to vary
from machine to machine.

Machine-dependent directories are named after the machine


type, not the vendor name, so different architectures from the
same vendor (for example, DECs alpha machine) correspond
to different directory names.

Other Docs

Known Problems

Directory Naming Conventions126

Developers Programming Guide

Directory Naming Conventions


Where possible, directory names are chosen to follow UNIX
conventions. In particular, the names bin/, etc/, include/, lib/,
and src/ are used for directories that contain files that an
experienced UNIX user would expect.
bin/ directories contain programs or shell scripts that are
launched by humans, such as the flow builder.
Machine-dependent programs go in machine-dependent
directories, such as $PROMAX_HOME/rs6000/bin/.
Machine-independent shell scripts go in
$PROMAX_HOME/port/bin/. Programs that are typically
executed by other programs, such as a ProMAX or Prospector
executive, go in the exe/ directory and have names that end in
.exe.
Subdirectories beneath src/ correspond to the destination of the
compiled code. Thus, src/lib/ contains source code for the
libraries in lib/, src/exe/ contains the source for executables in
exe/, and so on. The source code for libmaxutil.a is in
src/lib/maxutil/. Likewise for other libraries. Every subdirectory
of src/lib/ contains a Makefile that is responsible for building
the corresponding library.
All .o files are built in machine-dependent obj/ directories, so
that source code can be compiled for all machine types
simultaneously. The hierarchy beneath obj/ is the same as that
for src/, and the default Makefile rules exploit this similarity.
Some of our subdirectories, such as misc/, menu/, and help/
have no UNIX counterparts, so their names are simply chosen
to reflect the contents of these directories. Directory names
contain only lower-case characters (except for SCCS/
directories), simply to make them easier to type.

Other Docs

Known Problems

Product-dependent Subdirectories127

Developers Programming Guide

Product-dependent Subdirectories
Some files with the same names are different for different
products. For example, the menu and help files for ProMAX
2D, Prospector, ProMAX VSP, and ProMAX 3D differ. To
distinguish among different files for different products, the last
subdirectory sometimes reflects the product name. For example,
agc.menu appears in menu/promax/, menu/prospector/,
menu/promaxvsp/, and menu/promax3d/. The ProMAX flow
builder takes advantage of this structure to find and use the
appropriate files, depending on which product is being used.
The lib/ directories contain libraries (.a archives) of .o files that
are used to build executables. The following table describes
some of the more important libraries.
Libraries
File

Description

libmaxtool*

ProMAX tools for exec.exe only (formerly known as tools*.a). Most


programmers will be adding code to these libraries. Multiple libraries are used to
reduce the time required to update them.

libmaxexec.*

ProMAX utility functions called by tools and exec.exe only (formerly known as
exec.a). Link with this and you will get an executable as big as the exec.exe.

libmaxutil.*

ProMAX utility functions used by any ProMAX program or tool (formerly


known as MAX1.a and MAX2.a). Stand-alone programs typically need this
library, but DO NOT need ibmaxexec.a.

libmaxui.*

ProMAX user interface functions (formerly known as routines.a).

libagfc.*

ProMAX library of sort routines, FFTs, interpolators, etc.

X11/libXaw.a

Our customized and bug-free X Athena widget library.

X11/libXhp.a

Our customized and bug-free X HP widget library.


Libraries developed at Landmark follow the UNIX naming convention of
beginning with lib and ending with .a for shared versions.

Other Docs

Known Problems

Third-party Software128

Developers Programming Guide

Third-party Software
Third-party software requires special handling because third
parties are unlikely to organize their files in the same way that
Landmark does. Two or more vendors may choose the same
name for different files. Some vendors permit Landmark to
distribute their software and some do not. Today, no two sets of
third-party software can be handled in exactly the same way.
When a third party permits Landmark to distribute its software,
we simply install it in the usual place in the
$PROMAX_HOME hierarchy, except that we put it inside a
subdirectory that reflects the vendors name. An example is the
golden.a library from Golden Geophysical, which goes in
$PROMAX_HOME/sys/lib/golden/golden.a. We distribute this
library because Golden uses hooks into our licensing system
that force users of Goldens software to obtain a license from
Golden. Another example of software that Landmark distributes
is SDIs viewer (in $PROMAX_HOME/sys/exe/sdi/sdi_view)
for CGM metafiles, which has its own security/licensing
scheme.
All third-party software is installed (or symbolically linked) in
the $PROMAX_HOME directory tree with a unique directory
name corresponding to the vendor. For example, inside
$PROMAX_HOME/port/include/ are geoquest/ and sdi/
directories. These vendor-specific directories minimize file
name collisions. (Note that both geoquest/ and sdi/ have a
portable.h file.) Software that includes portable.h should do so
with #include geoquest/portable.h or #include sdi/portable.h,
depending on which portable.h is needed. In some cases both
may be included, so the vendor-specific directory name is
important. As always, full pathnames should not and need not
be specified in these #include statements.

Other Docs

Known Problems

Recompilation - GNU Make129

Developers Programming Guide

Recompilation - GNU Make


Every executable or library has its own Makefile, which is
located in the directory containing its source code. For example,
the Makefile for sys/exe/exec.exe is located in
port/src/exe/exec/. Likewise, the Makefile for the library
sys/lib/libmaxutil.a is located in port/src/lib/maxutil/.
Landmark Makefiles must be used with the GNU make
program (which we call gmake)they are incompatible with
the make program provided with most UNIX systems. We use
gmake primarily because it provides a powerful and uniform set
of features for all UNIX systems. The set of make features
provided by all UNIX systems is inadequate for the
management of software development projects as complex as
ours. The Free Software Foundation supports and distributes
GNU make with source code and documentation that is lucid
and complete. The GNU Make Manual (Stallman and McGrath,
1991) is highly recommended. In addition, a UNIX man page is
located in $PROMAX_HOME/port/man/man1/.

Other Docs

Known Problems

Makefile Rules130

Developers Programming Guide

Makefile Rules
Each developer of a library or executable program must provide
a Makefile to build it on all machine types supported by
Landmark. Most programmers will never have to write a
Makefile from scratch because there are several examples in the
src/ directories. However, if you write or modify Makefiles, be
sure the Makefile does not reference anything outside of the
$PROMAX_HOME directory tree. This simple rule:

facilitates system administration

makes porting to new machines easier

helps ensure that we distribute everything that clients need


for their own ProMAX development

Makefiles should reference only those libraries and include files


that are absolutely necessary to build whatever it is that they are
supposed to build. Makefiles should provide recipes for
building programs and/or libraries with no extra ingredients. If
programmers follow these rules, then it is easy to determine, for
example, which of our programs may be affected if GeoQuest
modifies its libraries.
Writing Makefiles is simplified by the standard definitions and
rules contained in advance.make and other files stored in the
$PROMAX_HOME/port/include/make/ directory.
advance.make sets numerous variables for directory paths that
are used in Makefiles, among other things. In particular,
advance.make automatically determines the machine type and
sets variables for machine-dependent libraries, compilers, flags,
etc. Hardwired pathnames to libraries, include files, etc., should
not be specified in Makefiles.
Another useful file in $PROMAX_HOME/port/include/make/
is maxprog.make. This file is included by Makefiles that build
stand-alone programs and socket tools, such as autostat.exe and
gbmig.exe. The core of the Makefiles for most stand-alone
programs and socket tools lie in the definitions and rules in
maxprog.make and advance.make.
Yet another useful file in
$PROMAX_HOME/port/include/make is machine_type.make,
where machine_type might be rs6000, sgimips or decmips. This
file sets variables which are specific to that platform.
Other Docs

Known Problems

Makefile Options131

Developers Programming Guide

Makefile Options
To make a program or library, just cd to the directory containing
the source code for the program or library, and type gmake.
All Makefiles that include advance.make provide two important
command line options. The first is for debugging. Typing
gmake debug=yes turns on debugging and turns off optimization.
The default is debug=no. Another useful command line option
for gmake is gmake clean, which deletes libraries and objects in
your personal directories, or gmake clearlibs, which only
deletes libraries.
Other supported options are purify=yes (Sun only),
quantify=yes, and loadmap=yes. purify=yes will try to run the
commercial Purify package on compiled code in order to find
memory leaks. quantify=yes will try to run the commercial
Quantify package on compiled code in order to profile the code.
(This assumes that Purify and/or Quantify are loaded on your
system.) loadmap=yes is an IBM option which will create a
loadmap file, which will report the source of undefines and/or
multiple defines in your code.
An executable shell, $PROMAX_HOME/port/bin/Makeexec, is
provided to make it easy to build any variant of exec.exe. This
shell simply cds to the exec source directory and runs gmake
with the command line arguments provided to Makeexec. For
example, typing
Makeexec debug=yes

will build the ProMAX exec with debugging enabled.


Makeexec is most convenient after modifying a tool, such as in
lib/maxtool/agc/, although it can be used from within any
subdirectory of $PROMAX_HOME/port/src/.

Other Docs

Known Problems

User and Master Versions132

Developers Programming Guide

User and Master Versions


The Makefiles have been designed to support simultaneous
development by a large number of programmers. Each
programmer should have his own version of the Master
$PROMAX_HOME directory tree in his home directory. For
example, /home/dave/$PROMAX_HOME would contain
Daves User version of $PROMAX_HOME. The actual
locations of the User and Master versions are set in
advance.make.
The Makefiles behave differently depending on which version
(User or Master) is the current working directory when running
gmake. For example, if Barry types gmake in
$PROMAX_HOME/port/src/lib/maxtool/ (the Master
directory), then the Makefile will compile source code as
necessary to ensure that the libraries
$PROMAX_HOME/sys/lib/libmaxtool*.a are up-to-date.
However, if Dean types gmake in
/home/dean/$PROMAX_HOME/port/src/lib/maxtool/, then the
Makefile will update
/home/dean/$PROMAX_HOME/sys/lib/libmaxtool*.a via the
following two-step algorithm:
1.

Any of the Master versions of libmaxtool*.a that are newer


than the corresponding User versions are copied to the
User directory, effectively replacing the User versions.

2.

The User versions of libmaxtool*.a are updated as


necessary by compiling source code in the User
subdirectories of maxtool/.

This algorithm ensures that Dean always has the latest tools that
have been installed in the Master versions, while enabling him
to have his own User version for development.
An important difference between User and Master versions of
$PROMAX_HOME is that a User version need not contain
everything that is in the Master version. Typically,
/home/larry/$PROMAX_HOME might contain subdirectories
for only those tools on which Larry is working, plus the
subdirectories necessary for his own version of exec.exe. When
Larry links his User versions of exec.exe, the exec Makefile will
ensure that any prerequisite libraries found in Larrys
$PROMAX_HOME directory tree are up-to-date. Any

Other Docs

Known Problems

User and Master Versions133

Developers Programming Guide

prerequisite libraries not found in Larrys $PROMAX_HOME


tree will be obtained from the Master version of
$PROMAX_HOME, and the Master libraries will be assumed
(not ensured) to be up-to-date.
A general rule to remember in using the $PROMAX_HOME
Makefiles is that they will search for include files and libraries
in the User version and the Master version of
$PROMAX_HOME, in that order. If Christof has his own User
version of the include file cglobal.h, then that version will be
included when he makes something in
/home/stof/$PROMAX_HOME/port/src/. Otherwise, the
Master version of cglobal.h will be included. The search order
used by the Makefiles implies that Christof does not need a
copy of every include file or library in order to build his own
User versions of exec.exe, but that he can override the Master
versions as necessary during his development and testing.

Other Docs

Known Problems

Master Versions for Landmark Clients134

Developers Programming Guide

Master Versions for Landmark Clients


Makefiles were designed to support development efforts by
Landmark clients, who themselves may have a large number of
programmers. A programmer at a client site must be able to
develop and test new ProMAX tools without changing anything
in the sites own Master version of the $PROMAX_HOME
directory tree. Likewise, the ProMAX guru at a client site who
is in charge of the Master version should not change the
software distributed by Landmark. Therefore, to facilitate their
use by clients, the Makefiles actually support three different
versions of $PROMAX_HOMEUser, Master, and Landmark.
By default, the Master version for clients is assumed to be the
Landmark version. This default will work well for clients with
no more than one or two programmers. However, clients with
more programmers will likely want the Master version to be
different from that provided by Landmark. These clients would
make their own top directory, such as
$PROMAX_HOME/client/, and then define the variable ctopdir
in advance.make. If ctopdir is defined, then it is assumed to be
the root directory of the clients Master version of the software.
The clients programmers would have their own User versions,
just like programmers at Landmark. A client programmer who
develops a new ProMAX tool could make it available to all
ProMAX users at the site by installing it in the Master directory
tree and remaking the Master versions of exec.exe.
Clients with their own Master version will also need access to
numerous files from Landmarks version of the software.
Therefore, when Makefiles search for include files or libraries,
the precedence of the three versions goes as you might expect
User, Master, and Landmark, in that orderso that anything
that is not contained in the User or Master versions will be
picked up from the Landmark version.
At Landmark, the variable ctopdir is left undefined, so that the
Master version is the Landmark version. You might say that
Landmark is its own client. Only programmers at Landmark
should modify the Landmark version of $PROMAX_HOME.
Reference:
Stallman, R. M., and McGrath, R., 1991. GNU Make: a
program for directing recompilation. Free Software Foundation.

Other Docs

Known Problems

135

Developers Programming Guide

C Environment

This chapter introduces the ProMAX C programming


environment and highlights some of the conveniences within
that environment. (See the C Programmng Examples appendix
for examples of C include files and simple processes.)

Topics covered in this chapter:

C Process Components (non-socket tools)


C and FORTRAN Links
Global Parameters

Other Docs

Known Problems

C Process Components136

Developers Programming Guide

C Process Components
The components of a ProMAX process written in the C
programming language are as follows:

a menu
an init_ subroutine
an exec_ subroutine
included files
an entry in the toolcall source file (toolcall.c or toolcall.f)
an entry in the Processes list

The menu is written using Lisp commands.


The initialization routine is executed once. It is used to get user
input parameters, allocate any memory that is needed
throughout the process, and to do anything that you will need to
do just once in the course of the processing. It is also used to
declare the number of parameters that need to be saved for
re-entrancy.
Included files usually have an .h appended to their name, but
these included files do not generally contain parameters for
re-entrancy.
The entry of your new tool in the toolcall.c or toolcall.f file tells
the trace Executive about the existence of your new processing
tool.
Finally, the entry in the Processes list points to your menu.

Other Docs

Known Problems

C and FORTRAN Links137

Developers Programming Guide

C and FORTRAN Links


The UNIX convention for linking C and FORTRAN
subroutines is demonstrated in the following examples.

Calling a FORTRAN Routine from a C Routine


The following syntax is used to call a FORTRAN routine from a
C routine. Suppose we have the following FORTRAN routine:
A_FORTRAN_ROUTINE( ALPHA, CNAME, NINT, ARRAY, CNAME2 )
REAL ALPHA, ARRAY()
INT NINT
CHARACTER CNAME, CNAME2

We call it from a C routine as follows:


float alpha, array[128];
int nint;
char cname[8], cname2[64];
a_fortran_routine_( &alpha, cname, &nint, array, cname2,
8, 64 );

Note that:

The name is all lower case with an underscore appended to


the name.
Only addresses are passed to FORTRAN (call by
reference).
The length of the character strings are appended to the
calling arguments.

Calling a C Routine from a FORTRAN Routine


The following syntax would be used to call a C routine from a
FORTRAN routine. Suppose we have the following C routine:
a_c_routine_( float *alpha, char *cname, int *nint,
float\ *array, char *cname2 );

We call it from a FORTRAN routine as follows:


CALL A_C_ROUTINE( ALPHA, CNAME, NINT, ARRAY, CNAME2 )

Other Docs

Known Problems

C and FORTRAN Links138

Developers Programming Guide

Note that the C subroutine has an _ at the end of the name.


This is required if a C subroutine is going to be called from a
FORTRAN routine. Another requirement if a C routine is to be
called from FORTRAN is that the calling arguments of the C
routine must be call-by-reference; in other words, the
arguments must be pointers rather than just values. Given these
rules and the fact that all ProMAX modules get called from the
FORTRAN subroutines in toolcall.f or analogous C routines in
the equivalent toolcall.c, the initialization routine in a C module
must be named
init_name_( int *len_sav, int *itooltype )

and the execution routine must be called


exec_name_( float *trace, float *rthdr, int *ithdr )

In other words, the _ must follow the tool name and all
arguments must be pointers. In this example, the exec_ calling
arguments are for a simple tool.

Other Docs

Known Problems

Global Parameters139

Developers Programming Guide

Global Parameters
The cglobal.h file (listed in the C Programming Examples
appendix) provides the facilities for accessing the ProMAX
external global common blocks using C structures. In
FORTRAN, common blocks are stored in a format similar to
structures in C. For example, using cglobal.h, the C variable
globalRuntime->samprat

corresponds to the FORTRAN variable SAMPRATz of the


GLOBAL_RUNTIMEcz common block. Other global variables
follow the same style of using the common block name as the
structure name and the same variable name in lower case
without the trailing z.
The FORTRAN constants, IENGLISHpz, are identical in C,
keeping the upper case but with the trailing pz dropped
(IENGLISH). For a complete listing of the C external global
variable names and constants, see the Global Parameters
chapter.

Trace Header Index Values


Array index values in C start with 0 while array index values in
FORTRAN typically start with 1. The ProMAX trace header
routines for the C programming language always use the C
standard of 0 being the index of the first element in a trace
header array.
ProMAX trace header routines for C all start with the three
letters hdr followed by other letters; for example, hdrIndex is
a function that returns the index of a trace header, the index
appropriate for the C programming language. The index for
standard headers can be found in the stdHdr structure defined in
$PROMAX_HOME/port/include/cglobal.h. Note that the
header index values in stdHdr are for FORTRAN arrays since
the stdHdr structure points to the same place in memory as the
trace executives standard header common block STD_HDRcz
(defined in $PROMAX_HOME/port/include/header.inc). C
programmers can use the macro STDHDR(x) to subtract 1 from
the value of the standard header, or the C programmer can
simply subtract 1 from the standard header to obtain the correct
C header array index.

Other Docs

Known Problems

Global Parameters140

Developers Programming Guide

Re-Entrancy
ProMAX modules handle re-entrancy by putting the permanent
variables in structure called parms by using the following
syntax. ProMAX FORTRAN modules handle re-entrancy by
keeping permanent variables in the common block
SAVED_PARMS. The Executive copies the variables out of
SAVED_PARMS to a private storage area after each routine is
called to avoid a conflict between variables of two separate calls
of the same module in a flow. The variables are then copied
back before the routine is called again.
BEGINPARMS
int int1, anotherInt;
float aFloat, anotherFloat;
Tbl *vel_tbl;
ENDPARMS(parms);

This block is placed outside of the init and exec subroutine


blocks.
The variables are then referenced in init_ and exec_ using the
standard C syntax for accessing a member of a pointer to
structure:
parms->int1, or parms->aFloat;

The *len_sav calling argument for init_name_( ) can be


conveniently set as follows:
*len_sav = NPARMS(parms);

The syntax of BEGINPARMS, ENDPARMS, and NPARMS are


macros defined as follows:
#define BEGINPARMS static struct{
#define ENDPARMS(p) } *(p)=(void *)
(&saved_parms_.buffer[1] );
#define NPARMS(p) (2+sizeof(*p)/sizeof(float));

Other Docs

Known Problems

141

Developers Programming Guide

Tool Types

ProMAX supports three main types of tools: executive,


stand-alone, and IPC. This chapter provides an overview of
these types.

Topics covered in this chapter:

Executive Tools

Simple Tools

Ensemble Tools

Panel Tools

Single Buffer Tools

Double Buffer Tools

Complex Tools
Stand-alone Tools
IPC Tools

Other Docs

Known Problems

Executive Tools142

Developers Programming Guide

Executive Tools
The Executive supports six varieties of tools: simple, ensemble,
panel, single buffer, double buffer, and complex (with the input
tool being special case of the complex tool). Each of these tool
types is designed to expedite the coding of typical trace
handling situations that arise in seismic processing. The
Executive attempts to do as much as possible to simplify data
management and the development environment (see the
Executive chapter).
Each of the Executive tools require a subroutine known as the
init phase and another subroutine known as the exec phase. The
name of an init or exec subroutine is dictated by ProMAX. The
name of the init routine is the tool name preceded by INIT_.
The name of the exec phase is the tool name preceded by
EXEC_. The Executive uses the tool name found in the
exec_data portion of each menu in the flow (see the Menu
chapter) pre-pended with init or exec to call the appropriate
tool.
The following sections describe the purpose and general
structure of the init and exec subroutines, and the mechanism by
which processing parameters are passed between the routines.
The buffered tools (single and double buffered tools) also
require a subroutine called the flow routine, which is discussed
later in the buffered tools sections.

init Subroutine
The init routines are responsible for:

Other Docs

getting menu parameters from the packet flow file and


saving them in the common block (FORTRAN) or in
external parameters (C) for use in the exec subroutine

doing one time calculations, such as calculating and saving


a filter for application in the exec phase. The filters
location in memory, not the filter itself, would be saved in
the common block defined in the include file

Known Problems

Executive Tools143

Developers Programming Guide

reserving any memory that would be held for the entire job.
For example, memory buffers of the size of a few traces
would be considered too small to bother allocating and deallocating in the exec phase. Buffers the size of a shot
gather would normally be allocated in the exec phase and
de-allocated after each group of traces exited the tool.

creating or deleting new header or database entries and


resetting any global runtime variables

checking parameters, memory and disk usage


requirements, etc. and erroring out if necessary

In short, the init subroutine does things that need to be done just
once during the execution of a particular processing tool.
The final and important responsibility of the init subroutine is to
set the values of the init subroutine return arguments called
LEN_SAV and ITOOLTYPE. The LEN_SAV parameter is the
number of memory words allocated to keep re-entrant
parameters and variables. ITOOLTYPE is a integer variable
indicating the tool type. The tool types are defined in the global
parameter include files global.inc for FORTRAN and cglobal.h
for C. Both of these variables must be set prior to exiting the init
routine.
The init phase routine for all tool types has the same calling
arguments, those of LEN_SAV and ITOOLTYPE. The
following is the subroutine definition for the Amp Ratio
exercise (see Simple Tool Examples appendix).
SUBROUTINE INIT_AMP_RATIO( LEN_SAV, ITOOLTYPE )

In the C programming language the function definition is


void init_amp_ratio( int* len_sav, int* itooltype )

parms Structure and .inc File


As discussed above, the init subroutine retrieves processing
parameters from the menu. The processing parameters are
passed from the init to the exec subroutines by way of a
common block called SAVED_PARMS in FORTRAN and
through an external structure called parms in C processes. The
SAVED_PARMS common block and parms structure must be
used so that the trace executive can save the processing

Other Docs

Known Problems

Executive Tools144

Developers Programming Guide

parameters for each instance of a tool in a flow. This allows a


tool to be used more than once in a flow while saving the
parameters for each occurrence of the tool. For example, the
band-pass filter module could be used twice in one flow, but
since there is only one subroutine for band-pass filter, the
parameters for each occurrence of the routine in the flow must
be kept separate and loaded into the routine when that
occurrence is called by the trace executive. The ability to use a
routine more than once in a flow is called re-entrancy.
In a FORTRAN module, the SAVED_PARMS common block
is a standard common block. In C, the parms structure is created
through use of the BEGINPARMS and ENDPARMS macros
which are defined in
$PROMAX_HOME/port/include/cglobal.h, where
$PROMAX_HOME is the directory path where the ProMAX
system is installed. An example of the SAVED_PARMS
common block and its use can be seen in the .inc files in the
directory $PROMAX_HOME/port/src/lib/maxtool/amp_ratio.
An example of the parms structure and its use can be seen in the
.c files in $PROMAX_HOME/port/src/lib/maxtool/ampRatio.

exec Subroutine
The exec subroutine is the subroutine that actually processes
data. The processing parameters are passed to the subroutine
through the saved parameters. The exec subroutine is normally
called multiple times within a processing flow since it processes
a natural grouping of traces and then passes those traces along
to tools that are further down the flow. The exec subroutine of a
band-pass filter program, for example, would be called each
time a new trace is passed down the pipeline to be filtered.
Since the exec routine is called multiple times, it is good
programming practice to deallocate memory that is allocated
within the exec subroutine before the routine returns control to
the trace executive.
A feature common to all exec tools is the cleanup condition.
After the last trace has passed through a tool in the flow (the rest
of the flow may have been executing for some time), the
Executive will call that routine one more time with the global
runtime ICLEANUPz set to true(=1). In C this value is in
globalRuntime->cleanup. This gives the tool an opportunity to
release any allocated memory, flush buffers of data, etc., and
signals the Executive not to call this portion of the flow again.

Other Docs

Known Problems

Executive Tools145

Developers Programming Guide

Be careful to return from the routine immediately after these


tasks and not continue on in the routine. For all tool types,
except complex and buffer tools, the Executive automatically
handles the last trace condition.
The complete calling argument list for an exec subroutine is
dependent upon the type of the processing tool (COMPLEX,
SIMPLE, etc). There are some common features to the
argument lists however. In all exec subroutines the calling
arguments include a buffer to hold a data trace array, a trace
header array for integer array values and another trace header
array for floating point trace header values. Note that the real
and floating point header arrays are actually equivalent
locations in memory. The subroutine definition for amp_ratio in
both FORTRAN and C is as follows:
SUBROUTINE EXEC_AMP_RATIO( TRACE, ITHDR, RTHDR )
void exec_amp_ratio( float* trace, int* ithdr, float*
rthdr )

Simple Tools
Simple tools are designed for those numerous seismic data
processing tools that only require a single trace at a time.
Scaling, bandpass filtering, spiking decon, NMO correction,
static shifting, and geometry installation are all examples. The
simple tool assumes a single trace will be input, the tool will
process the trace, and then output the processed trace to be
picked up by the trace executive routine. No buffering or special
directives to the Executive are required.
The amp_ratio example module makes an approximate first
break pick by finding the maximum of the ratio of a pair of
adjacent sliding time windows. After making the pick, the user
optionally stores the results in the trace headers and TRC
Ordered Database. The program also demonstrates the use of
interpolated time gates to limit the pick search range. This
example can be found in the Simple Tool Examples appendix.
Before leaving the init phase of amp_ratio, or any simple tool,
ITOOLTYPE must be set to ISIMPLEpz.

Other Docs

Known Problems

Executive Tools146

Developers Programming Guide

The exec phase routine for the Amp Ratio simple tool has the
following calling arguments:
SUBROUTINE EXEC_AMP_RATIO( TRACE, ITHDR, RTHDR )

TRACE is a buffer containing a single input or output trace


array (NUMSMPz long; see the Global Parameters chapter).
The Executive passes in a trace and returns the processed trace
(in TRACE buffer) to the flow for subsequent processing upon
exiting. ITHDR and RTHDR are fixed and floating point
equivalenced trace header arrays (NTHz long; see the Global
Parameters chapter) which are passed in and out with the
corresponding trace.
The ampRatio example in C has the same arguments of course,
but trace, ithdr, and rthdr are all pointers to arrays.
void exec_amp_ratio_(float *trace, int *ithdr, float
*rthdr)

Simple tools require little additional discussion except for


runtime variables. Consider the case of resampling the data
from 2 ms to 4 ms. Both the number of samples per trace and
the sample rate are changing from that point in the flow down.
Remember from the Executive chapter that a separate copy of
the runtime variables will be kept for each tool in the flow. The
last tools copy was given to you at the initiation of your init
phase; you must change these as needed before exiting. The
next tool in the flow will inherit your changes. With each call of
your exec phase, the globals will have the new, updated
versions; therefore, if you need some of the old values, you
must store them as new variables in the common block. In this
example, the runtime variables NUMSMPz (number of
samples/trace) and SAMPRATz will change. Specifically
consider that NUMSMPz will be about half the size after
processing by the tool. So what is the dimension of the TRACE
array passed to the exec phase or the tool? The Executive will
take care of you and set it to the larger of the incoming or
outgoing value. In this example, NUMSMPz may be set at
1001, but incoming trace buffer would be filled with 2001
samples in order to handle the incoming trace. This sort of hand
holding can be expected of the Executive even in more complex
situations described later.

Other Docs

Known Problems

Executive Tools147

Developers Programming Guide

Ensemble Tools
The next most common bundle size for traces is an ensemble,
where data is collected as shots, CDPs, receivers, offsets, etc.
Ensemble tools pass an ensemble of traces in and out of the
exec routines. Two dimensional filtering, such as FK, is a good
example of such processing. An ensemble tool must input and
output one ensemble in each call of the exec routine; however,
the number of traces in the output ensemble can be different
than the input.
Refer to the Ensemble Tool Examples appendix for examples of
an ensemble tool. The AVO attribute analysis creates either a
zero offset or gradient stack of incoming ensembles, and
provides an example of fewer traces in the output ensemble than
the input. In the prestack trace interpolation example, more
traces are output than were input.
Before leaving the init phase of an ensemble tool, ITOOLTYPE
must be set to IENSEMBLEpz in FORTRAN or IENSEMBLE
in a module written in C.
The exec phase of a FORTRAN ensemble tool has the
following calling arguments:
SUBROUTINE EXEC_AVO( TRACES, ITHDRS, RTHDRS, NSTORED )

and for C the exec arguments look like this:


void exec_avo_( float *traces, int* ithdrs, float
*rthdrs,\ int *nStored )

The input trace and header arrays are two dimensional in the
sense that there are multiple traces and headers in each array. A
FORTRAN program can dimension the TRACES array as
REAL TRACES( NUMSMPz, MAXDTRz)

and the headers as


REAL RTHDRS( NTHz, MAXDTRz)
INTEGER ITHDRS( NTHz, MAXDTRz )

where MAXDTRz is the maximum number of traces that the


tool is going to see in any trace ensemble in the flow.
MAXDTRz is one of the global variables and its value is

Other Docs

Known Problems

Executive Tools148

Developers Programming Guide

maintained by the Trace Executive. NTHz is the number of


trace header entries in the trace header array.
Most C programmers find it convenient to allocate an array of
(float*) of length globalRuntime->maxdtr (same value as in the
MAXDTRz discussed above) and point the beginning of each
data trace to a place in the array. The trace header arrays are
handled in a similar way. The ProMAX routine fVecTo2d() is
written to make this task easy.
The input trace and header buffers may not be completely filled
if the current ensemble is not the largest ensemble in the
dataset. The NSTORED (*nStored in C ) argument passes the
number of traces in the current ensemble. If the number of
traces in the ensemble is changed (that is, more or less than
NSTORED will be output), then NSTORED must be reset
accordingly prior to exit from the exec subroutine. The
Executive allocates the required memory and starts
accumulating traces just prior to calling the exec ensemble
routine. When an end-of-ensemble flag is found in a trace
header, indicating the end of the current ensemble, the
Executive calls your exec routine and passes the ensemble of
traces and headers. Your only responsibility is to return an
ensemble. You are at liberty to change the ensemble size, even
to one in the case of stacking, but the ensemble flag in the trace
headers must be properly set upon exiting. Of course, if you
change the ensemble size by stacking or interpolating traces,
you are responsible for changing the runtime, MAXDTRz
(globalRuntime->maxdtr in C), to reflect this change.
Remember that MAXDTRz or globlaRuntime->maxdtr must be
changed in the init_ subroutine, NOT in the exec subroutine.
You might wonder what the Executive would do for the buffer
size of TRACES if MAXDTRz was doubled for trace
interpolation. The input buffer will be filled with the original set
of, for example, shot traces, but the buffer would be
dimensioned large enough to accommodate the larger output
ensemble size. It is also worth pointing out again that the
Executive is allocating and de-allocating these input and output
buffers automatically as traces drop through the flow.

Panel Tools
Panel tools are designed to handle situations in which a 2D
processing step is to be applied to a dataset but there is not

Other Docs

Known Problems

Executive Tools149

Developers Programming Guide

sufficient room in memory to hold the entire 2D dataset at one


time. Post-stack migration and FK filter of large stacked
sections are two examples. With a panel approach, the dataset
can be divided into pieces that can be comfortably processed by
the system and then appropriately blended back together.
Panel tools attempt to collect a set number of traces to process
in each call of the exec routine. The exec subroutine processes
the 2D array that has been passed to it and passes the array back
out. The trace executive blends the processed array back
together with the adjacent panels that have been processed in a
like manner. The following figure depicts a stacked section; the
dashed vertical lines represent data traces, and the solid vertical
lines represent the panel of traces from within the section that is
being processed. The traces at the edge of the panel are summed
with the traces at the edge of the previous panel to provide
continuity from panel to panel in the processed section.

A panel of traces within a stacked section


Panel tools can panel through a large ensemble as well as a
through a stacked section. If an ensemble is found to be smaller
than the panel size, the panel exec will process the ensemble as
an ensemble tool would, without paneling or blending the traces
back together. An exception to this is the special case in which
an ensemble size is equal to one trace, since this typically
represents stack data. Panel tools are generally written in such a
way that the panel size is larger than a typical shot ensemble.

Other Docs

Known Problems

Executive Tools150

Developers Programming Guide

They will process shots (and small to moderate stack datasets)


like an ensemble tool, but will still panel for large stack datasets
or anomalously large ensembles (common offset sort).
In a panel tool, the programmer codes simply for a matrix of
traces. The Executive handles the buffering of traces and the
overlap blending automatically. The only special coding
required is for a panel that has fewer than the expected number
of traces. When you reach the end of a dataset or a large
ensemble there will usually be insufficient traces to complete
the panel. You can not anticipate when this will happen and
must be ready to deal with it for any panel.
Before leaving the init phase of a panel tool, ITOOLTYPE must
be set to IPANELpz in a FORTRAN module or to IPANEL in a
C module. Another routine that must be called in the init
subroutine of a panel tool is EX_PANEL_PARMS in
FORTRAN or exPanelParms in C. The arguments
EX_PANEL_PARMS and exPanelParms notify the trace
executive of panel size, overlap, and the number of traces to mix
between sequential panels. It also tells the trace executive how
much padding is required. The panel width, overlap, and mixing
are demonstrated by the example illustrated in the figure below.
The symbol O in the figure is used to indicate a trace that is
output after the panel is processed. An X indicates a trace that
is discarded after the panel is processed. An M indicates a
trace that is mixed with a trace from a previous panel and then
passed on in the trace pipeline for further processing. The
variable PANEL_SIZE is the number of traces in the panel.
PANEL_EDGE is the number of traces on either end of the
panel that will be either discarded or mixed after the panel is
processed. The variable PANEL_MIX is the number of traces at
either end of the panel that will be mixed with adjacent panels.

Other Docs

Known Problems

Executive Tools151

Developers Programming Guide

Adjacent panels in the figure are represented by rows of X,


M, and O characters.
A. NPANEL_SIZE=12, NPANEL_EDGE =3, NPANEL_MIX=0
OOOOOOOOOXXX
XXXOOOOOOXXX
XXXOOOOOOOOO

B. NPANEL_SIZE=12, NPANEL_EDGE =3, NPANEL_MIX=1


OOOOOOOOOMXX
XX MOOOOOOMXX
XXMOOOOOOOOO
C. NPANEL_SIZE=12, NPANEL_EDGE =3, NPANEL_MIX=3
OOOOOOOOOMMM
MMMOOOOOOMMM
MMMOOOOOOOOO

Note that the mix traces are a subset of the panel edge;
therefore, the number of mix traces must be less than or equal to
the number of edge traces. If the init subroutine of a panel tool
does not call EX_PANEL_PARMS, then the tool defaults to an
ensemble tool and the advantages of the panel tool are lost.
The exec phase routine for a panel tool has the same calling
arguments as the ensemble tool:
SUBROUTINE EXEC_PANEL_TEST( TRACES, ITHDRS, RTHDRS,
NSTORED )

for FORTRAN and


void exec_panel_test( float* traces, int* ithdrs,
float*\ rthdrs, int* nstored )

for C.
The NSTORED argument passes the number of traces found in
the current panel. NSTORED will be equal to the panel size in
traces specified in the init phase, except when the last trace in
the panel is at the end of a datasets or is at the end of an
ensemble that was not large enough to fill out the panel.

Other Docs

Known Problems

Executive Tools152

Developers Programming Guide

Panel tools offer padding in both time and space. This is to


facilitate such things as in place FFTs without the allocation of
additional memory. When using time padding, the traces that
are input to the exec subroutine are of length NUMSMPz + time
pad length. The executive provides the traces in a buffer that is
long enough to hold the padded trace, then shortens the trace on
output to NUMSMPz for subsequent processes. The value of
NUMSMPz remains set to the number of samples that will be
output from the tool after the panel tool is finished processing.
Therefore, NUMSMPz is always less than or equal to the
padded trace length. When padding traces are used, the padded
traces occur at the trailing edge of the 2D array containing the
data traces. In other words, the first trace in the input array is a
valid, live trace. There are NSTORED live traces in the array.
These live traces are followed in the array by the number of
padding traces that were specified in the init subroutine.
The padded regions always contain zero amplitudes; a padded
2D array input to the exec subroutine of a panel tool looks like
the following figure in which the dark shaded region represents
the original data and the light shaded region represents the
padded region of zero values.

Other Docs

Known Problems

Executive Tools153

Developers Programming Guide

traces

Original live data traces


Trace
Padding
time

Time padding

A padded 2D array
In FORTRAN programs it is vital to dimension the input trace
array to the exec routine as being NUMSMPz + the number of
padding samples. Therefore, the number of padding samples
must be sent to the exec routine from the init routine through
the SAVED_PARMS common block. Panel modules written in
C must also handle the extra trace length. See the example
programs in both C and FORTRAN in the panel test sections of
the Panel Tool Examples appendix.

Single Buffer Tools


Unlike ensemble tools that stop at ensemble groups or panel
tools that stop at a fixed number of traces, single buffer tools
stop collecting traces at some custom condition set by the
programmer. For example, you may write a tool that needs five
CDP ensembles in memory to implement some enhancement
process to the center CDP. This center CDP will be output, and
the next CDP ensemble will be read with the last four shuffled
down in memory; in other words, you will create a sliding
window of ensembles containing 5 CDP except at the dataset
boundaries. Generally, the condition to stop collecting and start
Other Docs

Known Problems

Executive Tools154

Developers Programming Guide

processing in the exec routine will be dependent on some trace


header condition, such as last trace in fifth CDP gather. For
ensemble tools, this check is simply for the END_ENS flag set
to 1, and is done automatically by the Executive.
For single buffer tools, a third routine in addition to the init and
exec routines must be written. This routine, called the flow
routine, accumulates traces in a buffer one at a time checking
each time for the execute condition. When the proper condition
is met for processing and output, the NOUTPUT calling
argument is set to the number of traces intended to be output
from the exec routine. This will signal the Executive to stop
accumulating traces and to make a call to the exec phase.
Single buffer tools (and double buffer tools) require the usual
init and exec routines plus a flow routine. The init phase must
set ITOOLTYPE to ISNL_BUFFpz in FORTRAN and
ISNL_BUFF in C. FORTRAN routines must also make a call to
EX_BUFF_PARMS before leaving the init routine to set the
maximum buffer size, in traces, for the input or output buffer.
The analogous routine in C is exBuffParms. This call also
specifies the time and space padding parameters for the input
buffer (similar to panel tools).
Refer to the Single Buffer Tool Examples appendix for an
exercise example of a single buffer tool. This example process
resets ensemble flags whenever a selected header changes. The
traces are accumulated in a buffer until this condition is met.
The calling arguments for the flow routine are:
SUBROUTINE FLOW_ENS_DEFINE( TRACES, ITHDRS, RTHDRS,
NSTORED,
&
IFOUND_EOJ, NOUTPUT, NOVERLAP )

Input arguments
Input arguments consist of:
TRACES: the 2D array of input accumulated traces
ITHDRS: the 2D array of trace accumulated headers
equivalenced to RTHDRS
NSTORED: number of traces currently stored in TRACES
IFOUND_EOJ: flag to indicate if the EOJ trace has been
encountered (1=true). Since you are accumulating traces,
you may hit the end of the dataset prior to reaching your

Other Docs

Known Problems

Executive Tools155

Developers Programming Guide

criteria
for processing. In that case, you will be given the last trace
again,
without incrementing NSTORED, and must react
accordingly.

Output arguments
Output arguments consist of:
NOUTPUT: number of traces that the tool will output from the
exec
subroutine. This argument must be set to a value of 1 or
greater for
the exec subroutine to be called.
NOVERLAP: number of input traces to include in the next
buffer that
is accumulated. The last NOVERLAP traces in the current
buffer
will be the first NOVERLAP traces in the next buffer that
is
accumulated in the flow routine.
The exec phase routine for an single buffer tool has the
following calling arguments in FORTRAN:
SUBROUTINE EXEC_ENS_DEFINE( TRACES, ITHDRS, RTHDRS,
NTR_BUFF )

and the following argument in C:


void exec_ens_define( float* traces, int* ithdrs, float*
rthdrs, int* ntr_buff )

This is the same as ensemble and panel tools, with the addition
of the parameter NTR_BUFF. NTR_BUFF is the size, in traces,
of the TRACES buffer and is set to the maximum of NSTORED
or NOUTPUT. If the number to be output is greater than the
number of traces stored, then the number of data traces that are
actually in the buffer to be processed must be sent to the exec
subroutine via the saved parameters.
Like ensemble tools, the number output can be larger (or
smaller) than the number accumulated. This could get tricky
with trace overlapping. Remember that NSTORED minus
NOVERLAP traces will be dropped from the first portion of the

Other Docs

Known Problems

Executive Tools156

Developers Programming Guide

buffer, and that the next NOVERLAP traces are saved at the
beginning of the buffer to start the next call of the flow routine.
When the flow tool is called again, the buffer will have the
NOVERLAP saved traces plus the next trace coming down the
pipe.

Double Buffer Tools


Double buffer tools are identical to single buffer tools in all
aspects except one: the exec phase has extra buffers that are
managed by the Trace Executive to store the output traces and
headers. This allows the programmer to fill the output buffer
without changing the buffer of input traces. In other words, the
Executive handles the allocating and de-allocating of one extra
work buffer. This type of automatic buffering is particularly
convenient for transforming data from one form to another; for
example, in generating a semblance plot from an input CDP or
in interpolating traces within an ensemble.
Double buffer tools require the usual init and exec routines plus
a flow routine. The init phase must set ITOOLTYPE to
IDBL_BUFFpz in FORTRAN and IDBL_BUFF in C, and must
also make a call to EX_BUFF_PARMS (or exBuffParms) to set
buffer size and padding. The flow routine for the double buffer
tool is identical to the single buffer tool.
The exec phase routine for a double buffer tool has the
following calling arguments
SUBROUTINE EXEC_SEMBLANCE( TRACES_IN, ITHDRS_IN,
RTHDRS_IN,
&
NTR_BUFF_IN, TRACES_OUT, ITHDRS_OUT,
RTHDRS_OUT,
&
NTR_BUFF_OUT )

where TRACES_IN, ITHDRS_IN, and RTHDRS_IN are the


input buffers for the traces and trace headers. NTR_BUFF_IN is
the amount of buffer space, measured in numbers of traces, in
the input buffer. TRACES_OUT, ITHDRS_OUT and
RTHDRS_OUT are the output buffers of traces and headers.
NTR_BUFF_OUT is the number of traces available in the
output buffer measured in numbers of traces.
Please refer to the Double Buffer Tool Examples appendix for
an example of how to use a double buffer tool.

Other Docs

Known Problems

Executive Tools157

Developers Programming Guide

Complex Tools
If none of the of the multi-trace tool types handle your needs for
trace bundling, you must finally resort to the complex tool
which offers the ultimate in multi-trace I/O flexibility. This
flexibility comes at a price. You must now handle trace
buffering and block your code into logical units for buffer filling
and flushing. Most tasks can be accomplished without resorting
to complex tools, but, if the need arises, this style of multi-trace
processing is only slightly more difficult.
Please refer to the Complex Tool Examples appendix for an
exercise example of a complex tool. This example process
transforms a shot ensemble so that the time axis is replaced by
the space axis. In other words, the shot is turned on its side.
Before leaving the init phase of a complex tool, ITOOLTYPE
must be set to ICOMPLEXpz in FORTRAN and ICOMPLEX
in a module written in C. The exec phase calling arguments of
complex tools is identical to simple tools:
SUBROUTINE EXEC_TRANSFORM( TRACE, ITHDR, RTHDR )

Like simple tools, one trace is input or output from the exec
routine at a time. Unlike simple tools, complex tools can declare
their state to be filling (only receiving), flushing (only giving),
or both (pipe: input and output in same call, same as a simple

Other Docs

Known Problems

Executive Tools158

Developers Programming Guide

tool). The exec phase of complex tools must declare their state
prior to exiting the routine. The options are described in the
following table:
Complex Tool Options
Option

Description

FILL

Set by a call to EX_FILLMODE. This tells the Executive that the tool is not supplying a trace
upon exit, but that it expects to receive one on the next call. Presumably you are filling a buffer
of traces for future processing. Note that in the very first call to the exec routine, a trace is
passed in and either kept or output depending on the mode (FILL, etc) set before exit. One
slight quirk of the system is that there is no mechanism to know if the trace you just received
and stored is the last trace to be input to the flow. If the trace is the last input trace and the tool
remains in fill mode, the Executive will pass the tool a dummy trace in the next call that has
the trace header entry EOJ set to 1. The tools cleanup flag will not be set (which terminates
the tool from the flow) because the Executive knows that traces are buffered and will be
released later. You are responsible for checking this flag and responding by processing the
traces that have been saved in the routine and then outputting them, primarily by using
FLUSH mode. The EOJ flag appears only ONCE when a tool is in FILL mode, so if there are
traces to dump after the EOJ trace appears, it is a good idea to keep a saved parameter stating
that the EOJ trace has been seen.

FLUSH

Set by a call to EX_FLUSHMODE. This tells the Executive that the tool is supplying
(outputting) traces to the flow upon exit, one trace per call, and that it will not receive a new
trace on the next call. This mode is for flushing traces from a buffer after processing.

PIPE

Set by a call to EX_PIPEMODE. This tells the Executive that a trace will be supplied to the
flow upon exit, and that a trace is expected to be input on the next call. If the last valid trace
has been input to a tool and it asks for another trace in pipe mode, the Executive sets the
cleanup flag to TRUE which terminates the flow for this tool. A complex tool that is always in
pipe mode behaves as a simple tool; in other words, the Executive assumes that the trace being
input is the same trace that is being output and that there are no traces buffered within the tool.
This is not always a valid assumption; however, EX_PUSHMODE alleviates this problem.
When shifting from fill to flush modes, there will be a single call to pipe mode when you are
flushing the last trace in a buffer and expect to start filling the buffer again on next call.

Other Docs

Known Problems

Executive Tools159

Developers Programming Guide

Complex Tool Options (Continued)


Option

Description

PUSH

Set by a call to EX_PUSHMODE. Push mode behaves exactly like pipe mode except for the
important difference that the EOJ trace is input to the tool. Recall that when a tool is in pipe
mode, the Executive does not pass the EOJ flag to the tool. The ability to see the EOJ flag
allows the tool to flush traces that may be stored in a buffer internal to the routine. If a tool has
more traces to flush after the EOJ flag has been found, it goes into flush mode until all of the
traces have been dumped into the processing flow, at which point the tool sets itself to pipe
mode to trip the cleanup flag. The general logic is as in the following pseudo-code for the exec
subroutine.
if( trace header has end of job flag (EOJ) )
set a saved variable that indicates the EOJ trace has
been seen
have_seen_EOJ_flag = TRUE
endif
if( have_seen_EOJ_flag is TRUE )
move trace and header from buffer to output trace
if( the trace being dumped is the last to dump )
set to pipe mode to trigger cleanup mode on next call
else
set to flush mode to continue outputting traces
endif
else
set to push mode, output this trace, accept the next
input trace on next call
endif

A very important point regarding the EOJ flag is that only ONE trace will be passed to the
exec_ subroutine in which the EOJ trace header is set to 1; thus, the have_seen_EOJ_flag
variable is set in the preceeding pseudo-code.
QUIT

Set by a call to EX_QUITMODE. This tells the Trace Executive that the exec subroutine
flushed the last trace in the flow on the previous call to the exec subroutine by using
EX_FLUSHMODE. EX_QUITMODE is called when the exec subroutine is called and:
- it finds that it has no more traces to pass to the trace executive,
- there are no more traces to come, and
- it is time to set the cleanup flag and have the flow terminated for this tool
This is appropriate for the case where the entire stack line was filled, processed, and flushed.
You know you are done when the last trace in the buffer is gone.

An input tool is a type of complex tools; by default, it is the first


tool in a processing flow. An input tool gets data and feeds it
into a processing flow. Examples include those which read data
from a disk or tape or a program that generates synthetic
seismograms. An input tool starts and remains in flush mode
until the last available trace is given to the flow. When the tool is
called again and it finds that it has no more trace to output, the

Other Docs

Known Problems

Executive Tools160

Developers Programming Guide

mode is set to quit mode. Refer to the Input Tool Examples


appendix for an example.
Another complex tool type is the iteration tool. Disk iteration
means to have ProMAX read a group of data traces more than
once from the disk. This facility is useful when all calculations
on an entire dataset must be done before results of calculations
can be applied. Examples include derive-and-apply processes
that must see all the data to first derive surface consistent
parameters (amplitude, decon, statics, etc.) and then pass
through the data again for an application phase. Refer to the
Disk Iteration Examples appendix for a crude example of
surface consistent amplitude correction. The data must pass
through the flow above the iteration tool two or more times, but
this is usually a small price to pay. There are even some
advantages: the first pass can optionally be enhanced (mixed,
FK filter strong low frequency noise, etc.) for the derive phase,
but not enhanced in the application phase. These tools have
virtually eliminated the need for stand-alone tools that handle
data traces.

Other Docs

Known Problems

Stand-alone Tools161

Developers Programming Guide

Stand-alone Tools
There are certain situations to which the pipeline model of trace
flow is not well suited. Modules that need to randomly access
traces off the disk many times are such examples. In these cases
a stand-alone tool that does its own trace I/O may be the answer.
(Executive multiple iteration tools have largely eliminated the
need for stand-alone tools that handle data traces. Refer to the
preceeding discussion in the Complex Tools section of this
chapter.)
ProMAX supports stand-alone executables for data input only.
These executables are launched by the Super Executive just as
the Executive. However, the menu for a stand-alone tool must
supply the executable name in a special section in the exec_data
portion of the menu. The tool is declared a stand-alone type to
the super exec in the same section. The TOOLTYPE and
PATHNAME parameters pass on this information to the super
exec, for example:
exec_data: (STAND_ALONE
(SPECIAL
(TOOLTYPE
implicit: STAND_ALONE)
(PATHNAME
implicit:
/usr/dave/poststack.exe)
)
(GENERAL
(LABEL
implicit: (value LABEL))
)
)

Stand-alone flows can contain only one executable and one


menu associated with that executable. Please examine the
stand-alone menus in the Stand-alone Program Examples
appendix.
Stand-alone programs must handle much of what is done
automatically in the Executive, including:

input of the packet file and special routines for parameter


retrieval
initialization of global geometry and runtime variables
trace input and selection

Please refer to the prestack.f code in the Stand-alone Program


Examples appendix for detailed comments on each of these
items.
Other Docs

Known Problems

Stand-alone Tools162

Developers Programming Guide

For FORTRAN modules, a C wrapper main must be written to


pass the command line arguments containing the packet file
name to the FORTRAN work routine. The wrapper for the
prestack example looks like:
void main( argc, argv )
int argc;
char **argv;
{
prestack_( &argc, argv[1] );
}

Compiling and linking stand-alone modules are somewhat


different than for the Executive subroutines; the compiling of
the C wrapper for FORTRAN processes is one specific
example.

Other Docs

Known Problems

IPC Tools163

Developers Programming Guide

IPC Tools
IPC tools are a relatively new way of programming a ProMAX
process. We recommend this approach to people for starting to
program in ProMAX. If you are an experienced ProMAX
programmer, note that IPC tools used to be called socket tools.
While most inline flow tools reside in a giant program called the
executive, IPC tools are separate programs that pass data via
sockets. As traces come down the processing flow, they are sent
at the appropriate place from the Executive to the IPC tool.
After the processing of each individual trace or group of traces,
the IPC tool sends them back into the Executive where they
continue down the flow. All the communication and associated
bookkeeping is hidden by input and output routines. To the
programmer, this tool is compiled similar to a stand alone
program. To the user, the IPC tool looks like any ProMAX tool.
The main advantages of this method of incorporating modules
into ProMAX are:

The executable size is smaller and links are much faster


and simpler.

The issue of re-entrancy is avoidedeach program has its


own address space.

The logic of a complex tool is simplified. When an IPC


tool needs traces, it calls the subroutines saGetTrace,
saGetEnsemble, or saGetPanel for C, and
ST_GET_TRACE or ST_GET_ENSEMBLE for
FORTRAN (panel I/O is not supported in FORTRAN).
Whenever it wants to write traces, it calls the subroutines
saPutTrace, saPutEnsemble, or saPutPanel for C, and
ST_PUT_TRACE or ST_PUT_ENSEMBLE for
FORTRAN.

The toolcall source code does not have to be edited.

An Alternative Executive does not have to be run for a new


module.

These characteristics mean that it is easy to maintain IPC tools.


You can update individual programs as needed. The compile
and link problems of some other modules does not effect your

Other Docs

Known Problems

IPC Tools164

Developers Programming Guide

module. IPC tools are also easy to trade since you do not need
to trade the entire executive.
On the downside, the IPC tool is less efficient that a normal
tool because of the overhead of data transfer; however, this
overhead is generally very small. And, at present, IPC tools can
only run on the same machine as the executive.
The best approach for understanding IPC tools is to examine the
example programs in the IPC Tool Examples appendix. The
comments in the code describe the steps. The user does not have
to alter the Executive or toolcall source code. The proper subset
of the packet file from the menu is transferred to the the IPC
tool. You can have repeated instances of the same IPC tool in a
flow. And, the IPC tool can access the data base and use other
ProMAX features, just as any normal stand alone program can.
Note, however, that all header routines must be preceded with
an st for C (stHdrAdd instead of hdrADD) and ST_ for
FORTRAN (ST_HDR_ADD instead of HDR_ADD). The same
is true for the Executive error routines.
The IPC tool is designed mainly for C programs but can be used
with FORTRAN programs. Some wrappers for the C routines
may need to be written.

IPC Tool Details


The IPC tool approach is implemented with master
init_stand_alone and exec_stand_alone routines that are
complex tools in the Executive. The packet file passes the path
of the IPC tool executable to init_stand_alone, which executes
it, hooks up sockets with it, passes it the proper subset of packet
files, and handles such items as passing global parameters and
headers. After a signal from the IPC tool, the init_stand_alone
routine returns and the exec_stand_alone starts. The
exec_stand_alone passes the traces via sockets to the IPC tool.
As a complex tool, it can read and write traces as the IPC tool
demands them. On the IPC tool end, we have written routines
that hide the IPC communication from the user.
The performance degradation using this IPC-based method is
not significant. The overhead to initiate and transfer data to an
IPC tool is comparable to running in-line Automatic Gain
Control (AGC). Since AGC is a computationally cheap module
(one or two operations per sample), the communication time

Other Docs

Known Problems

IPC Tools165

Developers Programming Guide

may not be significant. The transfer time to a process that is


running on a different machine from the rest of the flow is
greater, but not unmanageable. The cost of the transfer will be
less when the stand-alone process performs more computations,
since traces are sent and buffered on the receiving machine
while the module is computing. When the process needs the
traces, they are immediately available for access.

IPC Tool Debugging


To debug a IPC based tool, pass the DEBUG parameter in the
menu a value of 2 or 3. In a normal, no debug execution, this
value should be set to either 0 or 1 (1 = verbose listing of IPC
information).
When DEBUG is set to 2, the Executive will not start up the
IPC tool. You just start it, probably under dbx. The Executive
will print out the name of the packet file in /tmp that you must
execute with your program (see the View button in the user
interface). The command in dbx is:
(dbx) run /tmp/pFile_287657

where /tmp/pFile_287657 is the name of the packet file printed


by the Executive. Then, continue debugging your program as
you normally would.
When you set DEBUG to 3, the IPC tool is started but then halts
waiting for you to attach the debugger to it. You give the
command dbx -a 1542, where 1542 is the process ID of the IPC
tool. You can get the process ID of the IPC tools from the
printout (see the View button), or you can get it via the ps
command. After you attach the debugger, you can continue
running the program with the next or cont command. You have
about 5 minutes to attach the debugger before the program
aborts. With this approach, you do not have to specify the
packet file name.

Other Docs

Known Problems

IPC Tools166

Other Docs

Developers Programming Guide

Known Problems

167

Developers Programming Guide

Global Parameters

This chapter describes ProMAX global parameters.

Topics covered in this chapter:

Overview of Global Parameters


Common Blocks and C Structure Descriptions

Other Docs

Known Problems

Overview of Global Parameters168

Developers Programming Guide

Overview of Global Parameters


ProMAX global parameters are dataset-specific values that are
commonly needed within a processing tool. These values are
made conveniently available through the cglobal.h file for C and
the global.inc file for FORTRAN. (See the Global Include File
Examples appendix for examples of global.inc and global.h
files.)
An example of a global parameter is the number of samples per
trace, which can be accessed through the variable name
NUMSMPz in FORTRAN and the structure member
globalRuntime->numsmp.
The global parameters are initialized at run time and are defined
in the global.inc file. Notice that parameters are grouped into
common blocks by similar characteristics and that they all end
with a z suffix.

Other Docs

Known Problems

Common Blocks and C Structure Descriptions169

Developers Programming Guide

Common Blocks and C Structure Descriptions


The following table describes the common blocks and C
structure names and how they are initialized. The names of the
common block members are listed in some cases; the name of
the corresponding C member parameter is obtained by dropping
the trailing z on the name and changing all upper case letters to
lower case. For example, the number of samples per trace in the
FORTRAN GLOBAL_RUNTIMEcz common block is
NUMSMPz. The analogous name in the globalRuntime
structure is numsmp.
Common Blocks and C Structure Names
Item

Description

GLOBAL_CHARcz (FORTRAN)
globalChar (C)

These are global character parameters that are supplied to the


packet file (binary flow) by the flow builder at run-time. These
variables are extracted from packet file by the Executive.

GLOBAL_RUNTIMEcz (FORTRAN)
globalRuntime (C)

These are the global run time parameters. These parameters


are dataset dependent and, as such, are stored with each trace
dataset. These variables are read from disk at run time by the
input tool, if the input is a ProMAX dataset. If the input tool is
reading a foreign dataset (non-ProMAX format) or creating
traces (modeling), the tool must supply values for the
following subset of the run time variables
SAMPRATz
NUMSMPz
IPSORTz
MAXDTRz
IDTYPz
IPKEYz
ISKEYz
IDOMAINz
IGEOM_MATCHz
ITRNO_VALIDz
The remaining run time variables are either set by the
Executive or flow builder:
NTHz
MODEz
IOUNITz
IDATEz
INIT_ONLYz
CLEANUPz
IERRORz

Other Docs

Known Problems

Common Blocks and C Structure Descriptions170

Developers Programming Guide

Common Blocks and C Structure Names (Continued)


Item

Description

GLOBAL_GEOMcz (FORTRAN)
globalGeom (C)

These are the critical global parameters related to geometry


and are stored in the line order database file. Prior to geometry
installation, these values are set to either INULLpz or
RNULLpz. These variables are read from disk at run time by
the input tool. After geometry installation, most of these have
valid entries.

GLOBAL_MISCcz (FORTRAN)
globalMisc (C)

These are the miscellaneous global parameters related to


geometry and are stored in the LINE Ordered Database file.
Prior to geometry installation, these values are set to either
INULLpz or RNULLpz. These variables are read from disk at
run time by the input tool. After geometry installation, most of
these have valid entries.

GLOBAL_COORDcz (FORTRAN)
globalCoord (C)

These are the global parameters related to coordinates and are


stored in the LINE Ordered Database file. Prior to geometry
installation, these values are set to either INULLpz or
RNULLpz. These variables are read from disk at run time by
the input tool. After geometry installation, most of these have
valid entries.

GLOBAL_AQUIScz (FORTRAN)
globalAcquis (C)

These are the global variables related to acquisition and are


stored in the LINE Ordered Database file. Prior to geometry
installation, these values are set to either INULLpz or
RNULLpz. These variables are read from disk at run time by
the input tool. In practice, few of these parameters are ever
assign non-null values.
In addition to common block definition, the global.inc defines
what are referred to as global parameters. These constants end
in pz rather than z and are used instead of arbitrary numbers
(like 7) primarily for code readability. For example, the
primary sort flag may be set to IOFFSETpz instead of 4 for
offset sorted data. Beware that this is accomplished via
substitution by the C pre-processor, so adhere to the
upper/lower case mix.
For C coding, the COMMON blocks are replaced by
equivalent C structures and the same set of global constants
are defined without the pz extension. These definitions are
performed in the cglobal.h header file located in
$PROMAX_HOME/port/include.

Other Docs

Known Problems

171

Developers Programming Guide

Ordered Parameter Files

This chapter describes the ProMAX database, which consists of


a set of ordered parameter files that are used to store
information. See the Ordered Parameter File Examples
appendix for code examples.

Topics covered in this chapter:

Overview of the ProMAX Database


Standard Orders

Other Docs

Known Problems

Overview of the ProMAX Database172

Developers Programming Guide

Overview of the ProMAX Database


The ProMAX Database consists of a set of ordered parameter
files used to store information for each seismic line in structured
categories representing unique sets of information. There are
nine standard Orders that are created when the geometry is
loaded:

LIN (line)
SIN (source index number)
SRF (surface location)
CDP (Common Depth Points)
CHN (channel)
TRC (trace)
OFB (offset bin)
ILN (3D inline number)
XLN (3D crossline number)

Information stored in these Ordered Parameter Files is


considered common to all datasets in the line (or survey)
directory level. Information that is dataset dependent should be
stored in trace headers. See the discussion in the Trace Headers
chapter.
In each Order there are N slots available for storage of
information, where N is the number of elements in the Order
(number of sources, number of surface locations, number of
CDPs, etc.). Each slot contains various parameters (in various
formats) for one particular element of the Order. If values for a
particular parameter are not stored in all of the available slots,
the empty slots contain the proper null value for that parameter.
The following figure shows a sketch of an ordered parameter
file. The order has N elements (columns) and five parameters

Other Docs

Known Problems

Overview of the ProMAX Database173

Developers Programming Guide

(rows). Values would be stored in each of the boxes


(intersection of a row and column).
ORDER ELEMENTS
1

....

....

PARM 1
PARM 2
PARM 3
PARM 4
PARM 5

An ordered parameter file with


N elements and 5 parameters

Collectively, the Ordered Parameter Files are used to store large


classes of data, including the acquisition parameters, the
geometry, statics (and other surface-consistent information),
and pointers between the source, receiver, and CDP domains.
The design of the Orders is tailored for seismic data and
provides a compact format without duplication of information.
Of particular interest to programmers is the cross-referencing
between domains, which reduces the book-keeping in programs
such as residual statics.
The ordered parameter files serve four main purposes:

Other Docs

They serve as a geometry database to Executive tools,


stand-alone processes, and to the flow builder. Menu
parameters can be defaulted to parameters in the line (LIN)
Order; examples include minimum CDP number or
nominal CDP spacing. Surface consistent processing
modules can access these files to determine buffer sizes
and surface relation of shots and receivers, etc.

Known Problems

Overview of the ProMAX Database174

Other Docs

Developers Programming Guide

They provide general inter-tool communication of


information that is global to all datasets in the line or
survey; first break or residual statics picks are typical
examples. In ProMAX, in-line tools make these time picks
and place the picks in the trace Order. Another in-line or
stand-alone tool reduces these picks to shot and receiver
statics that are stored, respectively, as parameters in the
SIN and SRF Orders. Once in the database, these final shot
and receiver static parameters can be applied to any of the
lines datasets. As with trace headers, user defined Ordered
parameters can be of any length or format.

They allow domain mapping between the CDP, SIN, SRF


and TRC Orders. When geometry is installed, these
domains are cross-referenced for fast access. Two
convenience routines exist that utilize this
cross-referencing: DB_ENSEMBLE_MAP and
DB_TRACE_MAP. For example, when using
DB_ENSEMBLE_MAP, from a particular CDP, the
routine can return the receiver static of the nearest station
or the uphole time of the nearest shot. The analogous
routines in C are dbEnsembleMap and dbTraceMap.

They provide quick sorting of traces off disk. Each trace


dataset has a mapping file which maps the relative position
of each trace on disk to the original geometry trace number.
For each of the common ensemble sorts (CDP, shot,
receiver, offset bin, 3D inline, and 3D crossline), a row in
the TRC Ordered Parameter file serves as a look-up table
containing these original trace numbers sorted by the
associated ensemble. A corresponding starting address
look-up row (SLOOKUP) in each of the ensemble Order
files points to the start of each ensemble group in the
corresponding TRC look-up row. For example, assume you
want to read CDP 437 off a disk dataset of unknown sort
order. Disk Data Input will use the column associated with
CDP 437 in the CDP Order to determine the CDP fold
we will use 30 for this exampleand the starting position
(SLOOKUP) in the TRC look-up row for CDPwe will
use 4201. At position 4201 in the CDP look-up row of the
TRC Order is the original trace number for the first trace in
CDP 437, and the next consecutive 29 positions contain the
remaining trace numbers for CDP 437. From this set of
trace numbers, the dataset map file can be used to directly

Known Problems

Overview of the ProMAX Database175

Developers Programming Guide

determine the disk positions of the CDP traces. This


appears complicated, but it suffices to say that Orders
facilitate quick sorts of data from disk.
The quick sort from disk using the MAP file, as described in the
preceeding paragraph, depends on the trace numbers (in the
trace headers) being valid; that is, they are unique and
associated to a column in the TRC Order. If this is not the case,
the dataset will be flagged as such (run-time variable
ITRNO_VALIDz=0), and the sort will be performed using trace
headers.

Other Docs

Known Problems

Standard Orders176

Developers Programming Guide

Standard Orders
The following table describes the nine standard orders.
Standard Orders
Order

Description

LIN Order

The LIN Order contains information that is unique to the LINE, such as:
Geometry:
EXDATUMz - Final datum elevation (if not variable)
IUNITSz - Type of units
ISRCTYPz - Source type
NSHOTSz - Total number of live shots
NUMCDPz - Total number of CDPs
Etc.

TRC Order

The TRC Order contains information that is unique to each trace, such as:
Geometry:
SIN - Shot index numbers of every trace
SRF - Receiver surface location number of every trace
CDP - CDP bin number of every trace
CHN - Channel number of every trace
OFFSET - Source-receiver offset of every trace
SIN_LTBL - SIN look-up table
SRF_LTBL - Receiver surface location look-up table
OFB_LTBL - OFB look-up table
CDP_LTBL - CDP look-up table
ILN_LTBL - ILN look-up table
XLN_LTBL - XLN look-up table
User parameters:
First break pick times
Trim statics
Source-receiver offsets
Etc.

Other Docs

Known Problems

Standard Orders177

Developers Programming Guide

Standard Orders (Continued)


Order

Description

SIN Order

The SIN Order contains information that is unique to each source, such as:
Geometry:
NCHANS - Number of channels in each source
X_COORD - X coordinate of every source
Y_COORD - Y coordinate of every source
ELEV - Elevation of every source
SRF - Nearest surface location number of every source
SOURCE - Live source number of every source
PATTERN - Pattern number of every source
PATT_REF - Pattern reference surface location of every source
DEPTH - Hole depth of every source
UPHOLE - Uphole time of every source
SLOOKUP - Starting address in SIN look-up table for every source
User parameters:
Source statics
Etc.
Source index numbers are unique sequential numbers that are assigned to all of the
records that exist in the dataset that is used to initialize the database. They include
records that are not live sources. Live sources are therefore a subset of shot index
numbers and not a suitable order.

SRF Order

The SRF Order contains information that is unique to each surface location, such as:
Geometry:
FOLD - Receiver fold of every surface location
X_COORD - X coordinate of every surface location
Y_COORD - Y coordinate of every surface location
ELEV - Elevation of every surface location
SLOOKUP - Starting address in SRF look-up table for every surface location
Plus user parameters:
Surface location statics
Etc.
Surface locations are surveyed positions where either a shot or receiver may be placed.
For 2D data, surface locations are generally equivalent to stations. However, 3D data
generally have separate locations for shots and receivers resulting in stations locations
being the super-set of all shot and receiver positions. Receiver locations are therefore
subset and not a suitable order.

Other Docs

Known Problems

Standard Orders178

Developers Programming Guide

Standard Orders (Continued)


Order

Description

CDP Order

The CDP Order contains information that is unique to each CDP bin, such as:
Geometry:
FOLD - Fold of every CDP
X_COORD - X coordinate of every CDP
Y_COORD - Y coordinate of every CDP
ELEV - Elevation of every CDP
SRF - Nearest surface location to every CDP
SLOOKUP - Starting address in CDP look-up table for every CDP
Plus user parameters:
CDP statics
Etc.

ILN Order

The ILN Order contains information that is unique to each ILN bin, such as:
Geometry:
FOLD - Fold of every ILN
SLOOKUP - Starting address in ILN look-up table for every ILN

XLN Order

The XLN Order contains information that is unique to each XLN bin, such as:
Geometry:
FOLD - Fold of every XLN
SLOOKUP - Starting address in XLN look-up table for every XLN

OFB Order

The OFB Order contains information that is unique to each OFB bin, such as:
Geometry:
OFB_CNTR - Offset bin center
MEAN_OFF - Mean offset within the bin
FOLD - Fold of every OFB
SLOOKUP - Starting address in OFB look-up table for every OFB
Plus user parameters:
Offset amplitude adjustment
Etc.

CHN Order

The CHN Order contains information that is unique to each channel, such as:
Channel gain constants
Channel statics (if appropriate)
Etc.

Other Docs

Known Problems

179

Developers Programming Guide

Trace Headers

This chapter describes trace headers, the primary form of


inter-tool communication within the ProMAX system.

Topics covered in this chapter:

Overview of Trace Headers


Definition and Usage of Standard Header Entries

Other Docs

Known Problems

Overview of Trace Headers180

Developers Programming Guide

Overview of Trace Headers


Trace headers are the primary form of inter-tool communication
within the ProMAX system. They are typically used to
communicate information which is unique to individual traces
of the current dataset.. Global variables, another form of intertool communication, are typically used to communicate
information that is shared by all traces of the current dataset.
The Ordered Database, a third form of inter-tool
communication, is typically used to communicate information
that is global to all datasets within the line (unless the datasets
are flagged as not matching the Ordered Database).
Convenience is a governing factor in the form of
communication that is used. For example, geometry
information that is placed in the parameter database can be
conveniently accessed by stand-alone programs that do not wish
to read trace data.
Trace headers within ProMAX are very flexible. Individual
entries may have any length, order, or format. This has proven
to be a tremendous benefit in accommodating new ideas as the
system evolves. (We prefer to use the term trace header entry
rather than trace header word to avoid the notion of fixed
length.)
The concept of an ensemble within the Executive is facilitated
by trace headers. An ensemble is defined as any collection of
traces which (normally) share the same primary sort key value.
Typical examples are shot records, CDP gathers, and commonreceiver gathers. All of the traces within an ensemble have the
header entry END_ENS set to false (NLASTpz in FORTRAN
and NLAST in C), except the last trace, where it is set to true
(LASTTRpz in FORTRAN and LASTTR in C). The global
variable MAXDTRz (maxdtr in C) is the maximum number of
traces per ensemble, which must be greater than the number of
contiguous traces that have END_ENS set to NLASTpz, or else
the trace executive will stop the flow with an error.
You may be surprised to learn that when a flow is initially
executed, nothing exists in the trace header. All trace header
entries are created one-at-a-time during initialization phase by
calls to the routine HDR_ADD (hdrAdd in C) or
HDR_STD_ADD (hdrAddStd in C). This is done primarily by
the input tool, which has special responsibility for creating all
of the header entries that existed when a dataset was written out

Other Docs

Known Problems

Overview of Trace Headers181

Developers Programming Guide

in a prior flow. But any tool can create new trace header entries.
The decision to create a new header entry is left entirely in the
hands of the applications programmers whenever some piece of
information should be passed downstream in the processing
flow to other tools.
Trace headers are passed from tool to tool in an array, but the
format of the individual entries can vary. Currently supported
formats are integer, real, double precision real (seldom used),
logical (seldom used), and character (stuffed into integers).
Each header entry can actually be an array of values, although
the length must be a whole number of words. Complicated
entities such as C structures can also be included in the trace
headers.
For convenience, the trace header is presented in the calling
arguments of the execution routine of every tool in both integer
AND real format to avoid the need for juggling the formats of
common trace header entries (the integer and real array are
equivalent within the toolcall routine and therefore occupy the
same memory).
Any tool may access the trace header entries that were added by
tools that occur earlier in the flow, but first the tool must know
where to find the entries and what their lengths and formats are.
This information is provided by the routine HDR_NAMINFO
(or hdrInfo in C), which returns the description, length, format,
and index of a trace header entry that was specified by name.
The routine HDR_INDINFO (or hdrIndexInfo in C) returns the
name, description, length, and format of a trace header entry
that was specified by index.
For programmers to communicate via trace headers, there must
be some agreement on what the names and definitions of
headers are. A standard list can be found in the file
$PROMAX_PORT_MISC/header.list. It is important to note
that this is not the list of headers that WILL exist during any
given flow, it is just a list of what certain headers will look like
if they DO exist. It is also important to remind yourself that the
order of the headers may be different between any two flows
and has nothing to do with the order that they appear in
header.list. The strict definition and use of all of the standard
header entries is presented in at the end of this chapter.
There is a subset of the standard trace header entries known as
the guaranteed headers that are always guaranteed to exist in a

Other Docs

Known Problems

Overview of Trace Headers182

Developers Programming Guide

flow (although their positions may vary). The names,


descriptions, and initial values of these headers are as follows:
Guaranteed Headers
Name

Description

Initial Values

SEQNO

Sequence number in ensemble.

(variable)

END_ENS

End-of-ensemble flag.

(variable)

EOJ

End-of-job flag.

(variable)

TRACENO

Trace number in seismic line.

(INULLpz)

TRC_TYPE

Trace type (data, aux, etc.).

(ILIVEpz)

TLIVE_S

Start time of live samples.

(0.0)

TFULL_S

Start time of full samples.

(0.0)

TFULL_E

End time of full samples.

(end of trace)

TLIVE_E

End time of live samples.

(end of trace)

LEN_SURG

Length of surgical mute taper.

(0.0)

TOT_STAT

Total static for this trace.

(0.0)

NA_STAT

Portion of static not applied.

(0.0)

AMP_NORM

Amplitude normalization factor.

(1.0)

TR_FOLD

Current trace fold.

(1.0)

SKEWSTAT

Multiplex skew static correction.

(0.0)

LINE_NO

Line number (hashed line name)*.

(hashed line name)

LSEG_END

Line segment end*.

(NLASTpz)

LSEG_SEQ

Line segment sequence number*.

(1)

The initial values are the values to which the headers are
initialized before some tool in the flow changes them. The
initial values for other (non-guaranteed) header entries must be
explicitly set in the execution phase by the tool that created
them. If the tool does not supply values, the Executive will
insert system-wide null values (INULLpz or RNULLpz in
FORTRAN and INULL and RNULL in C). This does not
necessarily indicate that a bug is present. For example, if new
header entries are created in one side of a branched flow, the
header entries will be defined in the other side of the flow, but
their values will be null.
In most cases, tools call HDR_NAMINFO (hdrIndex in C)
simply to find out where a standard header entry can be found
Other Docs

Known Problems

Overview of Trace Headers183

Developers Programming Guide

during the current flow. Since this use is widespread, the indices
of the standard headers is placed in a C structure or FORTRAN
COMMON block for easy access. Use of any of these function
requires inclusion of header.inc or cglobal.h. C programmers
should note that the array index values provided for the standard
headers in cglobal.h point to the same place in memory as the
FORTRAN common block and that the array index values are
appropriate for FORTRAN. A value of 1 must therefore be
subtracted from a standard header index value to be correctly
used in a ProMAX module written in C. The following macro is
defined in cpromax.h to aid in making code clear when using
standard headers in C:
#define STDHDR(x) ( (stdHdr->x)-1)

in which x is a member of the StdHdr structure defined in


cglobal.h, such as icdp.
Headers can be deleted from the flow via a two step process in
the Executive. In the init phase, the header entry is removed
using EX_HDR_DELETE, but no traces are processed until the
exec phase. HDR_DELETE_UPDATE actually deletes the trace
header in the exec routine.
The use of the trace header routines is not restricted to tools that
are linked into the exec. Stand-alone programs can use them in
exactly the same way.

Other Docs

Known Problems

Definition and Usage of Standard Header Entries184

Developers Programming Guide

Definition and Usage of Standard Header Entries


Header entries adhere to the following general rules:

All standard header entries are one word in length.

Some header entries should not be modified by the user


(except indirectly); they contain an asterisk in the
description. Think of these as read-only.

All times are in milliseconds.

All elevations are relative to sea level and should be


negative for headers such as the source elevation in marine
shooting.

It is the convention within ProMAX that a negative static


shifts data up (towards time 0.0), and a positive static shifts
data down (away from time 0.0).

Other standard header entries may be added in future


releases.

Alphabetical Reference of Trace Header Entries


The following table lists all currently defined trace header
entries in alphabetical order. Each entry is followed by its
sequential number.
Standard Trace Header Entries
AMP_NORM (13)

FB_PICK (64)

OFFSET (41)

SOU_H2OD (37)

AOFFSET (42)

FFID (19)

PR_STAT (62)

62) SOU_SLOC (25)

FK_WAVEL (71)

PS_STAT (61)

SOU_STAT (58)

FK_WAVEN (70)

REC_DEP (48)

SOU_X (31)

CDP( 22)

FNL_STAT (55)

REC_ELEV (30)

SOU_Y (32)

CDP_ELEV (40)

FRN_TRNO (8)

REC_H2OD (36)

CDP_NFLD (23)

FT_FREQ (72)

REC_NFLD (26)

SR_AZIM (49)

CDP_SLOC (27)

GEO_COMP (45)

REC_SLOC (24)

TFULL_E (67)

CDP_X (38)

ILINE_NO (50)

REC_STAT (57)

TFULL_S (66)

Other Docs

Known Problems

Definition and Usage of Standard Header Entries185

Developers Programming Guide

Standard Trace Header Entries (Continued)


CDP_Y (39)

LAST_TRC (4)

REC_X (28)

TLIVE_E (68)

CHAN (20)

LEN_SURG (69)

REC_Y (29)

TLIVE_S 965)

CR_STAT (60)

LINE_NO (7)

REPEAT (6)

TOT_STAT (53)

CS_STAT (59)

LSEG_END (9)

SEQNO (2)

TRACENO (5)

DEPTH (34)

LSEG_SEQ (10)

SEQ_DISK (17)

TRC_TYPE (12)

DISKITER (15)

NA_STAT (52)

SIN (11)

TRIMSTAT (63)

DMOOFF (73)

NCHANS (21)

SKEWSTAT (56)

TR_FOLD (14)

DS_SEQNO (16)

NMO_STAT (54)

SOURCE (18)

UPHOLE (35)

END_ENS (1)

OFB_CNTR (44)

SOU_COMP (46)

XLINE_NO (51)

EOJ (3)

OFB_NO (43)

SOU_ELEV (33)

Sequential Reference of Trace Header Entries


The tables on the following pages provide detailed descriptions
of the trace header entries in sequential order. The first table
describes system-related headers.
System-Related Headers
#

Header

Name

Type

Description

END_ENS

End-of-ensemble
flag*

integer

An ensemble is defined within the exec as


any collection of traces which (normally)
share the same primary sort key. Typical
examples are shot records, CDP gathers,
and common-receiver gathers. All of the
traces within an ensemble have ENS_ENS
set to false (NLASTpz), except the last
trace, where it is set to true (LASTTRpz).
The global variable MAXDTRz is the
maximum number of traces per ensemble
which must concur with the number of
contiguous traces that have ENS_ENS set to
NLASTpz.

SEQNO

Sequence number in
ensemble

integer

The sequence number of an individual trace


within the current ensemble.

Other Docs

Known Problems

Definition and Usage of Standard Header Entries186

Developers Programming Guide

System-Related Headers (Continued)


#

Header

Name

Type

Description

EOJ

End of job flag*

integer

The header entry EOJ is set to false


(NLASTpx) for every trace in a flow, except
under certain circumstances when complex
tools will receive a dummy trace (and trace
header) with EOJ set to true (LASTTRpz).
The dummy trace (and trace header) should
not be returned by the complex tool.

TRACENO

Trace number in
seismic line*

integer

An internal reference number that is


assigned by the system when the database is
initialized. It represents the unique
sequential trace number within the dataset
that is used to initialize the database.
TRACENO is undefined (and set to
INULLpz) after stack. The value of
TRACENO in the headers can be used to
reference the TRC ordered parameter file in
the parameter database if the global variable
ITRNO_VALIDz is true (=1).

REPEAT

REPEATED data
copy number

integer

Set by the Reproduce Traces processing


directive to reflect the copy number when
ensembles or all data is repeated.
(Subsequent processing frequently keys on
the REPEAT copy number for purposes of
comparison.) The Reproduce Traces
directive creates and sets the header
REPEAT_T when traces are repeated on an
individual basis.

LINE_NO

Line number (hashed


line name)*

integer

Represents the hashed line (or survey) name


to uniquely identify lines. (Individual
inlines and crosslines of a 3D survey are
part of the same survey and would have the
same LINE_NO.) LINE_NO is used in
operations that involve processing or
storage of data from multiple lines.
LINE_NO is over-ridden by the GeoQuest
IES Input tool to reflect the hashed line
name of the IES line. In that case, each
version number of each inline or crossline
receives a different LINE_NO.

FRN_TRNO

Foreign tracenumber-within line

integer

Used to store trace numbers from nonProMAX sources (such as the GeoQuest
IES System) to distinguish between traces
with a common LINE_NO.

Other Docs

Known Problems

Definition and Usage of Standard Header Entries187

Developers Programming Guide

System-Related Headers (Continued)


#

Header

Name

Type

Description

LSEG_END

Line segment end*

integer

A line segment is defined as a portion of the


data in a flow (including all of the data) that
should be processed as a continuous piece.
For example, if two different lines were read
into the same flow and a runmix were
applied, LSEG_END would be used to
ensure that data was not smeared from one
line into the next. LSEG_END is set to false
(NLASTpz) for all traces except the last
trace in a segment, where it is set to true
(LASTTRpz). When multiple lines are
imported via the GeoQuest IES Input tool,
the LSEG_END entry is set to true for the
last trace of each inline, crossline, time
slice, reconstruction cut, or 2D line.

LSEG_SEQ

Line segment
sequence number*

integer

The sequence number of the current line


segment in a processing flow. See
discussion of LSEG_END.

10

SIN

Source index number


(internal)*

integer

An internal reference number that is


assigned by the system when the database is
initialized. It represents the unique
sequential source number (including test
records, bad shots, etc.) within the dataset
that is used to initialize the database. The
value of SIN in the headers can be used to
reference the SIN ordered parameter file in
the parameter database if the global variable
IGEOM_MATCHz is true (=1).

11

TRC_TYPE

Trace type (data, aux,


etc.)

integer

Used most commonly to distinguish


between live traces, dead traces, and aux
traces. Other valid trace types include
dummy, time break, uphole, sweep, timing,
water break, and unknown (other).

Other Docs

Known Problems

Definition and Usage of Standard Header Entries188

Developers Programming Guide

System-Related Headers (Continued)


#

Header

Name

Type

Description

12

AMP_NORM

Amplitude
normalization factor

real

Defined as the average amplitude


normalization that has been applied to a
trace. For example, if a time-variant gain
increased the amplitude of each sample of a
trace by an average factor of 2.0, then it
should also multiply the value of
AMP_NORM by 2.0.

13

TR_FOLD

Actual trace fold

real

The number of traces that were summed to


form the current trace. TR_FOLD should
reflect the actual number of traces that were
summed, even if the theoretical fold is
different (in a process such as a weighted
stack). Note that TR_FOLD is NOT an
integer.

The following table describes input-related headers.


Input-Related Headers
#

Header

Name

Type

Description

14

DISKITER

Disk Data Input


iteration*

integer

If Disk Data Input (or Tape Data Input)


reads through the data multiple times (for
the benefit of tools such as autostatics),
DISKITER will reflect the current iteration
number.

15

DS_SEQNO

Input dataset
sequence number*

integer

If Disk Data Input or Tape Data Input are


reading multiple datasets, DS_SEQNO
reflects from which dataset a trace was
originally read.

16

SEQ_DISK

Trace sequence
number from disk

integer

Reflects the actual sequence number that a


trace was read from tape or disk, if the input
tool was Disk Data Input or Tape Data
Input. SEQ_DISK is unique for every input
trace, even in the case of multiple iterations
or multiple datasets. For example, if a
dataset containing 10 traces was read twice,
on the second iteration the first trace would
have SEQ_DISK equal to 11.

Other Docs

Known Problems

Definition and Usage of Standard Header Entries189

Developers Programming Guide

The following table describes geometry-related headers.


Geometry-Related Headers
#

Header

Name

Type

Description

17

SOURCE

Live source number


(usr-defined)

integer

Assigned by the user when the geometry is


written and installed, and represents a
number that the user wishes to use to refer
to a given record. SINs that are not assigned
a SOURCE number are not part of the live
data and have SOURCE set equal to
INULLpz.

18

FFID

Field file ID number

integer

The FFID of each SIN is extracted from the


headers of the field data and stored in the
parameter database for user reference. It is
largely unused because it (unfortunately)
cannot be assumed to be unique.

19

CHAN

Recording channel
number

integer

The CHAN of each trace is extracted from


the headers of the field data. CHAN is one
of the few headers for which the values from
the field data are trusted (although they can
be corrected if in error). CHAN numbers
can be used to reference the CHN ordered
parameter file in the parameter database if
the global parameter IGEOM_MATCHz is
true (=1).

20

NCHANS

Number of channels
of source

integer

The number of channels found within the


SIN to which the current trace belongs. This
is a seldom-used header entry.

21

CDP

CDP bin number

integer

Also known as the CMP, this is assigned by


whatever method the user chooses to do
binning. Note that the increment between
CDP numbers is allowed to be greater than
one. CDP numbers can be used to reference
the CDP ordered parameter file in the
parameter database if the global variable
IGEOM_MATCHz is true (=1).

22

CDP_NFLD

Number of traces in
CDP bin

integer

The fold of the CDP to which the trace


belongs (as defined by the global geometry
for the line). This is a seldom-used header
entry.

Other Docs

Known Problems

Definition and Usage of Standard Header Entries190

Developers Programming Guide

Geometry-Related Headers (Continued)


#

Header

Name

Type

Description

23

REC_SLOC

Receiver index
number (internal)*

integer

An internal reference number that is


assigned when the database is initialized. It
represents the unique sequential receiver
number within the dataset that is used to
initialize the database. The value of
REC_SLOC in the headers can be used to
reference the SRF ordered parameter file in
the parameter database if the global variable
IGEOM_MATCHz is true (=1).

24

SOU_SLOC

External source
location number

integer

Typically the field station number assigned


to sources. It may or may not be on a similar
station grid as the receivers. See
SRF_SLOC.

25

SRF_SLOC

External receiver
location number

integer

Typically the field station number assigned


to receiver positions. It may or may not be
on a similar station grid as the sources. See
SRF_SLOC.

26

REC_NFLD

Receiver fold

integer

The fold of the receiver gather at which the


current trace was recorded. This is a
seldom-used header entry.

27

CDP_SLOC

External CDP
location number

integer

Typically the field station number assigned


to CDP locations. It may or may not be on a
similar station grid as the sources and
receivers.

28

REC_X

Receiver X
coordinate

real

Always the actual coordinates, not the


receiver surfloc coordinates (if they are not
coincident, as in the case of marine 3D). All
coordinates are relative to reference
coordinates in the parameter database
(XREFz and YREFz).

29

REC_Y

Receiver Y
coordinate

real

See discussion of coordinates under


REC_X.

30

REC_ELEV

Receiver elevation

real

Should reflect the actual receiver elevation


and NOT the elevation of the surface at the
receiver X,Y (if the receiver is in a
borehole). For marine shooting, the
REC_ELEV should reflect the water depth
of the cable (and should be a negative
number). See further discussion of
coordinates under REC_X.

Other Docs

Known Problems

Definition and Usage of Standard Header Entries191

Developers Programming Guide

Geometry-Related Headers (Continued)


#

Header

Name

Type

Description

31

SOU_X

Source X coordinate

real

Always the actual coordinates, not the


coordinates of the nearest surfloc. All
coordinates are relative to reference
coordinates in the parameter database
(XREFz and YREFz).

32

SOU_Y

Source Y coordinate

real

See discussion of coordinates under


SOU_X.

33

SOU_ELEV

Source elevation

real

The elevation of the SURFACE at the X,Y


of the source (and does NOT reflect a hole
depth; see DEPTH), except that for marine
shooting SOU_ELEV should reflect the
water depth of the source (and should be a
negative number). See further discussion of
coordinates under SOU_X.

34

DEPTH

Source depth

real

The HOLE depth of the source. It should be


defined as 0.0 if no hole exists. DEPTH
should be 0.0 for marine shooting,
regardless of the water depth of the source.

35

UPHOLE

Source uphole time

real

The uphole time observed for a buried


source.

36

REC_H2OD

Water depth at
receiver

real

In marine shooting, the water depth at the


X,Y of the receiver (not routinely assigned).

37

SOU_H2OD

Water depth at source

real

In marine shooting, the water depth at the


X,Y of the source (not routinely assigned).

38

CDP_X

X coordinate of CDP

real

The bin center (not the center of mass of the


contributing traces). All coordinates are
relative to reference coordinates in the
parameter database (XREFz and YREFz).

39

CDP_Y

Y coordinate of CDP

real

See discussion of CDP_X.

40

CDP_ELEV

Elevation of CDP

real

Elevations of CDPs are problematic because


they are not specified and may be difficult to
interpolate. Historically, the elevation of
each CDP was taken as the elevation of the
nearest surfloc. The elevations of CDPs are
interpolated from the elevations of surflocs.

41

OFFSET

Signed sourcereceiver offset

real

The separation between source and receiver


for a given trace. If the source is at a lower
surfloc than the receiver then the offset is
positive, otherwise the offset is negative (the
convention is the same for 3D, although the
sign of OFFSET has little meaning).

Other Docs

Known Problems

Definition and Usage of Standard Header Entries192

Developers Programming Guide

Geometry-Related Headers (Continued)


#

Header

Name

Type

Description

42

AOFFSET

Absolute value of
offset

real

Literally abs(OFFSET). AOFFSET is a


convenience for users for specifying
parameters in some situations.

43

OFB_NO

Offset bin number

integer

The sequential bin number of offset bins


that are created during geometry
installation. OFB_NO can be used to
reference the OFB ordered parameter file in
the parameter database if the global variable
IGEOM_MATCHz is true (=1).

44

OFB_CNTR

Offset bin center

real

The offset of the center of an offset bin. See


discussion of OFB_NO.

The following table describes special geometry-related headers


for VSP/Crosshole, 3D, and multi-component recording.
Special Geometry-Related Headers
#

Header

Name

Type

Description

45

GEO_COMP

Geophone
component (x,y,z)

integer

For multi-component recording,


GEO_COMP is set to 1 for the vertical
component of motion, 2 for the east-west
(or inline for 3D) component of motion, and
3 for the north-south (or crossline for 3D)
component of motion.

46

SOU_COMP

Source component
(x,y,z)

integer

For multi-component shooting,


SOU_COMP is set to 1 for the vertical
component of motion, 2 for the east-west
(or inline for 3D) component of motion, and
3 for the north-south (or crossline for 3D)
component of motion.

47

SRC_DEP

Source depth below


surface

real

For borehole sources, SRC_DEP is the


depth of the source below the surface.

48

REC_DEP

Receiver depth below


surface

real

For borehole receivers, REC_DEP is the


depth of the receiver below the surface.

49

SR_AZIM

Source to receiver
azimuth

real

In 3D surveys, SR_AZIM is defined as the


azimuth FROM the source to the receiver,
clockwise, where 0.0 is north (or the Y axis
of the survey coordinate system). The units
are radians.

Other Docs

Known Problems

Definition and Usage of Standard Header Entries193

Developers Programming Guide

Special Geometry-Related Headers


#

Header

Name

Type

Description

50

ILINE_NO

3D inline number

integer

In 3D surveys, ILINE_NO is defined as the


number of the common inline to which a
trace belongs, where inlines and crosslines
are defined by the CDP binning, but the
inline direction is the direction of source
motion (if applicable). For example, in a
marine 3D survey, a single sail line with a
single streamer would tend to produce a set
of traces with a common INLINE_NO but
varying XLINE_NO.

51

XLINE_NO

3D crossline number

integer

In 3D surveys, XLINE_NO is defined as the


number of the common crossline to which a
trace belongs. See the discussion of
ILINE_NO.

The following table describes statics-related headers.


Statics-Related Headers
#

Header

Name

Type

Description

52

NA_STAT

Portion of static not


applied*

real

Statics are normally not fully applied


within ProMAX, except to the nearest
whole sample interval (for efficiency, and
to avoid the effects of multiple
interpolations). NA_STAT represents the
fractional sample portion of the static that
is not applied. NA_STAT is applied
during NMO in normal processing, but
must also be applied by any application
that is sensitive to small static shifts (such
as velocity analysis). The Apply Fraction
Statics tool can also be used for this
purpose, either by users or in a menu
macro process.

53

TOT_STAT

Total static for this


trace*

real

Represents the total static that SHOULD


be applied to the trace (minus NA_STAT).
TOT_STAT can be used to remove
previously applied statics.

54

NMO_STAT

NMO datum static


(do not apply)

real

The static that WAS applied to move from


NO datum (the original data) to the NMO
datum.

Other Docs

Known Problems

Definition and Usage of Standard Header Entries194

Developers Programming Guide

Statics-Related Headers (Continued)


#

Header

Name

Type

Description

55

FNL_STAT

Static to move to
final datum

real

The static that will be (or was) applied to


move from the NMO datum to the final
datum. This is typically applied after CDP
stack by the stacking tool.

56

SKEWSTAT

Multiplex skew static

real

The multiplex skew static (channel static


due to differential delays in older
recording systems) that is assigned during
input of the field data.

57

REC_STAT

Total static for


receiver

real

The portion of TOT_STAT that is


attributed to the receiver (from elevation
statics).

58

SOU_STAT

Total static for source

real

The total portion of TOT_STAT that is


attributed to the source (from elevation
statics).

59

CS_STAT

Corr. autostatics
source static

real

The source static that was computed by a


correlation autostatics program. It exists
for convenience during parameterization
of the process that applies autostatics
solutions to the data. CS_STAT was
dropped for Releases 5.0+ (see
AS_STAT).

60

CR_STAT

Corr. autostatics
recvr static

real

The receiver static that was computed by


a correlation autostatics program. See
also CS_STAT. CR_STAT was dropped
for Releases 5.0+ (see AR_STAT).

61

PS_STAT

Power autostatics
source static

real

The source static that was computed by a


power autostatics program. It exists for
convenience during parameterization of
the process that applies autostatics
solutions to the data. PS_STAT was
dropped for releases 5.0+ (see
AS_STAT).

62

PR_STAT

Power autostatics
recvr static

real

The receiver static that was computed by


a power autostatics program. See also
PS_STAT. PR_STAT was dropped for
releases 5.0+ (see AR_STAT).

63

TRIMSTAT

Trim static

real

The static that was computed by a trim


statics (non-surface consistent) program.

64

FB_PICK

First break pick time

real

The first break pick time of the trace.

Other Docs

Known Problems

Definition and Usage of Standard Header Entries195

Developers Programming Guide

The following table describes mute-related headers.


Mute-Related Headers
#

Header

Name

Type

Description

65

TLIVE_S

Start time of live


samples

real

The time of the first live (non-zero)


sample, if a top mute was applied. The
difference between TFULL_S and
TLIVE_S indicates the taper length of a
top mute, if one was applied. The value of
TLIVE_S does NOT enter the equation
for conversion from sample number to
time, or vice versa (it is NOT a recording
delay time).

66

TFULL_S

Start time of full


samples

real

The time of the first full untapered


sample, whose amplitude is totally
unaffected by a top mute if one was
applied. The difference between
TFULL_S and TLIVE_S indicates the
taper length of a top mute, if one was
applied.

67

TFULL_E

End time of full


samples

real

The time of the last full untapered sample,


whose amplitude is totally unaffected by a
bottom mute if one was applied. The
difference between TLIVE_E and
TFULL_E indicates the taper length of a
bottom mute, if one was applied.

68

TLIVE_E

End time of live


samples

real

The time of the last live (non-zero)


sample, if a bottom mute was applied.
The difference between TLIVE_E and
TFULL_E indicates the taper length of a
bottom mute, if one was applied.

69

LEN_SURG

Length of surgical
mute taper

real

The length of the taper of a surgical mute


if one was applied. If multiple surgical
mutes were applied with different taper
lengths (which is discouraged),
LEN_SURG will represent the last
applied.

Other Docs

Known Problems

Definition and Usage of Standard Header Entries196

Developers Programming Guide

The following table describes special applications-related


headers.
Special Applications-Related Headers
#

Header

Name

Type

Description

70

FK_WAVEN

Wavenumber of F-K
domain trace

real

The common wavenumber of a series of


amplitudes (a trace) after transformation to
the F-K domain.

71

FK_WAVEL

Wavelength of F-K
domain trace

real

The common wavelength of a series of


amplitudes (a trace) after transformation to
the F-K domain.

72

FT_FREQ

Frequency of F-T
domain trace

real

The common frequency of a series of


amplitudes (a trace) after conversion to the
F-T domain.

73

DMOOFF

Offset bin for DMO

real

The offset of a common offset bin that is


created for purposes common offset DMO.

The following table describes standard headers.


Standard Headers
#

Header

Name

Type

Description

74

AS_STAT

Autostatics source
static

real

The source static that was computed by an


autostatics program. It exists for
convenience during parameterization of the
process that applies autostatics solutions to
the data. AS_STAT replaces PS_STAT and
CS_STAT.

75

AR_STAT

Autostatics receiver
static

real

The receiver static that was computed by an


autostatics program. See also AS_STAT.
NOTE: AS_STAT replaces PR_STAT and
CR_STAT.

Other Docs

Known Problems

197

Developers Programming Guide

Parameter Tables

This chapter describes ProMAX parameter tables.

Topics covered in this chapter:

Overview of Parameter Tables

Structure of ProMAX Tables

Table Rules

Table Interpolation

X Values in Tables

Table Extrapolation

Table Subroutine Categories


Examples of Table Routines

Other Docs

Known Problems

Overview of Parameter Tables198

Developers Programming Guide

Overview of Parameter Tables


ProMAX parameter tables are useful for storing and
interpolating parameters, such as velocity functions, time
windows, mutes, etc. The general philosophy behind ProMAX
tables is that parameters, such as first break mute times, are
stored on disk and retrieved into memory when they are needed.
Interpolation of the parameters can then be done as needed by
the ProMAX parameter interpolation routines. For example,
suppose a ProMAX user picks mute times on a set of shot
records. Those mute times will be stored in a ProMAX table on
disk. When the user wants to apply those mutes, the mute times
are read into memory and traces for which no mute times were
specifically picked will be interpolated by the ProMAX
interpolation routines. The application of the routines is, of
course, under the control of the programmer.

Structure of ProMAX Tables


A ProMAX table is a framework for storing information at a
location within a 3-dimensional volume. The following figure
shows a 3-dimensional volume with axes X1, X2, and Y. A
black dot marked P is a location at which information can be
stored.

X1

X2
P

A three dimensional volume with point P


where data can be stored

Other Docs

Known Problems

Overview of Parameter Tables199

Developers Programming Guide

A consistent terminology is used to describe locations within


ProMAX tables. As in the previous figure, a location within the
table is described in terms of the X1, X2, and Y axes. Data
stored at a point within the table is referred to as a Z value.
Therefore, a ProMAX table is a description of Z(X1, X2, Y).
In fact, any number of Z values can be stored at an X1, X2, Y
location, so this description might be more accurately be written
as Z[ ](X1,X2, Y), where the [ ] indicates that a vector of Z
values can be stored.
An example use of a ProMAX table would be in the storage of
NMO functions for a 3D seismic survey. Suppose that NMO
functions had been picked for several CDP bin locations in the
survey, as in the following figure. These functions could be
stored in a ProMAX table using the X1, X2 coordinates to
describe the spatial location of the CDP bins, the Y axis to
describe the times at which velocities had been picked, and the
Z values to describe the velocity at each picked time. In this
case there would only be one Z value at each (X1, X2, Y)
location.
X1

Surface locations of
CDP bins
X2

Y
Marks a time at which a velocity is stored

Velocity functions stored at CDP bin locations in a table

Other Docs

Known Problems

Overview of Parameter Tables200

Developers Programming Guide

Table Rules
Some important rules about the structure of tables are as
follows:.

The number of X1, X2 locations in a table can vary from


table to table and can also be changed within a table (points
can be added and deleted).

There can be any number of Y locations at any X1, X2


location.

The number of Z values stored at X1, X2, Y locations is


fixed for a table.

Table Interpolation
The following figure shows a set of scattered points in the
X1, X2 plane of a ProMAX table. These points might be
surface locations in a 3D seismic survey or points in any other
reference frame that is appropriate for a ProMAX table.
Assume that a set of parameters have been picked for each of
these points; in other words, there are Z values stored at Y
locations at each point in the plane. Also in the plane is a point
marked P, which is at coordinates (X1p, X2p). No parameters
have been picked at P; the goal of interpolation will be to
approximate values for Z(X1p, X2p, Y) based on the points that
are near to P. The question that is then raised is, Which of the
points that are near to P should be used for the interpolation?

Other Docs

Known Problems

Overview of Parameter Tables201

Developers Programming Guide

X1

P(X1p, X2p)

X2

Points scattered in the X1, X2 plane of a ProMAX table


The answer to this question in ProMAX tables begins by
dividing the X1, X2 plane into a set of triangles, as shown in the
following figure.
The triangles used to divide the X1, X2 plane are called
Delaunay triangles, which is a unique set of triangles for a
given set of points that comes as close as possible to making all
of the triangles equilateral. The Delaunay triangles method tries
to avoid creating long skinny triangles because they make
interpolation inaccurate.

Other Docs

Known Problems

Overview of Parameter Tables202

Developers Programming Guide

X1

X2

Delaunay triangles divide the X1, X2 plane


of a ProMAX table
Suppose that interpolation is needed for a Z value at coordinates
(X1p, X2p, Y). The table interpolation routines first determine
which triangle contains P. The following figure shows the point
P in the X1, X2 plane along with the triangle that contains P.
The vertices of the triangle in the figure are A, B, and C, and
have X1, X2 coordinates (X1a,X2a), (X1b, X2b), and
(X1c, X2c), respectively. The Y axis extends downward from
the X1-X2 plane.
The next step in the interpolation of Z(X1p, X2p, Y) is to
linearly interpolate values of Z(X1a, X2a, Y), Z(X1b, X2b, Y),
and Z(X1c, X2c, Y) along the Y axis of the respective points of
A, B, and C. Points of known Z(X1, X2, Y) are shown as dark
circles in the figure and interpolated points are shown as open
circles.

Other Docs

Known Problems

Overview of Parameter Tables203

Developers Programming Guide

X1
B
X2

P
A

(X1a, X2a, Y)

Interpolated Z(X1, X2, Y )


Known Z(X1, X2, Y)

Interpolation of Z(X1, X2, Y) along the Y axis from the


triangle vertices A, B, and C
A plane can now be formed in X1, X2, Z space that contains the
points (X1a, X2a, Za), (X1b, X2b, Zb), and (X1c, X2c, Zc), as
is shown in the following figure. The value of Z(X1p, X2p, Y)
is then calculated at the point where the line parallel to Y that
intersects P also intersects the plane.

Other Docs

Known Problems

Overview of Parameter Tables204

Developers Programming Guide

X1
B
X2

P
A

(X1a, X2a, Z)

Interpolated (X1, X2, Z)


Vertex of triangle

Interpolation of (X1p, X2p, Z) from nearby points

X Values in Tables
The primary use of tables is for interpolation of parameters in
2D and 3D seismic data processing. The parameters that are
interpolated are frequently associated with some integer
ensemble number, such as CDP bin number or Source Index
Number (SIN). Both CDP and SIN can be associated with
spatial locations on the ground such as the CDP bin location or
the source location.
When there is a 1-to-1 mapping between ensemble number and
spatial coordinates, ProMAX table information can be referred
to by either ensemble number or by the X1, X2 coordinates. For
example, interpolation of parameters can be done with the
subroutine tblInterpXY using just the ensemble number, which
is referred to as X in the calling arguments. The interpolation

Other Docs

Known Problems

Overview of Parameter Tables205

Developers Programming Guide

can also be done with the routine tblInterpZ which uses X1, X2
pairs to describe the location at which interpolation is to be
done. Tables can be built and used via either or both methods. In
the internals of the code, the tables are referenced by the X1, X2
values, so mapping goes on between X and X1, X2.

Table Extrapolation
The preceeding discussion of value interpolation assumed that
there were points bracketing the location for which
interpolation was being done. In cases where a value is beyond
the limit of known table values, the new value must be
extrapolated from values within the table.
Extrapolation in the X1, X2 plane: The rules for extrapolation
in the X1, X2 plane are simple. If interpolation is requested for
an X1, X2 location outside the table, then the point on the table
that is nearest the requested point is found. The Y and Z values
at the requested point are set equal to the Y and Z values of the
nearest point. Note that the nearest point might be (probably
will be) an interpolated point. See the following figure.

X1
Requested point

Nearest point on table

X2

indicates a point in the table

The nearest point on the table is used to set values at


exterior points
Extrapolation along Y: Extrapolation in Y can be done either
by setting the Y value equal to the nearest defined Y value or by
linearly interpolating based on the slope between the last two
Other Docs

Known Problems

Overview of Parameter Tables206

Developers Programming Guide

defined points along Y. The method of extrapolation is set by


running the routine tblSetExtrap in C or TBL_SET_EXTRAP
in FORTRAN.

Table Subroutine Categories


Four general categories of table subroutines are available to the
ProMAX programmer:

table initialization and creation routines to input/output


data to/from disk files

table value editing routines for adding, deleting, and


changing table values

routines to find values at locations in the table and to find


global minimum and maximum values

interpolation routines

A set of routines in each of these categories that be called from


the C programming language, with an analogous set for
FORTRAN (with one important exception which is discussed
later). Use the command
aman -k tbl

to print a list of all of the ProMAX table routines and a brief


description of their purpose.
In order to access the on-line manual pages for ProMAX
routines, you must have the path to PROMAX_HOME/port/bin,
where PROMAX_HOME is the path name where the ProMAX
directory structure is installed. To see documentation on an
individual table routine, such as tblCountX, type
aman tblCountX.

This provides an explanation of calling arguments, along with a


description of the function of the subroutine.
If you look at a list of the table routines you may notice that
there is a large number of routine names which begin with the
letters tbl or TBL. Many of these routines are used for working
with data that can be stored in the 2D tables. Many of the tbl
routines actually call other routines that work directly with data
Other Docs

Known Problems

Overview of Parameter Tables207

Developers Programming Guide

in the underlying 3D data structure. These direct access routines


have names that begin with tb3. Direct access to the underlying
3D data structure can be gained by first calling the routine
tblFetchTb3 from C, which returns a pointer to the location of
the table which can be used with the tb3 routines. There is not a
set of FORTRAN routine names that begin with the letters tb3,
and there currently is no direct access to the underlying C
structures from FORTRAN. Direct access to the underlying C
structures is not necessary, however, since FORTRAN routines
are provided that access the tables via X1 and X2 arguments.

Other Docs

Known Problems

Examples of Table Routines208

Developers Programming Guide

Examples of Table Routines


One of the best ways to demonstrate the use of the ProMAX
table routines is through example code. The following examples
are in both FORTRAN and C. You will not miss anything if you
read the code examples in one language and not in the other.
Both sets of code accomplish the same tasks; a discussion
accompanies each code fragment.

FORTRAN Code Examples


This section contains two examples of FORTRAN table
routines.

Example 1
The first FORTRAN example comes from the subroutine
INIT_AMP_RATIO, which can be found in the example source
code amp_ratio.f. This code is actually altered slightly from the
original amp_ratio.f to minimize code that is extraneous to this
discussion.
In this example, a table that holds start and end times for a time
gate is read from the database. The table DB_TBL_GET
allocates memory for the table and loads the table values into
that memory. The routine returns an argument called
ITBL_HANDLE. This is a numerical value that should not be
changed, as it is the memory location of the table. This value of
ITBL_HANDLE is the way in which the table is referenced.
Any subroutines that make use of the table will pass
ITBL_HANDLE to the routine so that the table can be uniquely
identified.
C ..... Get the name of the time gate file from the menu
CALL EX_CGETPARM( 'GATENAME', 1, CGATENAME,
NCHARS )
C ..... Get the gate table from the database
CALL DB_TBL_GET( 'GAT', CGATENAME, ITBL_HANDLE,
IERR )
IF ( IERR .NE. 0 ) THEN
CALL REPORT_PROMAX_ERR( IERR )
CALL EX_ERR_FATAL(
&
'Cannot open time gate ' //CGATENAME )
ENDIF

Other Docs

Known Problems

Examples of Table Routines209

Developers Programming Guide

C ......Get info on the gate table


CALL TBL_INFO( .TRUE., ITBL_HANDLE, CPRIM_KEY,\
CSCND_KEY,
&
CZ_DESC, CTABLE_DESC, IDUMMY(1), IDUMMY(2),\
IDUMMY(3),
&
NTIMES, RDUMMY(1), RDUMMY(2), RDUMMY(3),\
RDUMMY(4),
&
RDUMMY(5), RDUMMY(6) )
C ......There had better be two time values (upper and\
lower gate)
IF ( NTIMES .NE. 2 ) CALL EX_ERR_FATAL(
&
'Invalid gate (must have an upper and lower\
gate)' )
C ......We will need the index of the primary and\
secondary key
CALL HDR_NAMINFO( CPRIM_KEY, CDESC_DB, LENGTH,\
IFORMAT_PKEY,
&
IH_PKEY, IERR )
IF ( IERR .NE. 0 ) CALL EX_ERR_FATAL(
&
'The primary key of the time gate\
(' //CPRIM_KEY
&
//') is not in the header' )
CALL HDR_NAMINFO( CSCND_KEY, CDESC_DB, LENGTH,\
IFORMAT_SKEY,
&
IH_SKEY, IERR )
IF ( IERR .NE. 0 ) CALL EX_ERR_FATAL(
&
'The secondary key of the time gate\
(' //CSCND_KEY
&
//') is not in the header' )

After the table is created with DB_TBL_GET, information


about the table is retrieved from the table by use of the program
TBL_INFO. You can investigate the other calling arguments for
this subroutine by typing aman tbl_info.
Most of the arguments returned in this code are dummy
variables. The only information about the table that is needed is
the primary and secondary keys on which the table is based (the
X and Y axes of the table) and the number of Z values in the
table, represented here as the argument NTIMES.
After checking to be sure that there are only two times, a start
and end time, stored in the table, the code gets the trace header
index and format of the primary and secondary keys by use of
the header routine called HDR_NAMINFO.
This piece of code came from the initialization subroutine in
amp_ratio. The table is read into memory only one time. It will
be preserved there until it is intentionally closed by the

Other Docs

Known Problems

Examples of Table Routines210

Developers Programming Guide

programmer, or until the routine fails through EX_ERR_FATAL


or some other means of stopping execution.
Next we see where the table that is created is used in the
subroutine EXEC_AMP_RATIO, which can also be found in
the example code file amp_ratio.f. The subroutine
EXEC_AMP_RATIO is given one data trace at a time to
process, and the time gate is interpolated for that trace. The
trace for which the time gate is interpolated is referred to as the
current trace in the following discussion. The subroutine
EX_GET_REALKEY is used to get a floating point
representation of the primary key value (the tables X axis
value) and of the secondary key value (the tables Y axis value).
This is because the table interpolation routines only work with
floating point values.
FLOAT PKEYVAL, SKEYVAL, TGATE(2)
INTEGER IERR
C ......... Interpolate the gate times from the table
CALL EX_GET_REALKEY( RTHDR(IH_PKEY),
IFORMAT_PKEY,\ PKEYVAL )
CALL EX_GET_REALKEY( RTHDR(IH_SKEY),
IFORMAT_SKEY,\ SKEYVAL )
CALL TBL_INTERP_XY( ITBL_HANDLE, PKEYVAL,\
SKEYVAL,TGATE, NOINTERP )

The routine TBL_INTERP_XY is called next; it interpolates


the time gate values from the table. Note that the calling
arguments include ITBL_HANDLE, which was passed from
INIT_AMP_RATIO through the common block in
amp_ratio.inc. The input arguments PKEYVAL and SKEYVAL
are the X and Y locations in the table at which interpolation of
the time gate values will be done. The routine
TBL_INTERP_XY returns the start and end time of the time
gate TGATE. It also returns the value of NOINTERP, which is
used in control of extrapolation.
We could also do the interpolation by direct use of the X1, X2
coordinates. This is only desirable if X1 and X2 are readily
available through trace headers, as occurs in the following code:
C ......... Get the X1,X2 coordinates from the headers\
and interpolate
X1 = RTHDR( IH_X1 )
X2 = RTHDR( IH_X2 )
CALL TBL_INTERP_Z( ITBL_HANDLE, X1, X2, 2, 1,\
SKEYVAL, SKEYVAL,
&
TIMES, NOINTERP )

Other Docs

Known Problems

Examples of Table Routines211

Developers Programming Guide

Example 2
In order to create a new ProMAX table, the user must have first
created a table name while working in the user interface. The
program that will fill the table with data must get the name of
the table into which the table data will be written. The name of
the table is acquired with the routine EX_CGETPARM in the
INIT_ subroutine, as is shown in the previous example. Note
that the name of the table that is acquired from a call to
EX_CGETPARM is the 8-character label (or hash name) which
is generated from the table description input by the user. In
order write to the table, you must find the descriptive name by
use of the routine TBL_DESC_FROM_DB. Memory must then
be allocated for the table, which is done using
TBL_ALLOCATE.
The following code shows a working ProMAX module which
writes a new velocity table to the database.
C----------------------------------------------------------------------------C
C
Description:
C
Standard initialization routine
C
C
Output arguments:
C
LEN_SAVE - number of 4-byte words to save
for\ re-entrancy
C
ITOOLTYPE - processing tool type
C
C----------------------------------------------------------------------------SUBROUTINE INIT_DUMMYA( LEN_SAV, ITOOLTYPE )
#include "dummya.inc"
INTEGER LEN_SAV, ITOOLTYPE
INTEGER NCHARS, IERR
C ..... declare variable for user-given descriptive table
name
CHARACTER CTABLE_DESC*128
C ..... declare variable for lable or name created from\
CTABLE_DESC
CHARACTER CHASH_NAME*8
C ..... Call for the input parameter by name. Note the\
padding in the
C ..... character constant. It is the programmers\
responsibility to
C ..... provide the correct type of return argument.

Other Docs

Known Problems

Examples of Table Routines212

Developers Programming Guide

CALL EX_CGETPARM( 'VEL_FILE', 1, CHASH_NAME,\


NCHARS )
C ..... Get the table description from the hash name.\
The description is
C ..... needed both when the table is allocated and\
written to the data base
CALL TBL_DESC_FROM_DB( 'VEL', CHASH_NAME,\
CTABLE_DESC, IERR );
IF( IERR .NE. 0 ) THEN
CALL EX_ERR_FATAL('Table description not\
found.')
END IF
C ..... Allocate space for a new table
CALL TBL_ALLOCATE( ID_TABLE, 1, 'CDP', 'VEL',\
'TIME',
&
CTABLE_DESC, IERR )
C ..... Set the number of words that need to be saved\
for re-entrancy.
C ..... Note that LENSAVED declared within the include
file, hopefully
C ..... to avoid oversights
LEN_SAV = LENSAVED
C ..... Set the tool type to simple (one trace in, one\
trace out)
ITOOLTYPE = ISIMPLEpz
RETURN
END

C----------------------------------------------------------------------------C
C
Description:
C
Standard execution routine
C
C
Input/output arguments:
C
TRACE - array of trace samples
C
ITHDR - trace header (as integer)
C
RTHDR - trace header (as floating point)
C
C----------------------------------------------------------------------------SUBROUTINE EXEC_DUMMYA( TRACE, ITHDR, RTHDR )
#include "dummya.inc"
REAL TRACE(NUMSMPz), RTHDR(NTHz)
REAL XVALUE, YVALUE, ZVALUE
INTEGER ITHDR(NTHz), IERR

IF ( CLEANUPz ) THEN
CALL TBL_TO_DATABASE( ID_TABLE, 'VEL', IERR )

Other Docs

Known Problems

Examples of Table Routines213

Developers Programming Guide

C ......... We don't want control to pass into the main\


body
RETURN
ENDIF
C ..... Add values to the table
XVALUE = 1.0;
YVALUE = 2.0;
ZVALUE = 3.0;
CALL TBL_ADD_XY( ID_TABLE, XVALUE, YVALUE, \
ZVALUE )
RETURN
END
C----------------------------------------------------------------------------C
Include file for DUMMYA
C----------------------------------------------------------------------------IMPLICIT NONE
#include "global.inc"
COMMON /SAVED_PARMS/ SAVE1z, ID_TABLE
INTEGER ID_TABLE, LENSAVED
C ..... Specify the number of variables to save.
DATA LENSAVED /2/
C ..... ID_TABLE memory handle for the velocity table

C Code Examples
This section contains two examples of C table routines.

Example 1
The first C example comes from the subroutine
init_amp_ratio_, which can be found in the example source
code ampRatio.c. This code is actually altered slightly from the
original ampRatio.c to minimize code that is extraneous to this
discussion.
In this example, a table that holds start and end times for a time
gate is read from the database. The table database allocates
memory for the table and loads the table values into that
memory. The routine returns a (void*) pointer to the table
location. The returned value is the way in which the table is
referenced. Any subroutines that make use of the table require
Other Docs

Known Problems

Examples of Table Routines214

Developers Programming Guide

this pointer value as an argument to allow the table to be


uniquely identified.
char *tblName, *xKeyName, *yKeyName;
void* tblPointer;
int
xIndex, yIndex;
/* Get the name of the time gate file from the menu */
exParGetString( "TBLNAME", tblName );
/* Get the gate from the database */
tblPointer = tblFromDatabase( "MUT", tblName );
if( tblPointer == NULL ){
exErrFatal("Cannot open time gate");
}
/* Get the name of X and Y axes of the table and the\
header indicies */
xKeyName = tblDescX( tblPointer );
yKeyName = tblDescY( tblPointer );
if( xKeyName == NULL || yKeyName == NULL ){
exErrFatal("Table X or Y header names do not exist\
in the dataset.");
}
xIndex = hdrIndex( xKeyName);
yIndex = hdrIndex( yKeyName);
/* Get the number of Z values (times), it should be 2 */
if( tblCountZ( tblPointer ) != 2 ){
exErrFatal("Time gate must have a start and end\
time.");
}

After the table is read into memory, the names of the X and Y
axes are retrieved using tlbDescX and tblDescY. The header
array indices for the X and Y keys are also retrieved using
hdrIndex. The number of Z values (times) is checked using
tblCountZ to be sure that it is exactly two (a start and end time),
otherwise this would be an invalid table for this operation.
This piece of code came from the initialization subroutine in
ampRatio.c. The table is read into memory only one time. It
will be preserved there until it is intentionally closed by the
programmer, or until the routine fails through exErrFatal or
some other means of stopping execution.
Next we see where the table that is created above is used in the
subroutine exec_amp_ratio, which can also be found in the
example code file ampRatio.c. The subroutine exec_amp_ratio
is given one data trace at a time to process, and the time gate is

Other Docs

Known Problems

Examples of Table Routines215

Developers Programming Guide

interpolated for that trace, which is referred to as the current


trace in the following discussion.
In the following code segment, floating point representations of
the primary and secondary key values are found (the table
interpolation routines only work with floating point values for X
and Y coordinates) and the time gate is interpolated. The values
of xKeyName, etc., from init_amp_ratio were passed to
exec_amp_ratio through the external parms structure.
float pkeyVal, skeyVal, tgate[2];
int iErr;
/* get the primary and secondary key values */
pkeyVal = rthdr[xIndex];
if( hdrFormat( xKeyName ) == HDRINT ) pkeyVal =\
(float)ithdr[xIndex];
skeyVal = rthdr[yIndex];
if( hdrFormat( yKeyName ) == HDRINT ) skeyVal =\
(float)ithdr[yIndex];
/* interpolate the time gates */
iErr = tblInterpXY( tblPointer, pkeyVal, skeyVal,\
tgate );
if( iErr != 0 ){
exErrFatal("Error interpolating time gate.");
}

The routine tblInterpXY is called which interpolates the time


gate values from the table. tlbInterpXY also returns an error
code to iErr which must be 0, else the interpolation could not be
done for some reason.
We could also do the interpolation by direct use of the X1, X2
coordinates. This is only desirable if X1 and X2 are readily
available through trace headers, as occurs in the following code:
/*. Get the X1,X2 coordinates from the headers and
interpolate */
x1 = rthdr[ indexX1 ];
x2 = rthdr[ indexX2 ];
iErr = tblInterpZ( tblPointer, x1, x2, 1, 1, 1,\
&skeyVal, tgate );
if( iErr != 0 ){
exErrFatal("Error interpolating table value.");
}

Other Docs

Known Problems

Examples of Table Routines216

Developers Programming Guide

Example 2
In order to create a new ProMAX table, the user must have first
created a table name while working in the user interface. The
program that will fill the table with data must get the name of
the table into which the data will be written. The name of the
table is acquired with the routine exParGetString in the init_
subroutine, as shown in the previous example. The name of the
table that is acquired from a call to exParGetString is the 8character label (or hash name) which is generated from the table
description input by the user. In order write to the table, you
must find the descriptive name by use of the routine
tblDescFromDatabase. Memory must then be allocated for the
table, which is done using tblAllocate.
The following code shows a working ProMAX module which
writes a new velocity table to the database.
/* This example shows how to create a new table in the
database. */
/* The example if for adding a new RMS velocity table */
/* include ProMAX prototypes and globals */
#include "cpromax.h"
#include "cglobal.h"
/* define saved parameters */
BEGINPARMS
void *tblPntr;
ENDPARMS(parms)
/***-----------------------------------------------------------------Description:
Standard initialization routine
output arguments:
len_save - number of 4-byte words to save for\
re-entrancy
itooltype - processing tool type
--------------------------------------------------------------------***/
void
init_dummya_(int *len_sav, int *itooltype)
{
/* local variabes */
char *tblDesc; /* user-given descriptive table name
*/

Other Docs

Known Problems

Examples of Table Routines217

Developers Programming Guide

char *tblHashName; /* 8-character name created from\


tblDesc */
/* get the table hash name from a menu, this is an\
8-character */
/* string created from the original user-given table\
name */
exParGetString("VEL_FILE", &tblHashName );
/* get the table description from the hash name. The\
description is */
/* needed when the table is written to the data base */
tblDesc = tblDescFromDatabase( "VEL", tblHashName );
if( tblDesc == NULL ){
exErrFatal("Table description not found.");
}
/* allocate space for a new table, one z value per
x1,x2,y location */
parms->tblPntr = tblAllocate( 1, "CDP", "TIME",\
"VEL", tblDesc );
if( parms->tblPntr == NULL ){
exErrFatal("couldnt allocate space for a new\
table.");
}
/* Set the number of words that need to be saved for
re-entrancy. */
*len_sav = NPARMS (parms);
/* set the tool type */
*itooltype = ISIMPLE;

/*******************************************************
**************
*
*
Description:
*
Standard execution routine
*
*
Input/output arguments:
*
trace - array of trace samples
*
ithdr - trace header (as integer)
*
rthdr - trace header (as floating [point)
*
********************************************************
**************/

void exec_dummya_(float *trace, int *ithdr, float *rthdr)


{
float xValue, yValue, zValue;
int
iErr;
if( globalRuntime->cleanup ){

Other Docs

Known Problems

Examples of Table Routines218

Developers Programming Guide

/* .. The last trace has been processed, write the table


to the database */
tblToDatabase( parms->tblPntr, "VEL" );
return;
}
/* add values to the table */
xValue = 1.0;
yValue = 2.0;
zValue = 3.0;
tblAddXY( parms->tblPntr, xValue, yValue, &zValue );

Other Docs

Known Problems

219

Developers Programming Guide

Memory Management

This chapter describes memory-related routines within the


ProMAX system.

Topics covered in this chapter:

Other Docs

Overview of Memory Management


C Memory Management
Multi-dimensional Arrays
Multi-Dimensional Routine Names
FORTRAN Memory Management
Big Vector Routines

Known Problems

Overview of Memory Management220

Developers Programming Guide

Overview of Memory Management


There are three groups of memory-related routines within the
ProMAX system. The first group of routines are to be called
from the C programming language and are for allocating multidimensional arrays in single calls. The second group of routines
is for use in pseudo-dynamic memory allocation in FORTRAN.
The third group of routines is used for manipulating arrays that
are larger than the available memory. In this case disk space is
used as slow memory for data storage. All three groups of
routines are discussed separately in the following sections.
The environmental variable $PROMAX_HOME is used in this
document. This variable is equal to the path name of the
directory at which the ProMAX directory tree is installed on
your system. The default installation directory is /advance.

Other Docs

Known Problems

C Memory Management221

Developers Programming Guide

C Memory Management
The C programming language provides a number of very
flexible capabilities for handling different kinds of data. C
structures, for example, allow associated data to be placed in a
data object that can be named and passed from one routine to
another. Because of the flexibility of C, there are several general
types of memory management routines within ProMAX which
handle different collections of data. The types of data
collections which are handled include:

multi-dimensional arrays
deques
heaps
queues
stacks

These data types and the memory management routines that


handle them are discussed in the following sections.

Multi-dimensional Arrays
The array memory management functions are intended to
simplify manipulation of multi-dimensional arrays in scientific
programming in C. These functions are useful only because true
multi-dimensional arrays in C cannot have variable dimensions
(as in FORTRAN). For example, the following function IS NOT
valid in C:
void badFunc(a,n1,n2)
float a[n2][n1];
{
a[n2-1][n1-1] = 1.0;
}

However, the following function IS valid in C:


void goodFunc(a,n1,n2)
float **a;
{
a[n2-1][n1-1] = 1.0;
}

Therefore, the memory functions do not allocate true


multi-dimensional arrays, as described in the C specification.

Other Docs

Known Problems

C Memory Management222

Developers Programming Guide

Instead, they allocate and initialize pointers (and pointers to


pointers) so that, for example,
a[i2][i1]

behaves like a 2D array.


The array dimensions are numbered, which makes it easy to add
functions for arrays of higher dimensions. In particular, the 1st
dimension of length n1 is always the fastest dimension, the 2nd
dimension of length n2 is the next fastest dimension, and so on.
Note that the 1st (fastest) dimension n1 is the first argument to
the memory functions, but that the 1st dimension is the last
subscript in a[i2][i1].
The allocation of pointers to pointers implies that more storage
is required than is necessary to hold a true multi-dimensional
array. The fraction of the total storage allocated that is used to
hold pointers is approximately 1/(n1+1). This extra storage is
unlikely to represent a significant waste for large n1.
The memory management functions are significantly different
from similar functions described by Press et al in Numerical
Recipes in C, 1988particularly the following functions:

allocate arrays of arbitrary size elements


allocate contiguous storage for arrays
abort if allocation fails (unlike malloc)
do not provide arbitrary lower and upper bounds for arrays

Contiguous storage enables an allocated multi-dimensional


array to be passed to a C function that expects a onedimensional array. For example, to allocate and zero an n1 by
n2 two-dimensional array of floats, one could use
a = memAlloc2(n1,n2,sizeof(float));
zeroFloatArray(n1*n2,a[0]);

where zeroFloatArray is a function defined as


void zeroFloatArray(int n, float *a)
{ int i;
for (i=0; i<n; i++){
a[i] = 0.0;
}
}

Other Docs

Known Problems

C Memory Management223

Developers Programming Guide

Internal error handling and arbitrary array bounds, if desired,


should be implemented in functions that call the functions
defined below, with the understanding that these enhancements
may limit portability.

Multi-dimensional Routine Names


There are three sets of routines for handling multi-dimensional
arrays which can be identified by their names:

_mem
alloc
deque

The following sections describe these routines.

_mem
Routine names that begin with _mem have the name and line
number of the subroutine from which the _mem routine is being
called as calling arguments. If a memory error occurs, then the
subroutine and line number at which the error occurred will be
reported. The _mem routines have _memFree routines to free
the allocated memory.

alloc
Routine names that begin with alloc allocate multi-dimensional
arrays without error messages if there is a memory error (such
as if there is insufficient memory to satisfy the request). Routine
names that begin with ealloc are routines that call the alloc
routines, but they also provide error messages and a graceful
exit from the program if there is a memory allocation error.
Memory allocated with alloc and ealloc routines is freed using
the routine names that begin with free.

deque
Routine names that begin with deque are used for creating and
using a deque. A deque is a double-ended queue; in other
words, entries can be inserted and extracted from either end of
the queue.

Other Docs

Known Problems

C Memory Management224

Developers Programming Guide

Heap
Routine names that begin with the heap are used for creating
and using a heap. A heap is an ordered, balanced binary tree in
which the value of the node at the root of any subtree is less
than or equal to the value of either of its children. There is no
implied relationship between siblings. Because the tree is
balanced, an array implementation is possible. With the array
implementation, if the root of a subtree is at position i in the
array, the left child will be at position 2*i+1 and the right child
at position 2*i+2, for a tree beginning with the (C convention)
position 0.
A heap can contain any size data type, but all the data in any
heap must be the same size and should be the same type.

Linked Lists
Routine names that begin with the ll are used for creating and
using linked lists. A singly-linked list is a data structure in
which the memory location of the next data node is stored as
part of the current data node.

Priority Queues
A priority queue is a limited interface to a heap data structure. It
is defined as a queue because as items are added, they are
automatically positioned appropriately, depending on their
relative priority to items already in the queue. Items are always
deleted from the front of a priority queue. This implementation
is based upon a heap data structure.
A priority queue can contain any size data type, but all the data
in any priority queue must be the same size, and should be the
same type.

Promax
Routine names that begin with promax are memory allocation,
freeing, and reallocation routines for 1D arrays. The routines
also provide the benefit of checking the ends of arrays to be
certain that they have not been overwritten. This is
accomplished through use of the routine promaxCheckmem().

Other Docs

Known Problems

C Memory Management225

Developers Programming Guide

Queues
Routine names that begin with queue are for allocation and use
of standard queues. The first entry input to the queue is the first
entry taken from the queue.

Memory reallocation
Routine names that begin with realloc are for use with the alloc
and ealloc routines. These routines allow arrays that were
allocated with alloc and ealloc routines to be resized.

Stack
Routine names that begin with stack are for allocation and
manipulation of data in a stack. A stack is a data structure in
which the last data value input to the structure is the first one
that can be retrieved from the structure.

References
Esakov, J., and Weiss, T., 1989. Data structures: an advanced
approach using C. Prentice Hall, p. 260-267.
Sedgewick, R., 1990. Algorithms in C. Addison-Wesley,
p. 148-156.

Other Docs

Known Problems

FORTRAN Memory Management226

Developers Programming Guide

FORTRAN Memory Management


The FORTRAN programming language does not offer the same
dynamic memory allocation capabilities as that of the C or C++
programming languages. A result of not having the ability to
dynamically allocate memory is that sometimes programmers
will hard code array lengths to some fixed size that is large
enough to handle any data likely to enter the system. This
approach can lead to limitations in the usability of programs
when a large data array is input to the system. Hard coding
array sizes also wastes memory when the data arrays are
smaller than the hard coded limit. The ProMAX system
provides a type of dynamic memory allocation for the
FORTRAN programming language.

mem.inc
Three memory arrays are declared in the file
$PROMAX_HOME/port/include/mem.inc. One of these arrays
is the RSPACEz array, which is managed memory in the sense
that array bounds checking is provided by the ProMAX system.
Any array boundary that is overwritten due to a programming
mistake will be caught by the ProMAX system and the program
terminated with an error message. The array RSPACEz is used
for storing and accessing REAL (floating point) numbers. There
is also an array called ISPACEz for integer numbers. RSPACEz
and ISPACEz are equivalenced in memory. They occupy the
same space in memory, and the bit patterns in memory are
interpreted as being an INTEGER or REAL number depending
on which array you access; that is, RSPACEz or ISPACEz.
Another memory space that is available to the programmer is
the set of equivalenced 1-dimensional arrays RTEMPz,
ITEMPz, and CTEMPz for REAL, INTEGER, and CHAR data
types respectively. The TEMPz arrays are not managed memory
in the sense that array bounds are not checked; they are intended
to serve as a convenient place to put temporary results. The size
of the TEMPz array is 50000 four-byte words at the time of this
writing, but the programmer should check the array size by
looking at the value of the PARAMETER LTEMPpz in
$PROMAX_HOME/port/include/mem.inc if a question of the
size is important.

Other Docs

Known Problems

FORTRAN Memory Management227

Developers Programming Guide

A third array that is available is a 2-dimensional character array


called CCTEMPz, which is actually equivalenced with
CTEMPz but is conveniently sized for 2-dimensional use.

RSPACEz and ISPACEz


Pieces of the RSPACEz array can be reserved through use of the
routine MEM_RESBUFF. That memory can be returned to the
system through use of the routine MEM_FREEBUFF. An
important feature of the RSPACEz and ISPACEz arrays are that
they can be expanded if the initial array size specified in
mem.inc is not large enough to handle the memory requested by
a program. Memory expansion is done either automatically by
ProMAX when a call to MEM_RESBUFF exceeds the
available memory, or the memory space can be expanded by a
call to MEM_GROWBUFF.
The array bounds of RSPACEz and ISPACEz are checked after
each return from an INIT or EXEC subroutine. If an array
overrun is detected at that time, ProMAX stops execution and
delivers an error message ****SEVERE MEMORY
ERROR***. A programmer can cause all array bounds to be
checked within a routine though by calling MEM_CHECK or
MEM_TRAP.

Other Docs

Known Problems

Big Vector Routines228

Developers Programming Guide

Big Vector Routines


Vectors are occasionally too large to fit into available memory
and, therefore, must be written to temporary files on disk.
ProMAX provides a set of routines for handling large vectors
that appear to the programmer to be memory-like routines
rather than disk access routines. For example, the name of the
routine for creating a disk file is BV_ALLOC, suggesting
allocation of space. Actually, the routine BV_ALLOC has the
capability of checking to see if real memory is available to
satisfy the request. If that memory is not available then a disk
file will be used.
The routine names begin with the letters bv for C routines and
BV for FORTRAN routines (BV stands for Big Vector). The bv
routines generally use disk space as a type of slow memory. The
advantage of these routines is that they reduce the
programmers burden of opening, closing, and accessing disk
files.

Other Docs

Known Problems

229

Developers Programming Guide

Debugging with dbx

This chapter describes the dbx program.

Topics covered in this chapter:

Overview of dbx
System Review
Debugging

Other Docs

Known Problems

Overview of dbx230

Developers Programming Guide

Overview of dbx
Debugging ProMAX programs can be done in a number of
ways, such as by using print statements in the code to report
variable values. However, experienced programmers find that
use of the programming tool called dbx is one of the most
efficient ways of debugging a program. The program dbx is
available on all hardware platforms on which ProMAX runs. It
allows a programmer to step through a computer program and
check variable values at any point in the execution.
This chapter is not a tutorial on the use of dbx. You can learn
about dbx by typing man dbx from the command line or
through the manuals provided with your computer hardware.
This chapter provides a tutorial on how to use dbx when
debugging a ProMAX module.

Other Docs

Known Problems

System Review231

Developers Programming Guide

System Review
Before we discuss the use of dbx with ProMAX, we will review
the components that make a process. The following figure
shows the sequence of events that occurs when a ProMAX job
is created and executed. The Job Builder (promax.exe) is the
part of the user interface where the user builds a job flow, telling
ProMAX which data processing steps to run. A binary file is
written by the Job Builder when either the Execute or Exit
buttons are clicked. This file is called a packet file which, in
addition to the processing steps in the flow, contains the
ProMAX Area, Line, and dataset to be processed. The packet
file is written to the file
$PROMAX_DATA_HOME/Area/Line/Flow/packet.job
where

Other Docs

$PROMAX_DATA_HOME is an environmental variable


pointing to the directory where the ProMAX data
directories begin

Area is the directory containing the ProMAX Area,

Line is the directory containing the ProMAX line

Flow is the directory containing packet.job and the job


report in a file called job.output

Known Problems

System Review232

Developers Programming Guide

Job Builder
(promax.exe)
Batch
Queue
Super Executive
(super_exec.exe)

Stand-alone
Programs

Executive
(exec.exe)
Tool Caller
AGC

Diskread

NMO

Line Database
Information
(datasets, parameter tables,
ordered database files, etc.)

Mute
Filter

Packet File

ProMAX system overview


When you click the Execute button to start the ProMAX job, the
packet file is written and a program called super_exec.exe (or
Super Executive) reads the packet file, expands menus that are
Macros, and determines which lines in the packet file are
processing steps and which lines are not. For example, an
Alternate Executive card in the flow is not a processing step.
The Super Executive then determines which executable code
will be run to complete the job; that is, either a standalone
executable or a version of exec.exe. The Super Executive then
passes the processed packet.job file to the executive where the
processing is performed.

Other Docs

Known Problems

Debugging233

Developers Programming Guide

Debugging
The following sections provide information and tips on
debugging with dbx.

Writing to the packet.job File


There are a few requirements for the packet.job file that must be
met before dbx can be used to debug a ProMAX program. The
processing flow that is written to the packet.job file can only
contain valid ProMAX processing modules. Examples of illegal
entries in the flow include Alternate Executive and Alternate
Machine. These processes may not be in the packet file because
the Super Executive does not get a chance to process packet.job
when dbx is being used. Therefore, cards like Alternate
Executive may be presented to the system as a processing
program, although it is not, and the system will error out in the
initialization phase. In addition, flows with multiple input steps
are not allowed.
Some special-case entries are allowable in the processing flow
that are allowable include menus that are macros (see the Menus
chapter) and processes that have been commented out of the
flow.

Creating an Executable for dbx


Dbx needs to read executable code; in other words, the code
being debugged must have been successfully compiled and
linked, although it may still have some bugs. The creation of an
executable file in the ProMAX development environment is
easy. If you are creating a ProMAX module linked to the
executive, then you would type
Makeexec debug=yes

from the command line. If you are creating a stand-alone, type


gmake debug=yes

from the command line. This is assumes that you have the
correct Makefiles and are in the right directory structure in the
ProMAX environment.

Other Docs

Known Problems

Debugging234

Developers Programming Guide

The use of Makeexec debug=yes writes your executable to the


file
~user_name/$POMAX_HOME/MACHTYPE/exe/exec.exe

and use of gmake debug=yes writes your executable to the file


~user_name/$PROMAX_HOME/MACHTYPE/exe/progName.exe

where

user_name is the home directory in which the ProMAX


development environment has been set up

progName is the name of your stand-alone

MACHTYPE is the machine type for which the executable


was made

The possible choices for machine types are:


crayymp - for Cray YMP
decmips - for DEC 5000
rs6000 - for IBM RS6000
sgimips - for Silicon Graphics
solaris - for Sun Solaris

Running dbx
All that is required to run dbx is executable code which has
been compiled with the debug option set to yes, a packet.job
file, and the source code to the program that is being debugged.
Most programmers find it convenient to cd to the directory in
which the source code resides and create symbolic links to both
the packet.job and the executable code. For example, suppose
that a new ProMAX module existed in
~abc/$PROMAX_HOME/port/src/lib/maxtool/new_prog

The programmer could go to the source directory and create the


symbolic links to exec.exe and packet.job. Any changes that are
made to the executable by use of Makeexec, or to the packet.job
by changing parameters in the ProMAX flow, are automatically
seen in the local file names because they are symbolic links. In
order to make promax.exe (the user interface) write a new
version of the packet file, you can either execute the flow by
clicking on Execute, or simply click on Exit in the menu bar just

Other Docs

Known Problems

Debugging235

Developers Programming Guide

above the processing flow. The preferred method is to click on


Exit, since this will not start the Super Executive or exec.exe.
To start dbx, type
dbx exec.exe

from the command line. This starts dbx on the executable.


When dbx has finished reading the program, a prompt appears
and you may type
run packet.job

This identifies the packet.job file which is required input by


exec.exe.
At this point, running dbx on a ProMAX module is like running
dbx on any other program. You may use any or all of the
standard dbx commands.

Other Docs

Known Problems

Debugging236

Other Docs

Developers Programming Guide

Known Problems

237

Developers Programming Guide

Menus

This chapter describes ProMAX menu files.

Topics covered in this chapter:

Other Docs

Overview of ProMAX Menus and Landmark Lisp


Parts of a ProMAX Menu
Menu Heading
Parameter Specifications
exec_data
Rules
Tips on Writing Menus
Usable Lisp Functions
Lisp Primitives
Access and Assignment Functions
Callable Database Access Functions
ProMAX Lisp Extentions
Parameter Menu System
pwin
Example Macro: Display Shots with AGC

Known Problems

Overview of ProMAX Menus and Landmark Lisp238

Developers Programming Guide

Overview of ProMAX Menus and Landmark Lisp


A ProMAX menu file is the program that controls what appears
to the user of a ProMAX module; it controls the users access to
a ProMAX module. Every ProMAX module must have a menu
file if it is to be used within the ProMAX user interface.
ProMAX menus are written in the Lisp programming language;
an expert knowledge of Lisp is not required to write new
ProMAX menus. Of course, because more can be accomplished
with greater knowledge, the following two texts are
recommended for further study:

Lisp (3rd Edition), by Winston and Horn

Common Lisp: The Language, by Guy L. Steele, Jr.

Fortunately, even a superficial knowledge of Lisp can go a long


way in ProMAX menu programming.
Landmarks menu system is built around a proprietary Lisp
interpreter. The interpreter reads the code directly, rather than
having to go through a compile and link stage as would be done
with C or FORTRAN. The Landmark Lisp interpreter supports
a subset of the full Lisp language which consists of lists,
symbols, keywords, strings, and numbers (integer and floating).
The system does not support vectors, arrays, property_lists,
dotted lists, bignums, rationals, macros and multiple_value
returns and binds. ProMAX menu files can include other
ProMAX menu files.

Other Docs

Known Problems

Parts of a ProMAX menu239

Developers Programming Guide

Parts of a ProMAX menu


A ProMAX menu consists of four parts:

Menu Heading
Parameter Specifications
exec_data
rules

The following simple menu shows these four parts.

'(
name: PROGRAM_NAME
label: "Sample ProMAX Menu"
value_tab: 48

Menu Heading

parameter: NUMTO_DO
text: "Input the number of traces to process"
type: int:
value: 3
mouse_text: "Type in number of traces to process."
parameter: PARM_VAL
text: " Input the processing parameter value"
type: typein:
type_desc: ( float: 6 nil 999999. )
value: 4.
mouse_text: "Input the parameter value "

exec_data: ("PROGRAM_NAME"
("GENERAL"
("NUMTO_DO " implicit: (value 'NUMTO_DO))
("PARM_VAL" implicit: (value 'PARM_VAL))
)
)

rules: (
(rule1 ( > ( value 'NUMTO_DO ) 3 )
(do_show 'PARM_VAL)
(do_not_show 'PARM_VAL))
)
)

Parameter
Specifications

Exec_data

Rules

These parts are described in the following sections.

Other Docs

Known Problems

Parts of a ProMAX menu240

Developers Programming Guide

Menu Heading
The menu heading has three important features plus two
optional feature. The first important feature is the '( which is
actually the first two characters in the file. Lisp makes heavy
use of parentheses to group related syntax together. There is a
corresponding ) at the end of the menu. The single quote mark
just before the parenthesis signals the Lisp interpreter to just
read the string that follows (the menu code), but to not evaluate
it.
The second line in the Menu Heading section is the name of the
program to which the menu belongs. This line is actually
optional, but it is a good idea to include it so that you can see
which program the menu belongs to without searching the rest
of the menu.
The third line is the label. This is the name that will appear in
the ProMAX processes list in the user interface. This string
should match the string in the Processes file (the file that
contains a list of menus and where they reside), or else a
harmless error will be issued in the window from which
ProMAX was started.
The fourth line in the Menu Heading is the value_tab. This
value specifies how many character spaces from the right end of
the menu text to place the input boxes in the menu.
The fifth line is the optional plot_label: keyword. In the menu
heading this parameter controls whether or not this process
appears in side label processing history plots. The default is nil,
i.e. not to include this process in the plot history. Set to t to
override the default. Individual process parameters may then
use the plot_label: keyword to provide further details in the
processing history.

Parameter Specifications
This section is used to specify names, types, and other attributes
of menu parameters. In the preceeding example menu, there are
two parameters, each of which has its own set of attributes.
The first line in the Parameter Specification is parameter:. The
parameter: line acts to declare a variable name, so the first

Other Docs

Known Problems

Parts of a ProMAX menu241

Developers Programming Guide

parameter is named NUMTO_DO and the second parameter is


named PARM_VAL.
The next attribute is text:, which is the character string that will
appear on the ProMAX menu to the left of the box where data is
input.
The next attribute is type, which describes the kind of thing that
will appear in the menu for data input. The type of parameter in
NUMTO_DO is int, which tells the Lisp interpreter to put up a
box in the menu that will accept integer input from the
keyboard. The type of PARM_VAL is typein:, which tells the
Lisp interpreter that the data input box is to accept numerical
input from the keyboard and to look for more information about
the type in the attribute called type_desc.
The attribute type_desc appears in PARM_VAL but not in
NUMTO_DO, because the type int carries with it an implied
description. In the parameter PARM_VAL, type_desc states that

the parameter is a floating point number

the number of allowable characters in the input is 6

there is no lower limit on input values (indicated by nil)


except that the number cannot have more than 6 characters
(-99999)

the upper limit on input is 999999.

The default value for the parameter is set using the value:
attribute. This is the value that will appear on the screen when
the menu is first placed into a processing flow.
The final attribute in the example above is mouse_text: which
specifies the text that appears in a box at the bottom of the
ProMAX screen when the mouse pointer is on a parameter.
There are many variations of type and type_desc; for example,
the type can be a function, and the description of the function is
that it gets a list of header names and displays them to the
screen. An example of all the menu parameter types,
descriptions, etc., can be found in the Lisp Menu Code
Examples appendix..

Other Docs

Known Problems

Parts of a ProMAX menu242

Developers Programming Guide

exec_data
The first line in the exec_data section is
exec_data: ("PROGRAM_NAME"

The opening parenthesis is the beginning of the exec_data


grouping; there is a closing parenthesis at the end of the section.
The string inside the quotes is the name of the program; it must
match the name of the init and exec subroutines. For example, if
the init and exec subroutines in a FORTRAN ProMAX module
are INIT_MY_PROG and EXEC_MY_PROG, then the string
inside the quotes above would be MY_PROG. Letters in this
string must be upper case.
The purpose of the following two lines in the menu
("NUMTO_DO" implicit: (value 'NUMTO_DO))
("PARM_VAL" implicit: (value 'PARM_VAL))

is related to how parameters get from the menu into the


ProMAX module. Recall that the processing flow containing
one or more menus is written to a binary file called packet.job
when the Execute button is pushed on the ProMAX screen. The
ProMAX parameter-getting routines, such as EX_GETPARM
(FORTRAN), search the packet.job file for the character string
in double quotes at the beginning of the line and return the value
of the parameter. For example, EX_GETPARM might be called
from within the subroutine INIT_PROGRAM_NAME as
follows:
CALL EX_GETPARM( "NUMTO_DO", 1, VALUE_PARM )

The routine EX_GETPARM reads the part of the packet.job file


containing parameters for PROGRAM_NAME until it finds the
string NUMTO_DO. The parameter NUMTO_DO is then
evaluated for its value (the value input to the menu by the user)
and that value is passed back to the variable VALUE_PARM in
the subroutine INIT_PROGRAM_NAME.
The calling argument in quotes in EX_GETPARM has to match
the string in quotes in the exec_data section of the menu.
Therefore, the line in the menu
("NUMTO_DO"

implicit: (value 'NUMTO_DO))

could be also be written as

Other Docs

Known Problems

Parts of a ProMAX menu243

("FOO

Developers Programming Guide

"

implicit: (value 'NUMTO_DO))

as long as the call to EX_GETPARM is written as follows:


CALL EX_GETPARM( "FOO

", 1, VALUE_PARM ).

Note that the string "FOO


" is padded to 8 characters
between the quotation marks. The padding is a requirement
when ProMAX runs on IBM machines and is recommended for
programs written on other machines to make the code portable.
The word implicit: exec_data section indicates that the value to
be output to the packet file is of the type specified in the
Parameter Specifications. Note that in order to get the value of
the parameter NUMTO_DO, the word value must be put in
front of NUMTO_DO. The word value indicates that the value
of the parameter (which is one of its attributes) is to be
evaluated.

Rules
The rules section is the part of the menu file that controls,
among other things, which parameters are hidden from the user
when they are not needed.
The rules section begins with the string rules( and ends with
a closing parenthesis. The rules themselves are of the form
( ruleName ( conditional statement )
(action if conditional statement is true)
(action if conditional statement is false)

)
The string ruleName represents a character string without blank
spaces that can contain anything. It serves as a label to give
some documentation as to what the rule accomplishes. The
string has no length limit except that it has to contain at least
one character. Note that additional documentation can be added
in a Lisp menu by preceding the documentation line with a
semi-colon. For example:
;this is a comment line

in a menu file would be ignored by the Lisp interpreter.

Other Docs

Known Problems

Parts of a ProMAX menu244

Developers Programming Guide

The conditional statement following the rule name is commonly


an evaluation of a parameter. Evaluation in the Lisp interpreter
is done with the following form:
( type of evaluation (thing being evaluated) comparison
value)

The type of evaluation is >, <, =, etc. The thing being evaluated
is some attribute of a parameter, such as its value; the
comparison value can be a constant or some expression, such as
the sum of two other parameters.
In the preceeding example menu, the value of NUMTO_DO is
evaluated to see if it is greater than 3 by the statement:
( > ( value 'NUMTO_DO ) 3 ).

If we wanted to see if NUMTO_DO was less than 3, we could


write:
( < ( value 'NUMTO_DO ) 3 )

and to check for NUMTO_DO equal to 3, we would write:


( = ( value 'NUMTO_DO ) 3 ).

In the preceeding menu file example, the only rule in the file
states that PARM_VAL is to be shown to the user on the menu
when NUMTO_DO is greater than 3.
The conditional statement need not be as simple as the one in
the menu file example above. It can contain compound statements such as and or if, as well as functions. For example, the
following rules section sets the condition that in order for the
parameter SHOW_PAR to be shown on the menu, the value of
parameter PARM1 must be equal to 1, the value of PARM2
must be equal to the value of PARM1, and the value of PARM3
must be equal to the sum of the values of PARM1 and PARM2.
The action statements can also have conditional and compound
statements within them.
rules:(
(rule1
(and
( = (value 'PARM1 ) 1 )
(and
(= (value 'PARM2 ) (value 'PARM1) )
(= (value 'PARM3 ) (+(value'PARM1) (value\
'PARM2)) )

Other Docs

Known Problems

Parts of a ProMAX menu245

Developers Programming Guide

)
)
(do_show 'SHOW_PAR)
(do_not_show 'SHOW_PAR)
)
)

Rules may also be made unconditional by specifying t for the


condition. Such rules are initializations and run only once.

Other Docs

Known Problems

Tips on Writing Menus246

Developers Programming Guide

Tips on Writing Menus


Keep the following tips in mind when writing ProMAX menus.

Use Examples
Unlike the source code for ProMAX modules, you have access
to all of the ProMAX menus. Study and copy those files
liberally. It is likely that somewhere within the existing menus
there is a menu file that does something similar to what you
would like to do in your new menu.

Keep it Simple
Complex conditional statements can be difficult to debug (as in
any other programming language) but there are no debugging
tools such as dbx to debug Lisp code.

Other Docs

Known Problems

Usable Lisp Functions247

Developers Programming Guide

Usable Lisp Functions


Three functions are usable from the menu system: Lisp
primitives, menu access and assignment functions, and the
callable database access functions. The following sections
describe these functions.

Lisp Primitives
We do not document the Lisp primitives in this manual; instead,
we direct you to two references:

Lisp (3rd Edition), by Winston and Horn


Common Lisp: The Language, by Guy L. Steele, Jr.

If you are unfamiliar with Lisp, we urge you to acquire at least


the first reference. If you have used any Lisp dialect, you should
be comfortable with most of these forms and probably already
have both these documents.
The following table lists the Lisp primitives. Please note that:

Other Docs

The ** symbol indicates functions that are destructive list


operations; if you are new to Lisp, we caution against their
use before careful study

The ? symbol indicates a wildcard for the test equal; that


is:
(equal ? anything) => t therefore (member ? '(1 2 3)) => (1
2 3)

Lisp keywords are symbols beginning with colons, such as


:test. Parameter attributes are symbols ending in colons,
such as type:. Symbols beginning or ending with colons
are, in fact, both Lisp keywords and are eq; for example,
(eq :test test:) => t. Keywords eval to themselves and will
printout in the manner they were first encountered; that is,
colon at the start or end.

Known Problems

Usable Lisp Functions248

Developers Programming Guide

Lisp Primitives
Lisp Primitive

Common Lisp

Reference

cdr

Yes

car

Yes

length

Yes

first

Yes

second

Yes

third

Yes

fourth

Yes

fifth

Yes

sixth

Yes

seventh

Yes

nth

Yes

nthcdr

Yes

last

Yes

list

Yes

append

Yes

cons

Yes

nconc

Yes

push

Yes

rplaca

Yes

pushend

No

destructive (setq a '(1 2 3)) (pushend 4 a) a=>1 2 3 4)

remove

Almost

1, :test fixed as equal (see remq)

remq

No

like remove with :test fixed as eq

delete

Almost

a=1, :test fixed as equal (see delq)

delq

No

like delete with :test fixed as eq

copy

No

same as copy-list

copy-list

Yes

eq

Yes

equal

Yes

Yes

Other Docs

Known Problems

Usable Lisp Functions249

Developers Programming Guide

Lisp Primitives (Continued)


Lisp Primitive

Common Lisp

Reference

>

Yes

>=

Yes

<

Yes

<=

Yes

member

Almost

1, :test fixed as equal (see memq)

memq

No

like member with :test fixed as eq

atom

Yes

numberp

Yes

listp

Yes

symbolp

Yes

and

Yes

or

Yes

null

Yes

not

Yes

boundp

Yes

assoc

Almost

1, :test fixed as equal (see assq)

assq

No

like assoc with :test fixed as eq

eval

Yes

print

Yes

makunbound

Yes

Yes

Yes

Yes

Yes

quote

Yes

'

Yes

Almost

2, is not implemented as a macro

if

Yes

cond

Yes

setq

Yes

Other Docs

Known Problems

Usable Lisp Functions250

Developers Programming Guide

Lisp Primitives (Continued)


Lisp Primitive

Common Lisp

Reference

set

Almost

1, operates only on symbols

setf

Almost

1, operates only on symbols

progn

Almost

1, break not recognized

let

Almost

1, is in fact let*

defun

Almost

1, &rest, &key, and any variable number of args not supported

do

Yes

load

Yes

Access & Assignment Functions


Each of the following functions evaluate their arguments; in
order to get the value of a parameter with symbol name foobar,
you would write (value 'foobar).
Access & Assignment Functions
Function

Description

value parm

Returns contents of value: attribute of parameter named parm.

set_value parm sexp

Set contents of value: attribute of parameter named parm to sexp.

type parm

Returns contents of type: attribute of parameter named parm.

set_type parm type_kwd

Set contents of type: attribute of parameter named parm to one of the


supported type keywords.

type_desc parm

Returns contents of type_desc: attribute of parameter named parm.

set_type_desc parm sexp

Set contents of type_desc: attribute of parameter named parm to


sexp.

text parm

Returns contents of text: attribute of parameter named parm.

set_text parm string

Set contents of text: attribute of parameter named parm to string.

selected_item parm

Returns contents of selected_item: attribute of parameter named


parm.

set_selected_item parm sexp

Set contents of selected_item: attribute of parameter named parm to


sexp.

mouse_text parm

Returns contents of mouse_text: attribute of parameter named parm.

set_mouse_text parm string

Set contents of mouse_text: attribute of parameter named parm to


string.

error_list parm

Returns contents of error_list: attribute of parameter named parm.

Other Docs

Known Problems

Usable Lisp Functions251

Developers Programming Guide

Access & Assignment Functions (Continued)


Function

Description

add_error parm string

Adds error to error_list: attribute of parameter named parm with text


of string.

delete_error parm string

Deletes error from error_list: attribute of parameter named parm


with text of string.

warning_list parm

Returns contents of warning_list: attribute of parameter named parm.

add_warning parm string

Adds warning to warning_list: attribute of parameter named parm


with text of string.

delete_warning parm string

Deletes warning from warning_list: attribute of parameter named


parm with text of string.

value_tab parm

Returns contents of value_tab: attribute of parameter named parm.

set_value_tab parm integer

Set contents of value_tab: attribute of parameter named parm to


integer.

showing parm

Returns contents of showp: attribute of parameter named parm.

do_show parm

Set contents of showp: attribute of parameter named parm to t.

do_not_show parm

Set contents of showp: attribute of parameter named parm to nil.

Callable Database Access Functions


There are currently only four database access functions callable
from Lisp. The first three are of questionable usefulness
because they return the UNIX name for things, not the
descriptive user name.
Database Functions
Function

Description

(dataset_list)

Argumentless function that returns a list of three elements, the third of


which is a list of the UNIX names of available datasets. The first two
elements should not be depended upon as they are used internally by
the menu system.

(header_list)

Argumentless function that returns a list of three elements, the third of


which is a list of the header words available. The first two elements
should not be depended upon as they are used internally by the menu
system.

Other Docs

Known Problems

Usable Lisp Functions252

Developers Programming Guide

Database Functions
Function

Description

(parm_list parm_type)

This function returns a list of three elements, the third of which is a list
of the UNIX names of available parameter files. The first two elements
should not be depended upon as they are used internally by the menu
system. One string argument is required, such as "MUT", "VEL", etc.,
for the various types of parametric data.

(db_parmget_line var_string)

Returns the value of a line level variable named in var_string. For


example, (db_parmget_line "IUNITSz") returns IENGLISHpz,
ISECARCpz, or IMETRICpz, depending on the units of measurement
for this line in the database. (Used in menu defaulting rules.)

ProMAX Lisp Extentions


ProMAX defines some additional functions that are useful in
menus. The following table lists some of those you may
encounter perusing in the master ProMAX menus.

Extended ProMAX Lisp Functions


Function

Description

(string_out var)

Return a string representation of the given Lisp variable.

(string_shorten var)

Remove extra white space and return the result.

(string_upcase var)

Return string argument converted to upper case text.

(string_downcase var)

Return string argument converted to lower case text

(string_concatinate var1 ... varN)

(Yes thats how its spelled.) Returns the concatenation of its string
arguments as one long string.

(count_string var token)

Returns the number of occurences of the second argument string in


the first argument string.

(system var)

Executes the Unix command line in the argument string and return
the commands output.

(xsystem var)

Execute the Unix command line in the argument string, which is


assumed to invoke some X Window application, and return the
commands output.

(promax_path "partial_path")

Returns a string prefixing the current $PROMAX_HOME to the


given partial path.

(current_area)

Returns the current area.

(current_line)

Returns the current line.

(current_flow)

Returns the current flow.

Other Docs

Known Problems

Usable Lisp Functions253

Developers Programming Guide

Extended ProMAX Lisp Functions


Function

Description

(flow_directory)

Returns pathname ofdirectory containing current flow.

(where_promax_is)

Returns the name of the host on which the ProMAX UI is running.

(where_promax_displays)

Returns the X Window DISPLAY string being used by the


ProMAX UI.

(set_environment var value)

Set an environment variable to the given string value.

(unset_environment var)

Unset the specified environment variable

New Lisp functions can be defined by using defun with any of


the supported Lisp primitives or other functions. New functions
that are defined by using defun do not require recompilation.
These forms should be placed in a file and loaded by adding a
load call to $PROMAX_HOME/port/misc/extend.lisp.
As an example, assume that we are creating a menu called
framus and need a function that can be called from the rules to
perform some needed action. We would create the file
$PROMAX_HOME/port/misc/framus.lisp, the code of which
is:
(defun framus_simple_function (arg1)
(if
(and (listp (type_desc 'parm1))
(member arg1 (type_desc 'parm1)))
(set_type_desc 'parm1 (remove arg1 (type_desc
'parm1)))
)
)

We can then cause this file to be loaded by adding the following


line to the file $PROMAX_HOME/port/misc/extend.lisp:
(load (promax_path "port/misc/framus.lisp"))

Other Docs

Known Problems

Parameter Menu System254

Developers Programming Guide

Parameter Menu System


Parameter menus are driven and developed by manipulating an
ASCII text file, called the Menu Description File (MDF), which
is read by the Lisp interpreter. The MDF is a list of keyword
value pairs (KVPs) and always begin with '( and end with ).
Keywords may be written :keyword or keyword: (see the Lisp
Primitives section at the beginning of this chapter). Therefore,
each of the following lines are exactly equivalent:
type:
:type
:type
type:

choose:
choose:
:choose
:choose

We suggest that you use the last form; that is, to use the postfix
notation for process and parameter attributes and the prefix
notation for keyword values. The remainder of this document
uses this notation, although it is possible that this notation is not
used in early examples that you might have encountered. The
choice is arbitrary and completely up to the menu author.
Three KVPs are always first in the MDF: name, label, and
value_tab. The plot_label specification should appear with that
group as well. The exec_data and rules KVPs may appear
anywhere.
Keywords
Keyword

Value Type

Default

name:

symbol

NONE

label:

string

name:
attribute

Menu Label coerce to string.

value_tab:

integer

40

Default parameter value_tab: (see value_tab


parameter attribute in the following table).

plot_label:

nil or t

NONE

Include parameters in plot sidelabel history.

rules:

list

NONE

List of Lisp production rules used to provide context


sensitivity.

exec_data:

list

NONE

Causes parameter data to be written to packet_file for


execution.

Other Docs

Definition

Known Problems

Parameter Menu System255

Developers Programming Guide

Parameter Keywords
Each parameter keyword is followed by a name symbol and
defines a new parameter. These appear one below another on the
menu. Each parameter has a number of attributes associated
with it that are also set using KVPs. The KVPs immediately
following a parameter-KVP establish the initial settings for that
parameter and may appear in any order. However, if the same
keyword is repeated before the next parameter keyword is read,
the last occurrence takes precedence. The parameter and
attribute KVPs are as follows:
Parameter Keywords
Parameter

Keyword
Value Type

Default

Definition

parameter:

symbol

None

Defines new parameter.

type:

keyword

None

Type of parameter.

type_desc:

list

nil

Extended type info.

selected_item:

string or list

nil

See choose: below.

value:

depends on type

nil

Contains selected value.

text:

string

parameter:

Symbol text of parameter coerce to string.

value_tab:

integer

menu
value_tab:

Horiz space in chrs for text.

showp:

nil or t

Visibility predicate.

mouse_text:

string

nil

Pointer help text.

plot_label:

nil or t

nil

Include item in plot sidelabel history.

error_list

list

nil

Errors not set directly.

warn_list

list

nil

Warnings not set directly.

Of these keywords, the type and type_desc attributes are the


most important and the most complicated. They determine the
appearance and allowed user actions on a parameter.

Parameter Types and Attributes


The parameter types break down into 2 general categories:
Type-ins and Choose-parameters from a list of choices,
although Other Parameter Attributes exist.

Other Docs

Known Problems

Parameter Menu System256

Developers Programming Guide

Type-ins
The following table describes implicit Type-ins.
Implicit Type-in
Type

Description

type: :int
or type: :integer
or type: :fixnum

User allowed to type in any integer into 8 character field. No upper or lower
bounds applied.

type: :real
or type: :float
or type: :flonum

User allowed to type in any real into 10 character field. No upper or lower
bounds applied.

type: :string

User allowed to type in any string into 40 character field

For each of these types, selected_item and type_desc are not


used, and the value attribute is set to the integer (real, or string,
respectively) that the user typed in.

Specified Type-in
In this example, the value typed in is placed in the value
attribute of the parameter, and selected_item is not used. One or
both of bounds may be omitted, which would allow the field
width to be set without any restriction on the value. To specify
an upper bound and no lower bound, set lower bound to nil.
type: :typein
type_desc: ( typein_type field_width typein_lower_bound\
typein_upper_bound )
where- typein_type is from the list of implicit\
typein types above
field_width is an integer number of characters\
to provide for entering values.
typein_lower_bound is the lowest numerical\
value allowed to be entered (ignored for\
:string type)
typein_upper_bound is the highest numerical\
value allowed to be entered (ignored for\
:string type)

Editor Type-in
In this example, the editor pops up when the visible field
(show_always_width) is clicked on. The editor and the help
windows are scroll-enabled, so neither needs to be as large as
the maximum expected entry. Again, the value typed-in is

Other Docs

Known Problems

Parameter Menu System257

Developers Programming Guide

placed in the value attribute of the parameter, and selected_item


is not used.
type: :edit
type_desc: (show_always_width editor_width\
editor_height help_string )
where- show_always_width is the width of a mouse\
sensitive\
field that contains the first width non-blank\
characters of the string in the value\
attribute
editor_width is the width in chars of the popup\
editor
editor_height is the height in lines of popup\
text editor
help_string is a string of text which will\
appear at the bottom of the editor.

Choose from Parameters List


Choose-parameters presents a list of choices from which the
user can pick. The choices that will appear are registered in the
type_desc attribute.

Choose Type
In this example, if you want to have the list of choices appear
when no item is selected, you must set selected_item to the
keyword :none.
type: :choose
type_desc: ( item [item] [item] ... )
where- item = string
or item = ( string sexp mouse_help )
or item = :return
selected_item: an item from type_desc or :none
Items may be:
string - -String will appear on list of choices
-selected_item is the string to highlight\
and is set when the user clicks button\
1 on it
-value will be set to selected_item string
list - -String will appear on list of choices
-selected_item is set to entire list with\
user click
-value set to (eval sexp) mouse_text string
-will appear on mouse-help line when user\
is pointing at this specific choice
:return --repeatable keyword which will not appear\
on list of choices but instead causes\
choices that follow to be placed on a\
new line beneath previous choices

Other Docs

Known Problems

Parameter Menu System258

Developers Programming Guide

Defaults;
selected_item-defaults to (first type_desc). If\
specified it must be a 'member' of\
type_desc list or it will be set to (first\
type_desc).
value
-defaults to selected_item if selected_item\
is a string or to (eval (second\
selected_item)) if selected_item is a list.

Pop_Choose List
Pop_choose presents a single mouse sensitive item
(selected_item) to the user that, when clicked on, pops up the
entire list specified in type_desc.
type: :pop_choose

The attributes type_desc, value, and selected_item are exactly


as specified for type: :choose, except
-return keyword is not handled or needed
-selected_item: :none is not supported and\
selected_item must be set or will default as\
covered in type choose.

Circular List
Circular lists are just like pop_choose in that they present to the
user only the selected_item element of type_desc in a mouse
sensitive field. However, instead of popping up the entire list
when clicked on by the user, the selected_item circulates to the
next item in type_desc.
type: :circular

The attributes type_desc, value, and selected_item are exactly


as specified for type: :choose, except
-return keyword is not handled or needed
-selected_item :none is not supported and must be\
set or will default as covered in type choose.

Boolean
Boolean type presents a list of two items to the user, Yes and
No. The value attribute is set to t if Yes is selected and to nil if
No is selected.

Other Docs

Known Problems

Parameter Menu System259

Developers Programming Guide

type: :boolean
selected_item:always one of the two lists ("Yes " t) or \
("No" nil)
defaults to ("Yes " t)
Boolean is a shorthand fortype: :choose
type_desc: ( ("Yes " t) ("No" nil) )

Multiple Choose
Multiple choose work like the choose type except that any
number of the options (including none) may be selected. The
value is this case is a list containing as members the
corresponding value that the ordinary choose would have
returned for a given selected item.
type: :multiple_choose

The attributes type_desc, value, and selected_item are exactly


as specified for type: :choose, except
-return keyword is not handled or needed
-selected_item :none is not supported and must be\
set or will default as covered in type choose.

Action Lists
Action lists are a shorthand type exactly equivalent to choosetype with selected_item: set to :none. Both permit lists of
choices to appear without any item selected by default, so a rule
might be fired when it is detected that selected_item does not
equal :none.
Action list are normally used as a middle ground between a
regular choose parameter, supplying a predetermined selection
list and a value, and a :function type requiring special functions
or programs to initialize its entries. Action lists typically have
no default :type_desc and these items are dependent upon other
user parameter settings.

Function Type
The function type is a specialized type for access to three major
components of the ProMAX database.
type: :function
type_desc: function_call_list
where function_call_list is (dataset_list datasets)

Other Docs

Known Problems

Parameter Menu System260

Developers Programming Guide

or (header_list headers)
or ((parm_list string) parms)
where string is "MUT", "VEL", "GAT" or one of\
the other three letter strings for each type of\
parametric data allowed in the ProMAX database.

There is no flexibility in the function type parameter; that is, the


only three options are those shown above. Function type
parameters act as follows:
1.

Check the value attribute of the parameter against the list


of dataset_list, header_list, or parm_list, respectively.

2.

If not there, indicate some type of problem to the user by


way of a warning or error.

3.

A single mouse sensitive entry appears on the menu which


is either INVALID or selected_item string. When clicked
on, the menu for selection of the corresponding type pops
up.

4.

Selection from the popup menu causes the value attribute


to be set to the system internal name for the choice, and the
selected_item attribute to be set to the descriptive name of
the choice.

Other Parameter Attributes


This section describes additional parameter attributes.

Value Tab Attribute


Value_tab tabs the values (choices, type-ins, etc.) the specified
number of characters over.
value_tab: integer

In essence, the number is approximately the amount of space


that will be reserved on the left for the parameter text set with
the text keyword. If not set, value_tab for an individual parameter defaults to value_tab: attribute for the menu, which defaults
to 40. Increase this value if you encounter mysterious blank
lines when the menu is displayed.
If value_tab is set to zero or text is set to :none, the values will
appear at the left edge of the menu under the text if text is

Other Docs

Known Problems

Parameter Menu System261

Developers Programming Guide

supplied, or in place of text if text is set to :none. The space for


text and values are set to 1.6 times the process value_tab. Using
this feature, it is possible to create what appears to be mouse
sensitive text. For example, try this:
parameter: foo
type: :choose
type_desc: ("Mouse sensitive text at left side of menu")
selected_item: :none
value_tab: 0
text: :none

Text Attribute
The text attribute specifies the parameter text to appear or the
menu.
text: string or text: :none

As discussed in the preceeding section, there is value_tab space


in characters for text against the left side of the menu. Text can
be longer than this, however, which will cause the text to
occupy multiple lines, each value_tab long.
If text is set to the keyword :none, a text window is omitted and
values will appear up against the left side of the menu, ignoring
value_tab.

Showp Attribute
The showp attribute is a predicate that controls the visibility of
the parameter on the menu.
showp: Attribute

If set to nil, the parameter will still exist, but will not appear at
all on the menu. Being a predicate, if set to any other value
except nil, the parameter will appear (the default case). It is
possible to have parameters which never show, but this
predicate is usually manipulated by the rules which affect the
set of parameters that will be visible, based on other userspecified parameter values. This, along with the computational
power of rules, is how context sensitivity is achieved.

Other Docs

Known Problems

Parameter Menu System262

Developers Programming Guide

Mouse Help Attribute


If a mouse_text is specified, string will appear in the mousehelp line at the bottom of the screen when the mouse is pointing
at this parameter:
mouse_text: string

For certain choose-types, this mouse-help may be over-ridden


by some other mouse_text specified for individual choices.

Plot_label Attribute
The plot_label attribute is a predicate that controls the visibility
of the parameter on the sidelabel history of hardopy plots.
plot_label: Attribute

If set to nil (the default case), the parameter will still exist, but
will not appear at all on the plot sidelabel history. Being a
predicate, if set to any other value except nil, the parameter will
appear. In addition to being an attribute, the plot_label:
predicate is used at the beginning of the menu as a keyword to
control whether any individual parameters appear on the plot
sidelabel. (If omitted, the first plot_label: attribute determines
this global menu setting.) In any event the name of the process
being run appears on the sidelabel history.

Error_list and Warning_list Attributes


The error_list and warning_list attributes are both:

a list of strings (which is the text to be displayed beneath


the text)
the value section of a parameter

They are seldom specified; instead, they are manipulated by the


rules using the add_error, delete_error, add_warning, and
delete_warning functions. There is intentionally no set_error or
set_warning functions.

Other Docs

Known Problems

Parameter Menu System263

Developers Programming Guide

Exec_Data Process-Level Keyword


The exec_data process attribute is not strictly a menu system
attribute. Instead, it is a list which is read and interpreted by the
user interface when saving flow changes or executing a job, if
that job causes executable packets to be written out to the trace
processing Executives packet file. Its structure is as follows:
exec_data: packet_list
or
exec_data: ( packet_list [packet_list] ... )
where
-packet_list = ( tool_namestring group_list\
[group_list] ...
-group_list = ( group_namestring parameter_list\
[parameter_list] ... )
-parameter_list = ( parameter_namestring\
output_form value_sexp )
where
-output_form = :implicit
or :string
or (:string nwords) where nwords causes
nwords * 4 chars to be output padding\
with blanks or truncating as necessary
or :real or :float or :flonum
or :int or :integer or :fixnum
-value_sexp = a Lisp form that will be eval'ed to\
get the value to output to the packet or coerced\
with output_form.

exec_data Examples and Explanation


If exec_data is present and the process is not commented out in
the flow editor, the packet_list value of the KVP exec_data will
cause one executable packet to be written to the packet_file for
reading by the Executive. The exec_data KVP can be a list of
packet_lists in which multiple executable packets will be
output. In this manner, a single menu can be constructed (as a
macro) that will cause multiple processes to be executed by the
trace Executive.
Each packet_list is a list of the string name of a processing tool,
such as AGC or FILTER, followed by the group_list or lists for
that tool. Most tools have only one group, typically GENERAL.
Each group_list is a list of the string name of the group, such as
GENERAL, followed by n parameter_lists where n is the
number of parameters the tool expects to read from this group
in the packet_file.

Other Docs

Known Problems

Parameter Menu System264

Developers Programming Guide

Each parameter_list is a list of the string name of a single


parameter that will be output to this group, followed by a format
specifier (output_form) and a value expression (value_sexp).
The value_sexp is a Lisp expression that will be evaluated.
After evaluating, its value will be output, or coerced into a form
specified in output_form, according to the following rules:
Lisp Expression Evaluation
output_form

(eval value_sexp) returns

parameter value output

:implicit

real, float, or string

corresponding type at left

:implicit

list, keyword, or symbol

ERROR

:real

real

Returned value

:real

integer

Float the value returned

:real

not float or integer

ERROR

:integer

integer

Returned value

:integer

real

Truncate value to integer

:integer

not float or integer

ERROR

:string

string

String padded with blanks to even multiple of 4 byte


words

:string

not a string

ERROR

(:string num)

string

String padded with blanks or truncated to num 4 byte


words

(:string num)

not a string

String padded with blanks or truncated to num 4 byte


words

(:int and :fixnum are synonyms for :integer, :float and :flonum
are synonyms for :real)

exec_data Example
The exec_data: KVP from the AGC menu is:
exec_data:("AGC"
("GENERAL"
("MODE_AMP" implicit: (value 'MODE_AMP))
("AGCLEN" implicit: (value 'AGCLEN))
("MODE_WIN" implicit: (value 'MODE_WIN))
("MODEZERO" implicit: (if(value 'mode_option)1\
0 ))
)
)

Other Docs

Known Problems

Parameter Menu System265

Developers Programming Guide

When this exec_data KVP is in a menu included in a flow, a


single packet will be output that will cause the AGC process to
be executed by the trace Executive. The AGC process expects to
find all its critical parameters in one group called GENERAL,
and will find 4 parameters available in the packet file for
retrieval: MODE_AMP, AGCLEN, MODE_WIN, and
MODEZERO.
The values output to the packet file, for the first three of these
parameters, is whatever was held in the value attribute type and
contents of the similarly named parameter in the menu system
at the time the packet file was saved. In the last case,
MODEZERO parameter in the packet file will always contain
an integer of value 0 (zero) or 1 (one), depending on whether
the value attribute of the menu system parameter mode_option
was nil or non-nil at the time the packet file was saved.
As just mentioned, exec_data may be a list of packet_lists, as
illustrated in the following code. This would cause two packets
to be output, with the first initiating AGC execution, followed
by FILTER. In essence, a menu with this type of exec_data that
also manipulates all the pertinent parameters correctly is a
macro; that is, it is a single menu item that causes the trace
Executive to execute multiple processes.
exec_data: (
("AGC"
("GENERAL"
("MODE_AMP" :implicit (value 'MODE_AMP))
("AGCLEN" :implicit (value 'AGCLEN))
("MODE_WIN" :implicit (value 'MODE_WIN))
("MODEZERO"::implicit ( if (value 'mode_option)\
1 0 ))
)
)
("FILTER"
("GENERAL"
("FLT_TYPE" :implicit (value 'FLT_TYPE))
("PHASE" :implicit 1 ) ;
("PHASE" :implicit (value 'PHASE))
("PCT_PAD" :implicit (value 'PCT_PAD))
("FLT_FREQ" :implicit (value 'FLT_FREQ))
("FLT_PARM" :implicit (value 'FLT_PARM))
("F_NOTCH" :implicit (if (value 'notch_option) \
(value 'F_NOTCH) 0.0 ))
("N_F_WIDE" :implicit (value 'N_F_WIDE))
("GATENAME" :implicit (if (value 'db_option)\
(value 'GATENAME) "NONE" ))
("PRIM_KEY" :implicit (value 'PRIM_KEY))
("SCND_KEY" :implicit (value 'SCND_KEY))
("FLT_GATE" :implicit (value 'FLT_GATE))

Other Docs

Known Problems

Parameter Menu System266

Developers Programming Guide

("REMUTE" :implicit (if (value 'remute_option)\


1 0 ))
)
)

Including Other Menus


A ProMAX menu may include another ProMAX menu using
the :include directive. Parameters, exec data and rules are all
included. The syntax is:
:include [PARAM] "inc.menu" ("CALLER" "EXECNAME")

where the optional PARAM field is the name of a parameter in the


current menu above which you wish the newly included
parameters to appear. If no parameter is given, the included
parameters go at the end of the current menu. The list of strings
directs unnamed included exec_data to the proper place in the
current menu. For example in the menu example above, this list
could be ("AGC" "GENERAL") or ("FILTER" "GENERAL").
If the menu to be included is not a fully-qualified pathname,
ProMAX uses the setting of $PROMAX_PORT_MENU_HOME
(which defaults to $PROMAX_HOME/port/menu) as the include
search directory.

Rules and Context Sensitivity


The menu system provides for the reconfiguration of a menu
based on user action by way of rules. Formally, the rule system
is a forward-chaining production rule inference engine, which is
provided as part of the menu system; therefore, each menu with
rules can be considered a small expert system. Such systems are
well documented in the literature (see the Handbook of
Artificial Intelligence by Barr and Feigenbaum: William
Kaufmann, publisher). Here is how it works.
Each rule is a list which is supplied in one of the following
forms.
( rule_name if_clause then_clause )
( rule_name if_clause then_clause else_clause )
or
( index_list rule_name if_clause then_clause )
( index_list rule_name if_clause then_clause\
else_clause )
where-

Other Docs

Known Problems

Parameter Menu System267

Developers Programming Guide

index_list is an optional list of state_variable(s).


rule_name is an unused Lisp symbol used only as a\
place holder and for the authors expressive\
needs.
if_clause is a valid Lisp expression which will be\
eval'ed each time any of the state\
variables ( read parameter attributes) that\
it tests or involves change.
then_clause is a valid Lisp expression which will be\
eval'ed if its corresponding tested\
if_clause eval'ed non-nil.
else_clause is an optional valid Lisp expression\
which will be eval'ed if its corresponding\
tested if_clause eval'ed to nil.

As this is a forward-chaining system, the key to rule execution


is the if_clause. Each parameter attribute can be considered a
state variable; that is, the values of the parameter attributes at
any moment in time define the current state of the system.
Every user action on a menu causes some change in a parameter
attribute, usually value or selected_item. In addition, action
clauses (such as then_clauses and else_clauses) which call any
of the menu assignment functions will cause changes in these
state variables. Instances of state variables will hereafter be
written state_variable and represented by a two element list of
the form ( attribute_symbol parameter_name ). Therefore, the
state_variable representing the value attribute of parameter
framus would be the list '(value framus).
Each change is recorded in a change_list by appending the
state_variable corresponding to that change to the end of the
change_list. The index_list is a list of all state_variables
referred to in a rules if_clause. It is always present at rule
execution time, and automatically generated by the rule reader
(usual case) if not provided by the rule author.

Example
As an example, consider the following scenario. A menu is on
the screen and the change_list is nil (the empty list). This menu
has one parameter called framus, of type integer, and an initial
value of 2:
parameter: framus
type: :integer
value: 2
There is one rule, i.e:
rules: (
;start of rule list
( framus_rule;rule name start of rule

Other Docs

Known Problems

Parameter Menu System268

Developers Programming Guide

)
)

(not (= 2 (value 'framus))) ;if clause


(set_value 'framus 2) ;then clause
;end of rule framus_rule
;end of rules

The index_list was not provided by the author; therefore, the


rule reader automatically set the index_list for rule framus_rule
to:
( (value framus) )

When the user types in a new value for integer framus, the value
attribute of framus is changed to that new value, and the
state_variable '(value framus) is pushed onto the end of the
change_list. The change_list is now:
( (value framus) )

As soon as a state_variable appears on the change_list, the rule


interpreter runs. The actions of the rule interpreter are described
in Lisp code (valid in some dialects of Lisp, but not ours for
lack of a loop macro) and comments below.
1 (loop for change in change_lis bind a variable change\
one at a
;time to state_variable elements
;of change_list until change_list
;is exhausted.
2 (loop for rule in rule_lis ;bind a variable rule one\
at a
;time to elements of rule_list
;until rule_list is exhausted.
3 (if (member change (first rule)) ;if state_variable\
changed is a
;member of rule's index_list,
;i.e., referred to in rules\
if_clause
;if member then
4
(if (eval (third rule)) ;evaluate rules\
if_clause
;
if non-nil then
5
(eval (fourth rule)) ;evaluate rules\
then_clause
;else
6
(eval (fifth rule)) ;evaluate rules\
then_clause
;Remember that if there is no
;else_clause, (fifth rule)=>nil
;and nil eval's to nil so no action
;is taken
)
)

Other Docs

Known Problems

Parameter Menu System269

Developers Programming Guide

)
)

In this example, we have one parameter, one rule, one change in


the change_list. You might guess there would only be one pass
through the steps of the rule interpreter. What actually happens
is as follows.
At step 1, change is bound to our only change '(value framus).
At step 2, rule is bound to the first (and only) rule.
( ((value framus)) ;rule index_list auto generated
framus_rule
;rule name start of rule
(not (= 2 (value 'framus))) ;if clause
(set_value 'framus 2) ;then clause
)
end of rule framus_rule

Step 3 checks to see if change '(value framus) is a member of


the index_list:
((value framus))

It is, so at step 4, noting (third rule) is if_clause:


(not (= 2 (value 'framus)))

However, in this example, the value of framus is not equal to 2.


If the user had typed in the integer 2 as the initial value, it would
not have been detected as a change; therefore, no change in
state would have occurred, and we would not have gotten this
far. This is because the if_clause would have evaled to t, and at
step 5 the then_clause would eval (set_value 'framus 2). The
set_value function is a menu assignment function which
immediately set the value of framus back to 2; you might guess
that the process would end, but it does not.
The menu assignment functions have a side effect which
assumes they actually make a change in the state_variable to
which they correspond, and they push that change on to the end
of change_list. There are assignment functions for manipulating
all the attributes of a parameter. The only thing that cannot be
changed is the order of parameters. Therefore, (set_value
'framus 2) when the value of framus was not 2; it caused a
state_variable change (value framus) to be pushed onto the
change_list:
( (value framus) )

Other Docs

Known Problems

Parameter Menu System270

Developers Programming Guide

resulting in the change_list becoming


( (value framus) (value framus) )

When we get back to our top level, we loop over change_list to


see if it is exhausted. We remove the first element and check for
more, which there now is. So the process continues. We find the
same rule and evaluate its if_clause again, which evals nil this
time, so we eval its else_clause (nil in this case, which does
nothing). Now back at the top again, we remove the change just
handled and find the change_list indeed empty this time. So rule
execution stops, and the menu is redisplayed. This is, of course,
a quite worthless menu because the user variable cannot be
changed by the user. The rule will immediately undo anything
he or she does. But the example does illustrate how rules and
lists interact.

Initialization Rules
In the event that the if-condition is t, the rule is unconditional
and termed an initialization rule. Such rules are run once and
only once immediately after menu parameter attributes are set
when the menu is first invoked. Initializations in included
menus are run after all initialization in the including menu have
been run, irrespective of where the :include parameters appear
on the displayed menu.

Procedural vs. Production


The important point in the preceding example and verbose
explanation is recognizing that when we got back to the top of
the outermost loop, we found there were more changes on the
change_list that resulted from actions taken inside the loop.
This is the advantage of a production rule system over
procedural type programming. Each rulecalled a production
or a production rule inference enginestands alone,
unconcerned about how or if the state variables in its if_clauses
came to be in any particular condition. The structure driving the
rules assures that whenever any change that any rule cares about
occurs, the conditions and actions called for in that production
are tested and taken. Contrast this to procedural programming,
where, if we want to call procedure ACTION whenever A = B,
we must make the test and call at every point in the program
where A could become equal to B.

Other Docs

Known Problems

Parameter Menu System271

Developers Programming Guide

The process of rule interpretation, which is described iteratively


in code and example above, can more elegantly be written
recursively. We illustrate it in this form because we believe you
may be more familiar with iteration than recursion.
We hasten to add that while technically this is expert system
technology, it is the oldest, most primitive and limited variant. It
cannot deal with ambiguity or uncertainty, nor is it directed at or
assured of some type of answer. It also can not explain how it
arrived at a particular conclusion after the fact, as can most
modern expert system shells.

Rules and Tips For Writing Rules


The following sections provide rule-writing tips.

Use Rule Names and Parameter Names Expressively


Rule names are not used by the system except as place holders.
They exist only to make a large collection of rules more
readable, which they will if you use them expressively. The
same applies to parameter_names, despite the use of names like
parm1 and parm2 in the examples. You should choose names
that express content, use, and actions.

Avoid Conditionals In Action Clauses


The following example illustrates the most common error in
rule-writing, where one rule is structured as follows:
(visibility_of_parm3
(= (value 'parm1) 1)
(if (= (value 'parm2) 1)
(do_show 'parm3)
(do_not_show 'parm3)
)
)

In this example, parm1 and parm2 can both be equal to 1 and


parm3 still not show. To understand why, assume at some point
in time parm1 and parm2 both equal 2. An action clause in
some other rule caused parm1 to be set to 1. Because value of
parm1 changed, and this rules if_clause involves the
state_variable (value parm1), this rules if_clause will be tested.
The if_clause evals, so the then_clause is evaled. The
then_clause is an if conditional, the second form of which is

Other Docs

Known Problems

Parameter Menu System272

Developers Programming Guide

evaled because parm2 is still 2, so parm3 is made not-visible.


Assume after this that some other rule action changes parm2 to
be 1. If this rule was ever executed again it would produce the
desired result, but the only thing that will cause this rule to
execute is a change in value parm1, not a change in value
parm2.
There are two possible fixes to this problem. The first fix is the
same as title of this section: avoid conditionals in action
clauses. This rule should be written:
(visibility_of_parm3
(and
(= (value 'parm1) 1)
(= (value 'parm2) 1)
)
(do_show 'parm3)
(do_not_show 'parm3)
)

In this case, the if_clause involves both parm1 and parm2


values so any change in either will cause this rule to execute
again and take the intended action. This type of badly formed
rule often leads to rule order dependency, the subject of the next
tip about writing rules.
The other way to fix this dilemma is not recommended, but is
included for completeness sake only. We could hand index the
original visibility_of_parm3 rule as follows:
( ((value parm1)(value parm2)) ;author customized
index_list
visibility_of_parm3
(= (value 'parm1) 1)
(if (= (value 'parm2) 1)
(do_show 'parm3)
(do_not_show 'parm3))
)

In this case, whenever the value of either parm1 or parm2


changes, this rule would be executed.
A third, more distasteful solution is to force the state variable
(value parm2) into the if_clause without changing the return
value of the expression. This could be accomplished by making
(value 'parm1) the first expression inside a progn statement and
returns only the last form it evaluates, which we would make
the actual if_clause.

Other Docs

Known Problems

Parameter Menu System273

Developers Programming Guide

Rule Order Should Never Matter


In the previous example, if both the rules that set parm1 and
parm2 equal to 1 occurred before the visibility_of_parm3 rule,
the first execution of this rule would have produced the
expected answer. The example illustrates how almost all
unexpected behavior is caused by one or more badly formed
rules.
Of course, achieving the desired behavior is most important, but
for maintenance programming reasons (when someone a year
from now tries to figure out what these two dozen rules where
supposed to do), it is best to assure that the rules are all well
formed and unambiguously express intent. One easy way to
almost guarantee this is to change the order of rules in the rule
list from time to time and see if the behavior is still as desired.
Develop a rule at the end of the rule list, then when thought to
be correct, move it to the top; if the behavior of the menu is still
correct, that rule is unlikely to have any unforeseen
peculiarities.

Think THEN, Then IF


In building up rules, think first about the action that needs to
take place. This may sound backwards, but it is perfectly
reasonable and less error prone. For example:
sometimes this parm should not show
or
sometimes this value should be recalculated

Each action which is determined in this way will usually best


become a then_clause in a rule. Avoid trying to think about all
the other things that should or could be set in conjunction with
the one under consideration. Once a needed action is fixed in
your mind, then and only then formalize the conditions that
describe the situations when the action should be taken. This
will form the if_clause of the rule. If, in considering an action,
you then recognize the conditions necessary for that action to be
taken are the same conditions as for some other rule, you may
bundle the two or more actions within a progn statement in the
action_clause. This approach leads to simple action clauses and
collections of rules that are much easier to read, understand, and
maintain.

Other Docs

Known Problems

Parameter Menu System274

Developers Programming Guide

A corollary between the think THEN, then IF rule and the


avoid conditionals in action clauses rule is: if_clauses are
likely to be more complicated expressions than action clauses.
This is because the simplest actions sometimes require
complicated and strict conditions; that is, the heavy use of
if_clauses. You can overdo pushing complexity into if_clauses,
which leads to our next rule.

Keep Rules As Simple As Possible (Simple = Small)


In using the preceding tips, you may often find yourself writing
if_clauses involving many ands, ors, ifs, and conds. These
can become difficult to comprehend, as illustrated in this
example:
(and (= 2 (value 'parm1))
(or (equal (value 'string_var) "one for the money")
(not (member '("Data" 1 "get some data")\
(type_desc 'parm4)))
(and (eq (error_list 'parm3) nil)
(or (= (value 'parm4) (* (value 'parm5)\
(value 'parm6)))
(= (value 'parm5) (value 'parm6))
)
)
)
)

It is hard to tell when or if the then_clause following an


if_clause, as illustrated above, would ever be called. This rule
would be better broken into several rules, each with identical
action and if clauses, as follows:
(and (= 2 (value 'parm1))
(equal (value 'string_var) "one for the money")
)
(and (= 2 (value 'parm1))
(not (member '("Data" 1 "get some data") (type_desc\
'parm4)))
)
(and (= 2 (value 'parm1))
(eq (error_list 'parm3) nil)
(= (value 'parm4) (* (value 'parm5) (value 'parm6)))
)
(and (= 2 (value 'parm1))
(eq (error_list 'parm3) nil)
(= (value 'parm5) (value 'parm6))
)

These four rules, each with the same simple action clause(s),
are much easier to comprehend than a single rule with an
if_clause as complicated as the earlier example. (There are, of
Other Docs

Known Problems

Parameter Menu System275

Developers Programming Guide

course, a number of other ways this clause could have been


broken up besides the way that is illustrated in this example.)

Do Not Use else_clauses


Except to Negate the Action of a Rules if_clause
When reading rules written by someone els, one of the most
confusing things to determine is the effect of else_clauses that
do something completely different than the then_clause did. If
the actions that are needed when the if_clause is non-nil are
completely different and unrelated to those that are needed if it
is nil, separate these actions clauses into two separate rules. One
should look just like the original with no else_clause, and the
second should look like this, relative to the original:
(negation_rule13 (not if_clause) else_clause )

Avoid Side Effects in If Clause


Assume you have a number of rules, each with only if and then
clauses, and all if clauses evaluate to nil. You might expect that
nothing could happen. But remember, if_clauses are evaled
often to see what action clause to act on. Beware that if the
if_clause itself calls assignment functions or has other side
effects, confusing things can begin to happen.

Other Docs

Known Problems

pwin276

Developers Programming Guide

pwin
pwin is a program that you can use to develop new menus. You
can execute pwin to see how the menu will appear on the
ProMAX screen; you do not have to put the menu into the
processes list and start ProMAX. Additionally, you can change
the menu file and immediately see the effect on the menu
behavior.
Before you execute pwin, make sure that your menu file is not
read-only and that the following environment variables, which
are also needed to run ProMAX, are set:

XFILESEARCHPATH (for all systems)


LM_LICENSE_FILE (for all systems)
PROMAX_DATA_HOME (for all systems)
PROMAX_HOME (for all systems)
LIB_PATH (for RS6000 systems)
LD_LIBRARY_PATH (for Sun, Solaris, SGI systems)
LD_LIBRARYN32_PATH (for SGI systems)

You may also need to set PROMAX_PORT_MENU_HOME if


your menu includes another menu. For more information about
setting up a ProMAX environment, refer to the System
Administration guide and/or the Promax command script.
Once you have set up a ProMAX environment, you can type:
pwin menuName.menu

This will pop the menu up onto the screen along with an emacs
editor window in which you can make changes to the menu. To
see the behavior of the menu, place the mouse pointer in the
menu itself. To change the menu, click on the part of the screen
that contains the source code. After the change, move the mouse
pointer back into the menu to see the effect of the change.
You can also execute pwin by typing:
pwin menuName.menu -t

This will bring up the menu without the emacs part of the
window. Resize the window so that it does not occupy the entire
screen, and start your favorite editor in or from another window.

Other Docs

Known Problems

pwin277

Developers Programming Guide

You can then make changes to the file in the editor window, and
observe their effects in the menu window when you move the
mouse pointer into the pwin window. Remember to save the
new edits to the disk file or pwin will not see them, since pwin
reads the menu disk file each time you return to the menu
window.

Other Docs

Known Problems

Example Macro: Display Shots with AGC278

Developers Programming Guide

Example Macro: Display Shots with AGC


A ProMAX macro is a menu file which combines previouslyexisting ProMAX menus into a new menu file. A macro can
show any, none, or all of the parameters from the original
menus to the user. The value of parameters that are not shown to
the user are set within the menu.
The purpose of a macro is to combine several processing steps
into a single menu and to require the user to select only the
minimum number of processing parameters. An example
ProMAX macro is shown below. This macro is called Display
Shots with AGC; it combines Disk Data Input, Automatic Gain
Control, and Screen Display into a single menu. The menu only
has four parameters that need to be selected. The rest of the
parameters are set within the menu to values that are
appropriate to a flow which is used to quickly check the quality
of seismic shot records. Even a relatively unexperienced data
processor or unexperienced ProMAX operator could set up and
parameterize Display Shots with AGC, while that same
operator might have difficulty selecting the 50 parameters in a
flow that had Disk Data Input, AGC, and Screen Display.
'(
name: DISKREAD
label: "Display Shots with AGC"
value_tab: 28

parameter: LABEL
text: "Select trace data file"
type: function:
type_desc: (dataset_list datasets)
value: "no entry"
;selected_item: "* No Datasets Found *"
selected_item: "INVALID"
mouse_text: "Use Mouse Button 1 to select a dataset file\
description from the DATASETS menu."

parameter: KEYLIST
text: " SOURCE list to display"
type: edit:
type_desc: (25 80 5 " FORMAT: Shot1ShotN,ShotM,ShotI,etc/
EXAMPLES: 1,5,9,13,27,30-40,47/ 1-10/ 11-20(2)/ \
1-10000(50),1005/
HELP: EMACS Editor Widget (scroll with down/up arrow\
keys)
CURSOR MOVEMENT: Use the arrow keys:->,<-,etc.;Point\
the mouse cursor,click B1

Other Docs

Known Problems

Example Macro: Display Shots with AGC279

Developers Programming Guide

CM: Ctrl-AMove the cursor to the BEGINNING of the\


current line
CM: Ctrl-EMove the cursor to the END of the current line
EDITING: All keyboard entry is in 'insert' mode
E: Backspace, Delete keysDelete one character to the\
LEFT of the cursor
E: Ctrl-D Delete one character to the RIGHT of the\
cursor
E: Ctrl-KKILL to the end of the line (from the cursor)
E: Ctrl-YYANK back the contents of the kill buffer;\
'Cut and
paste'; (Can move the cursor first) " 3 )
value: "1-10000"
mouse_text: "Use Mouse Button 1 to access the editor and\
define your desired input source order list."
parameter: AGCLEN
text: "AGC operator length"
type: typein:
type_desc: ( real: 7 1.0e-5 nil )
value: 500.0
mouse_text: "Amplitude estimation operator length in\
milliseconds for sliding gate AGC."
parameter: X_SERVER
text: "Select display DEVICE"
type: :typein
type_desc: (:string 32)
:value "This Screen"
mouse_text: "'This Screen' for current display or type\
in a display name to override the current display
default."
exec_data: (
("DISKREAD"
("SPECIAL"
("TOOLTYPE"
implicit: "INPUT")
)
("GENERAL"
("version" implicit: "@(#)display_shots.menu
\
50.4 9/8/93" )
("VERSION"
implicit: 0.1)
("LABEL"
implicit: (value 'LABEL))
("SORTOPT"
implicit: 1 )
("PKEYNAM"
implicit: "SOURCE " )
("SKEYNAM"
implicit: "NONE
" )
("TKEYNAM"
implicit: "NONE
" )
("KEYLIST"
implicit: (value 'KEYLIST))
("THDRONLY" implicit: 0 )
("SAMPRATE" implicit: 0.0 )
)
)
("AGC"
("GENERAL"
("MODE_AMP" implicit: 1 )
("AGCLEN " implicit: (value 'AGCLEN))
("MODE_WIN" implicit: 2 )
("MODEZERO" implicit: 1 )

Other Docs

Known Problems

Example Macro: Display Shots with AGC280

Developers Programming Guide

)
)
("TR_DISPLAY"
("GENERAL"
("X_SERVER" implicit:
(if (= (value 'X_SERVER) "This Screen")
(where_promax_displays)
(value 'X_SERVER)))
("TSTART"
implicit: 0.0 )
("TEND"
implicit: 8000.0 )
("NTR_SCRN" implicit: 0 )
("NEN_SCRN" implicit: 1 )
("GAP"
implicit: 0 )
("SCROLL"
implicit: 0 )
("XMAGNIFY" implicit: 1.0 )
("YMAGNIFY" implicit: 1.0 )
("DISPMODE" implicit: 2 )
("VARBIAS" implicit: 0.0 )
("AUTOSAVE" implicit: 1 )
("NIMAGES" implicit: 2 )
("NBATCH"
implicit: 1 )
("DIRECT"
implicit: 1 )
("POLARITY" implicit: 1.0 )
("TIMELINE" implicit: 100 )
("TIMEBOLD" implicit: 1000 )
("TIMEANN" implicit: 500 )
("LKEYNAM1" implicit: "SOURCE " )
("LABLMOD1" implicit: 3 )
("LABLINC1" implicit: 5 )
("LKEYNAM2" implicit: "CHAN
" )
("LABLMOD2" implicit: 2 )
("LABLINC2" implicit: 5 )
("POSITION" implicit: 0 )
("CLIP"
implicit: 2.0 )
("MODSCALE" implicit: 1 )
("ASCALAR" implicit: 1.0 )
("SCALEOPT" implicit: 1 )
("LMFRDATA" implicit: 0 )
("SCRN_MIN" implicit: -10.0 )
("SCRN_MAX" implicit: 10.0 )
("INTERP"
implicit: 1 )
("SPLT_ENS" implicit: 1 )
)
)
)
rules: (
(test_host_name (NOT (= (value 'X_SERVER) "This
Screen"))
(progn
(setq temp (host_valid_p (value
'X_SERVER)))
(if temp
(add_error 'X_SERVER temp)
(set_error_list 'X_SERVER temp)))
(set_error_list 'X_SERVER nil)
)
)
)

Other Docs

Known Problems

Example Macro: Display Shots with AGC281

Developers Programming Guide

The form of a macro menu is very similar to that of a regular


menu. There is a Menu Heading and a section for Parameter
Specifications, which only specifies those parameters that the
user is to be shown. There is an exec_data section, in which
modules to be executed are listed and the parameter values for
each module are set, either via the menu parameters or by being
explicitly specified with a numerical value or character string.
Finally, there is a rules section, which primarily governs the
behavior of the parameters, such as which parameters will be
shown to the user. Writing a macro normally involves cutting
and pasting existing menus and filling in appropriate values for
those parameters that are not shown to the user.

Other Docs

Known Problems

Example Macro: Display Shots with AGC282

Other Docs

Developers Programming Guide

Known Problems

283

Developers Programming Guide

Helpfiles

Documentation is an important part of the ProMAX system.


You should write a helpfile for your new process if it is going to
be used in a production processing environment. Please contact
any member of the Documentation Department for assistance.
This chapter describes how to make a helpfile for your new
process and display it in the ProMAX help system.

Topics covered in this chapter:

Other Docs

FrameMaker-formatted Helpfiles
Starting FrameMaker
Creating a New Helpfile
Editing a Helpfile
Working with FrameMaker Files
Helpfile Organization
Example Helpfile
Theory
Usage
References
Parameters
Interactive Display
Common Error Messages
Customizing the User Interface
Hypertext

Known Problems

FrameMaker-formatted Helpfiles284

Developers Programming Guide

FrameMaker-formatted Helpfiles
At Landmark, we use Adobe FrameMaker to generate and edit
most of our online and printed software documentation. This
chapter describes how to create and edit FrameMaker-formatted
helpfiles. The Documentation Department is also available to
help with formatting or style issues, such as word usage.

Starting FrameMaker
Follow these steps to start FrameMaker at Landmark:
1.

Login to Spitfire

2.

cd /usr/local/frame/bin

3.

setenv DISPLAY your_workstation:0

4.

maker

Creating a New Helpfile


Follow these steps to create a new helpfile from a template:
1.

Click on Open and select any helpfile from the latest


working directory.

2.

Select Save As from the File menu and enter a unique


file name. The filename should have the format
process_name.lok

3.

Replace the contents of the helpfile template with your


text.

Editing a Helpfile
Follow these steps to edit an existing helpfile:
1.

Other Docs

Click on Open and select the helpfile.

Known Problems

FrameMaker-formatted Helpfiles285

2.

Developers Programming Guide

Unlock the file (if it is locked) with the following keystroke


sequence:
<Ctrl>-r, <shift>-F, l, k (commas separate
keystrokes)

You can tell a helpfile is locked if it appears without the


menu options across the top of the window. If you want to
edit the document, the file must be unlocked; if you want to
activate the hypertext, it must be locked (use the same
keystroke sequence lock the file).
3.

Make your changes and save the file.

Working with FrameMaker Files


Always edit the master copies of the helpfiles in the latest
release directory of $PROMAX_HOME/port/help. Please do
not make a personal copy of a helpfile, edit it at your leisure,
and then return the copy to $PROMAX_HOME/port/help.
While you are working on your copy, someone else may edit the
original; when you return yours to the directory, you will wipe
out the other persons edits.
In the course of working with helpfiles, you may encounter a
number of files that FrameMaker automatically generates. The
following sections describe these files.

Other Docs

Known Problems

FrameMaker-formatted Helpfiles286

Developers Programming Guide

Lock Status Files (*.lck)


The built in file locking feature in FrameMaker prevents
parallel edits. If someone attempts to open a file you are editing,
they will get the following message:

File In Use Message


This information comes from a lock status file that is written
when you open the file. When someone else attempts to open
the file, FrameMaker displays the contents of the lock status
file.
When you get this message check the date. If the date is:

Other Docs

recent (one day or so), then someone is now editing the file

old, then someone was editing the file, probably left it open
in FrameMaker, went to lunch, and Framemaker closed
abnormally, such as if the host rebooted or the X-terminal
crashed. Since the file was never exited properly, the lock
status file is still present, even though no one is currently
editing the file. To be safe, check with the person listed in
the warning message dialog box. If they are not using the
file, then click the Reset file lock checkbox and click
Continue to proceed. If you simply want to look at the
file, just click Continue on the message dialog. If you
then do try to save the file, the warning message will
appear again.

Known Problems

FrameMaker-formatted Helpfiles287

Developers Programming Guide

Recover files (*.recover)


Sometimes when you open a FrameMaker file, you will get a
message stating, A recover file exists. This warning means
that a recover file was made while frame was crashing during an
earlier editing session. Since the integrity of this file unreliable,
do no open the recover file.

Autosave Files
Autosave files are automatically generated by FrameMaker
while you have a file open. The save interval can be specified in
the Preferences option under the File menu. The default has
autosave turned on and set to 5 minutes. Autosave versions of
files are reliable as long as autosave is turned on.

Backup Files (*.backup)


FrameMaker documents are set so that whenever a file is saved,
the previous version of the file is renamed to
helpfile_name.lok.backup. This file is usually present, even if
the document is exited normally. You can open the backup file
using Open.

Other Docs

Known Problems

Helpfile Organization288

Developers Programming Guide

Helpfile Organization
The following pages describe the organization of a helpfile. We
have included examples to make writing your helpfile easier.
FrameMaker helps you organize your information with
paragraph and character formats. Paragraph formats have names
that correspond to the sections to which they are typically
applied. For example, the title of a helpfile uses the paragraph
format Helpfile Title. The list of predefined paragraph formats
should handle most of the documentation formatting issues that
you might experience when creating a ProMAX helpfile. Please
try to avoid customizing the formats. The actual body of the
documentsuch as the text that you are reading nowuses the
text or body paragraph format. You can modify the text with
character formats, but use these modifications sparingly and
only as needed for clarity.

Other Docs

Known Problems

Example Helpfile289

Developers Programming Guide

Example Helpfile
This section provides the purpose and a short description of a
process. Begin the first sentence with the exact process name
and bold it. The following paragraph provides an example:
Differential Autostatics measures time shifts between
unstacked traces in common receiver and shot gathers.

Theory
The theory section is an explanation of how a process
accomplishes its purpose. Write this with your audience in
mind. Your audience has a good knowledge of geophysics and
seismic processing; therefore, you do not need to define P-wave
or S-wave, nor do you need to include a discussion of
Zoeppritzs equations. Consider the 90% rule: mention what
90% of our clients will want to know. The following two
examples illustrate two different but concise theory discussions:

Theory Example 1
The spectral shaping algorithm has two modes of application.
The first scales all frequency components of the data to a
specified contour, while maintaining the original phase
relationships. The second multiplies all frequency components
by the specified contour also without changing the phase. The
contour is defined by a series of frequency-amplitude pairs. The
amplitudes may be given as a percentage of the maximum
amplitude, or as a dB value relative to 1.0.

Theory Example 2
Spectral analysis of the results of IRLS L1 decon show
spectral whitening within the bandwidth of the original data.
The IRLS system is
A

A X = A

W Y where:

A X = Y and where:
A = Convolution Matrix, (rows columns)

Other Docs

Known Problems

Example Helpfile290

Developers Programming Guide

= transpose of A

W = diagonal weighting matrix


X = column vector of filter coefficients
Y = trace values being predicted
The elements of W are computed from the prediction error of
the past iteration. Each Y is predicted by the filter X vector
dotted into the corresponding row of A (past trace values).
W is initially set to the identity matrix, then updated for the next
iteration by:
W i = Y i A i, j X j ( L1 norm minimization )
The above system becomes:
C X = D where the main diagonal of C is augmented by
white noise, and then solved for X by Gauss-Seidel iteration.

Usage
The Usage section discusses how to use the process and
includes a description of the input/output headers. For instance,
what kind of data does the process operate upon? What must be
done first in order to use the process? What typically comes
after the use of the process? In this section, you fit the process
into the big picture of using ProMAX. The following paragraph
illustrates one way to write the Usage section:
Header Output: Tau-P creates new header entries called
SLOWNESS, TAUMIN, and TAUPIN. SLOWNESS is the P
value for the trace, TAUMIN is the Tau value of sample one of
the trace, and TAUPIN contains information used by the inverse
transform. Required input trace headers are CDP and OFFSET
for prestack data and CDP, CDP_X and CDP_Y for stacked
data.

References
If you use the 90% rule discussed in the preceeding theory
section, you can use the References section to supply our clients

Other Docs

Known Problems

Example Helpfile291

Developers Programming Guide

with the remaining 10% of the information about a process. Cite


any important or relevant publications that you used in the
research of your process. Use the following formats for
references:

Paper from journal


Authors last name, initials, year. Title of paper (capitalize only
proper nouns). Journal, v. x, p.xx-xx.

Books
Authors last name, initials, year. Book title (capitalize only
proper nouns). City of publication, publisher, xxx p.
Refer to the SEG Instructions to Authors for more information
on references.

Parameters
Write the parameter exactly as it appears in the process.
The parameter explanation should be as clear and concise as
possible. Our clients should know what input is expected for
any given parameter within the first two sentences. It is also
helpful if you include the default or expected input range for all
parameters. For clarity, we are using the following styles:

The parameter requires hand entered information, such as:


Maximum trace length to display
Enter the maximum trace length in ms.

The parameter requires a selection, such as:


Has NMO been applied
Select Yes to display NMO applied data.
or

Other Docs

Known Problems

Example Helpfile292

Developers Programming Guide

Types of trace statistics to compute


Select trace statistics to compute and write to the TRC database.
The statistics include:

TRC_AMPL: average trace energy

FB_AMPL: average first break energy

PRE_FB_A: average pre-first break energy

The parameter appears after another parameter is selected, such as:


Percent velocity scale factor
This appears if Yes to Adjust output velocities by
percentages?. Enter the percentages to scale velocities in
time and space. An example of the format is given in the edit
window.
or
Minimum velocity
This appears if Calculated or 1/v2 to Velocity input.
Enter a minimum velocity.......
The preceeding sentences are not grammatically correct, but we
use the structure in order to give our audience a concise
statement of when this parameter appears in a process.

Interactive Display
Several ProMAX processes are interactive. The optional
Interactive Display section comes after the Parameters section
and describes how the interactive display operates. For a good
example, see Trace Display.

Common Error Messages


Common Errors Message is another optional section that
follows the Parameters section. For an example, see GeoQuest
Horizon Output.

Other Docs

Known Problems

Example Helpfile293

Developers Programming Guide

Customizing the User Interface


Customizing the User Interface is another optional section. The
System Administration manual covers most of the information
that our clients will need for customizing their user interface,
but if you need to include additional information, see Trace
Display.

Other Docs

Known Problems

Hypertext294

Developers Programming Guide

Hypertext
Hypertext links documents in the online help system. Hypertext
is a word or group of words that, when clicked upon, will cause
a jump to a different part of the current document or to an
entirely different document. The hypertext character format
(which appears as red italics) helps the reader identify
hyperactive text. However, in addition to marking the text with
the hypertext character format, you will also have to embed the
actual hypertext jump commands in your document.
Not every helpfile will have or should have hypertext in it. It can
be a very valuable aid to the reader, but most simple helpfiles do
not need it. Please notify the Documentation Department if your
helpfile needs hypertext links.

Other Docs

Known Problems

295

Developers Programming Guide

Code Standards

This chapter outlnes the standard coding practices that should


be used in ProMAX coding. The goal is to produce source code
that is standardized and easy to maintain. The most important
guideline is this: write your code with the expectation that
someone else will be trying to understand it.

Topics covered in this chapter:

C Coding Standards
FORTRAN Coding Standards
Portable Code

Other Docs

Known Problems

C Coding Standards296

Developers Programming Guide

C Coding Standards
At Landmark, we use Recommended C Style and Coding
Standards by Cannon et. al. as a general coding guideline and
make the following additions:

Other Docs

1.

Comment the code liberally but intelligently. Very few C


programmers provide enough comments in their code to
allow other programmers to easily understand it.
Comments should answer the question What is going on
in this block of code? On the other hand, comments
should not state the obvious or repeat what is in the code. If
you spend much time explaining yourself during code
walk-throughs, your comments are inadequate.

2.

Do not patch bad code, rewrite it! Rewriting code is often


less work than you would expect and usually dramatically
improves it. Even good software eventually wears out as
new features are added.

3.

Always choose clarity over efficiency on the initial


development of an application. Code can be modified later
if speed improvements are necessary. In general, only
processes that are performed on a sample by sample or
pixel by pixel basis need to be optimized. If the program
does not work or is not maintainable, it does not matter
how fast it is.

4.

Always measure program speed before attempting to make


efficiency changes (which may not be required). Use the
profiler to find slow code structures. If too much
modification is needed to make code efficient, a new
algorithm is probably needed.

5.

Functions should be simple and singular in purpose. The


length of functions should generally be less than about four
pages each. If they are longer, you may be combining
functionality that should be separated.

6.

If you use the same code in several places, make it a


function. Some discretion is warranted; for example, three
lines of code used in two places should not be replaced by
a function. In many cases, a routine already exists that
would do the job. Also, when you create a new routine,
consider whether it would be of use to the rest of the

Known Problems

C Coding Standards297

Developers Programming Guide

programming staff; if so, include it in the libraries and the


documentation.
7.

Never make a copy of a function and then modify it


slightly. If the original function is not quite what you want,
it is better to add the desired functionality than to have two
copies that are nearly the same.

8.

If a function returns a special value for error conditions


(such as a NULL pointer), it should also set the external
variable errno with a value that does not overlap the system
values or the values of any other ProMAX function. See
/advance/port/include/*err.inc and
/advance/port/include/*err.h for error values that are
already reserved. New error values should be handled in
the function reportPromaxErr().

9.

Variable and function names should be long enough to


clearly express their meaning. When naming subroutines
and functions, avoid obvious names that might be defined
elsewhere in the system.

10. Use underscores OR mixed case consistently to delimit


words within a function or variable name, but not both.
11. In addition to using the assert facility, include fprintfs to
stderr that can be used later to diagnose problems, and
leave them in the production code. These statements should
be disabled by default, but should be enabled by setting the
environmental variable PROMAX_DEBUG.
12. If you are developing anything that is somewhat
complicated, include a main() that can be used to test the
functions later (do not forget to #ifdef out the main() for
production purposes). The main should contain internal
checks that can be used to determine if the functions are
producing good results.
13. Use Purify on your code as standard procedure before you
check it in to the production libraries.

ProMAX C Routine Documentation


When writing a C language routine intended for general
usage, please use the following source layout for

Other Docs

Known Problems

C Coding Standards298

Developers Programming Guide

documenting its purpose, arguments, return values and


special notes:
Place the return value (if any) on the same line as the
function body declaration, i.e. use
float cvtibm(float ibm_in)

and not
float
cvtibm(float ibm_int)

Place the documentation as a comment block immediately after the function declaration. Begin the comment
lines with /********** (a forward slash followed by at least
10 asterisks) and end the block of lines with **********/
(at least 10 asterisks followed by a forward slash.) Internal sections of the documentation should be separated
by a row of (at least 5) asterisks.
Begin the documentation comments with one or more
lines describing the purpose of the routine.
Follow the purpose section with a description of the
arguments and return value. Do not describe more than
one argument per line. Divide this section into up to
three groups separated by blank lines, entitled "Input:",
"Output:" and "Returned:". If an argument is both an
input and an output, list it in both sections.
After the argument section, place any further sections
you may want, for example Notes, References, and
Author sections.
The following code shows an example of recommended C
documentation style.
float cvtibm(long ibm_in)
/*******************************************************
Convert IBM hexadecimal floating point numbers
********************************************************
Input:
in_ibm IBM floating point number to be converted
Returned:native floating point equivalent
********************************************************
Notes:
Converts to IEEE standard format and uses the xdr library
to convert from there.
********************************************************
Author:Anonymous, Jan. 24, 2000
*******************************************************/
{ /* begin function body ... */

Other Docs

Known Problems

FORTRAN Coding Standards299

Developers Programming Guide

FORTRAN Coding Standards


This section outlines general FORTRAN coding practices.
Do not patch bad code, rewrite it! Rewriting code is often less
work than you would expect and usually dramatically improves
it. Even good software eventually wears out as new features are
added.
Avoid hidden interdependencies, particularly FORTRAN
common blocks. As a rule of thumb, do not create a common
block until the number of calling arguments to a routine is 20 or
more. If you do break down and use a common block, be sure
that it is placed in an include file and not directly in the code.
This ensures that you will not give the same variable different
names in different places, and that you will not change the
common block in one place and forget to change it in another.
Avoid fixed length arrays. Not only do they waste memory
resources, but they are rarely assured to be long enough in all
cases. Use the memory management routines, even in standalone programs. One of the features of ProMAX is that there are
virtually no built-in limits.
When you use the memory management routines, you should
normally pass the buffers into routines where they can be
assigned a meaningful name and indexed starting at array
element 1. In other words, avoid this type of code:
CALL MEM_RESBUFF( LENGTH, IX_WORK, IERR )
DO 100 I=1,LENGTH
ISPACEz(IX_WORK+I-1) = X(I)
100 CONTINUE

Always choose clarity over efficiency on the initial development


of an application. Code can be modified later if speed
improvements are necessary. In general, only processes that are
performed on a sample by sample or pixel by pixel basis need to
be optimized. If the program does not work or is not
maintainable, it does not matter how fast it is.
Always measure program speed before attempting to make
efficiency changes (which may not be required).
If too much modification is need to make code efficient, a new
algorithm is probably needed.

Other Docs

Known Problems

FORTRAN Coding Standards300

Developers Programming Guide

Subroutines and functions should be simple and singular in


purpose. The length of a subroutine or function should
generally be less than about four pages. If they are longer, you
may be combining functionality that should be separated.
If you use the same code in several places, make it a subroutine
or a function. Some discretion is warranted; however, three
lines of code used in two places should not be replaced by a
subroutine. In many cases, a routine already exists that would
do the job. Also, when you create a new routine, consider
whether it would be of use to the rest of the programming staff.
True constants should be set using the PARAMETER statment,
as should any immutable values such as PI or E (or any other
magic numbers).
If you have a very complicated expression having many levels
of parentheses, break it up into two or more expressions.
Do not rely too heavily on FORTRAN precedence among
operations; use parentheses instead. The precedence is:
exponentiation, multiplication and division, and then addition
and subtraction.
Never mix variables types in an expression. Always use type
conversion functions such FLOAT, INT, NINT, etc.
Do not use real values to index into arrays such as this example
(some compilers will not accept this at all):
X = 1.0
RWORK(X) = Y

General Text File Format


The maximum line length is 72 columns.
Use fortran-mode in emacs when writing FORTRAN code.
No tabs should exist in any FORTRAN code or include files.
When you are using fortran-mode in emacs, tabs will be
converted to spaces.
All indentations (in loops and IF structures) should be 4 spaces.
If your code is deeply nested and you run out of space, you

Other Docs

Known Problems

FORTRAN Coding Standards301

Developers Programming Guide

probably have a design problem and should be breaking


segments of the code into individual routines.
Statement labels should be used on all DO loops, and each DO
statement should reference a unique statement label. Bad
example:
DO I=1,10
X(I) = 0.0
ENDDO
DO 100 J=1,10
DO 100 I=1,10
X(I,J) = 0.0
100
CONTINUE

Good example:
DO 110 J=1,10
DO 100 I=1,10
X(I,J) = 0.0
100
CONTINUE
110 CONTINUE

Statement labels should appear in ascending order in the code


and should have an increment of 10 or more to allow insertion
of new labels without destroying the ordering.

Variable Naming and Declarations


All FORTRAN code should be in upper case, with comments in
lower case. On occasions when you make a temporary change
to some code, reverse this convention to make the code stand
out as temporary.
Variable names should be long enough to clearly express their
meaning. We do not adhere to the maximum variable name
length of 8 as specified in the FORTRAN 77 Standard. The
same is true for subroutine and function names. When naming
subroutines and functions, avoid obvious names that might be
defined elsewhere in the system.
The IMPLICIT NONE statement must appear in all code,
forcing all variables to be declared.
Despite all variables being declared, the FORTRAN default
types should be adhered to. All integer variables should begin
with I-N, and all others are real, with the exception that only
character variables should begin with C.

Other Docs

Known Problems

FORTRAN Coding Standards302

Developers Programming Guide

Avoid non-standard variable types, such as I*2, I*1, etc. If you


need to use these variables types, you probably should be
programming in C.
Know the difference between character strings and character
arrays. A character string is declared as:
CHARACTER CWORK*8

while a character array is declared as:


CHARACTER CWORK(8)

These variable types are as different from each other as


LOGICAL is from REAL*8. The important difference is that a
character string has an associated length. Character arrays can
be safely passed to C routines, while character strings cannot
(there is no way to know where the length will go when a
character string is passed). In general character strings create
portability problems and should be used sparingly.
Be sure that character arrays are null terminated before you pass
them to C routines. Null termination means that a CHAR(0)
exists in the array after the last significant character.
If a routine takes a character string as an input argument and the
routine will need to recognize the character string (a name for
example), be sure that character constants are padded out to the
correct length. For example, this code will fail on some
machines (8 characters are expected):
CALL EX_GETPARM( 'XLOC', 1, XLOCATION )

but this will always work:


CALL EX_GETPARM( 'XLOC

', 1, XLOCATION )

C preprocessor
All ProMAX FORTRAN code is run through the C
preprocessor before it reaches the FORTRAN compiler. The
primary benefits are the use of the #ifdef and #include
statements. The syntax of an include statement is:
IMPLICIT NONE
#include "foo.inc"
#include "header.inc"

Other Docs

Known Problems

FORTRAN Coding Standards303

Developers Programming Guide

rather than:
IMPLICIT NONE
INCLUDE 'foo.inc'
INCLUDE '/usr/ProMAX/sys/misc/header.inc'

Note that the use of full path names for include files is
disallowed (use the -I directive in the compiler).
Be aware that the C preprocessor knows nothing about Fortran
source code format and will happily generate lines longer than
72 characters. Judicious use of continuation lines are suggested.
For example:
#define VLONG 'a very very long string to substitute...'
CHARACTER*(*) TITLE
PARAMETER(TITLE=
&VLONG
&)

maximizes the space available for the VLONG text string.


Another thing to avoid within Fortran source is the character
combination /*, i.e. the beginning of a C comment. Most C
preprocessors will by default remove C comments. All
characters from that /* up to any following */ will disappear,
leading to very confusing Fortran compiler error reports.

Comments
Comments should be used to adequately explain the structure
and intent of the code. Poorly commented code is difficult for
the author to maintain and impossible for someone else to
maintain. If you spend much time explaining yourself during
code walk-throughs, your comments are inadequate. No one
ever errors on the side of too many comments.
Comments should begin with C ..... for readability. The first
letter of the comment should always line up with the code that
follows. Put comments inside the part of an IF structure that
applies to the comments.
Each subroutine should have a reasonable description that
explains it basic purpose.

Other Docs

Known Problems

FORTRAN Coding Standards304

Developers Programming Guide

White Space
Do not be afraid to use white space. Blank lines can be used to
further clarify the structure, and spaces between the elements of
a statement make it easier to read. A statement like:
IF ( GL .LT. 0.0 .AND. GE .GE. GMAX ) THEN

is easier to read than:


IF(GL.LT.0.0.AND.GE.GE.GMAX) THEN

just like:
Source code statements should read like sentences
is easier to read than:
Amassofcharacterswithoutblanksisdifficulttoread
Avoid too many blank lines; however, it is nice to be able to see
a reasonable number of lines of source code on the screen at the
same time.

Code Structure
Do not use multiple IF conditional tests on the same variable in
the same block of code if an ELSE or ELSEIF will do the same
task.
Bad example:
IF ( NSAMPS .EQ. 1 ) X = Y
IF ( NSAMPS .EQ. 1 ) J0 = 0

Even worse:
IF ( NSAMPS .EQ. 1 ) X = Y
IF ( NSAMPS .EQ. 2 ) X = Y2
IF ( NSAMPS .EQ. 1 ) J0 = 0

Good example:
IF ( NSAMPS .EQ. 1 ) THEN
X = Y
J0 = 0
ELSEIF ( NSAMPS .EQ. 2 ) THEN

Other Docs

Known Problems

FORTRAN Coding Standards305

Developers Programming Guide

X = Y2
ENDIF

GOTO statements should be avoided and computed GOTO


statements are forbidden. Multiple RETURN statements within
a routine should also be avoided.

Miscellaneous
The source code for a particular processing tool should be kept
in a unique directory and include the associated include file.
Keep FORMAT statements close to the code where they are
being used, or preferably imbed them in the code like this:
READ (*,(A8,3I8)) CWORK, I, J, K

In general, you should not need to use many FORMAT


statements, since most I/O is handled for you by the Executive,
the error routines, and the graphical user interface.
Be alert for null values in the system (this is our most common
source of bugs). For example, this code will crash if the CDP
number in the trace header is null:
ICDP = ITHDR(IH_CDP)
X(ICDP) = 0.0

and this code will crash if CDP is not defined in the header:
ICDP = ITHDR(ICDPz)
X(ICDP) = 0.0

Purify
14. Use Purify on your code as standard procedure before you
check it in to the production libraries.

ProMAX Fortran Routine Documentation


When writing a Fortran language routine intended for general
usage, please use the following source layout for documenting its purpose, arguments, return values and special notes:
Place the documentation as a comment block immediately before the FUNCTION or SUBROUTINE definition.
Other Docs

Known Problems

FORTRAN Coding Standards306

Developers Programming Guide

Begin each line of the documentation block with the two


character sequence CX. Use CX-prefixed blank lines to
improve readability between sections of the documentation.
Begin the documentation comments with a duplicate of
the SUBROUTINE or FUNCTION statement complete
with all its arguments. For internal readability, bracket
this between 'CX-----------------------------' lines.
Follow this with a Description: section bfirefly giving the
purpose of the routine.
Next document the routines arguments and return
value. Do not describe more than one argument per line.
Divide this section into up to three groups separated by
blank lines, entitled "Input:", "Output:" and "Returned:".
If an argument is both an input and an output, list it in
both sections.
After the argument section, place any further sections
you may want, for example Notes, References, Author
and See Also sections.
Finish with a final CX---------------------------------- for
consistency.
The following code shows an example of recommended
Fortrandocumentation style.float cvtibm(long ibm_in)
CX-----------------------------------------------------CX
REAL FUNCTION CVTIBM(IBM_IN)
CX-----------------------------------------------------CX
Description:
CX
Convert IBM hexadecimal floating point numbers
CX
CX
Input:
CX
IN_IBMIBM floating point number to be converted
CX
CX
Return value: Native floating point equivalent
CX
CX
See Also:
CX
CVTIEEE
CX
CX
Author:Anonymous, Jan. 24, 2000
CX-----------------------------------------------------REAL FUNCTION CVTIMB(IBM_IN)
INTEGER IBM_IN
etc.

Other Docs

Known Problems

Portable Code307

Developers Programming Guide

Portable Code
Since ProMAX products are offered on multiple hardware
platforms, it is important to make your code a portable as
possible. Portable code minimizes compiler and runtime errors
with new compiler releases, new hardware platforms, and new
operating systems. Here are some rules that have been derived
from experience.

Other Docs

1.

Never hard-code the size of any numerical type; always use


the sizeof() operator when programming in C.

2.

The size of a pointer is not the same as other numerical


types on all machines; do not make this assumption in your
code (particularly true on SGI 64-bit machines).

3.

Do not assume that a divide-by-zero operation is


acceptable to all machines. On some platforms this is a
hard error. Always protect from dividing by zero in your
code.

4.

Do not assume that all FORTRAN compilers initialize


automatic variables to 0 (particularly true on SGI 64-bit
machines).

5.

Be watchful for argument aliasing whereby the same


variable or array is passed to a subroutine under two
different names. In particular do not do this for output
arguments if there is a possibility that the same location
may be changed in both arguments. Note that ProMAX
does use argument aliasing when it passes the header array
twice, once as INTEGER and once as REAL. This
particular usage is safe because no location in the trace
header is simultaneously an INTEGER and a REAL.

Known Problems

Portable Code308

Other Docs

Developers Programming Guide

Known Problems

309

Developers Programming Guide

Man Page Reference

This appendix provides an overview of the UNIX man facility.

Topics covered in this chapter:

Using the Man Pages


Finding What You Want

Other Docs

Known Problems

Using the Man Pages310

Developers Programming Guide

Using the Man Pages


The man pages contain online information for selected C++, C,
and Fortran routines. You may use the UNIX man command if
you add $PROMAX_HOME/port/man to your MANPATH
environmental variable. You can access man pages via the
command:
$PROMAX_HOME/port/bin/aman

or simply aman if this directory exists in your path. aman is a


script that calls man after adding $PROMAX_HOME/port/man
to your man path.
The following list describes the key man pages:

Other Docs

c_promax: This man page will give you an overview of


the C ProMAX routines.

fortran_promax: This man page will give you an


overview of the Fortran ProMAX routines.

cs#: These man pages will give you information pertaining


to the C Section # of the man pages. Note that # represents
the section number to be referenced.

fs#: These man pages will give you information pertaining


to the Fortran Section # of the man pages. There may also
be an introduction section in the Fortran version.

Known Problems

Finding what you want311

Developers Programming Guide

Finding what you want


If you are not sure which routine you are looking for, you can
type the command
aman -k keyword

where keyword is the descriptive word for which you are


looking. For example, to find all of the routines that deal with
ProMAX tables, type aman -k table. This will give you a
long list of all of the C and FORTRAN routines. In this case, to
further limit the list, you can type the command
aman -k table | fgrep "C routine" | fgrep -i add

to list all C table routines that deal with adding points.


To see all ProMAX routines at once, type aman c_promax if
you are programming in C, or aman f_promax if you are
programming in FORTRAN.
You will see a man page with an overview of the system divided
into sections. There will be a short description of each section,
as well as a list of routines which have online man pages.
Decide on which routine you need from this man page. If you
need more information, narrow it down to a section and then
type aman fs# or aman cs#, where # is the number of the
section on which you desire information. After you determine
which routine you want information, type
aman [routine_name] where [routine_name] is the actual
name of the routine.

Other Docs

Known Problems

Finding what you want312

Other Docs

Developers Programming Guide

Known Problems

313

Developers Programming Guide

Appendix: Expanded Directory


Structure

This appendix lists the ProMAX Expanded Directory Structure.

Topics covered in this appendix:

Expanded Directory Structure

Other Docs

Known Problems

Expanded Directory Structure314

Developers Programming Guide

Expanded Directory Structure


$PROMAX_HOME

Other Docs

rs6000/ (sys/ -> rs6000/ on IBM RS/6000 machines)

bin/

promax

prospector

promaxvsp

promax3d

emacs

gmake

...

exe/

exec.exe

super_exec.exe

autostat.exe

dbmath.exe

...

showfile

...

lib/

libmaxexec.a

libmaxtool1.a

libmaxtool2.a

Known Problems

Expanded Directory Structure315

Other Docs

Developers Programming Guide

libmaxtool3.a

libmaxtool4.a

libmaxutil.a

libmaxui.a

libagfc.a

libXaw.a

libXhp.a

golden/ (rs6000 only)

geoquest/ (sparc only)

libsupport.a

...

sdi/ (-> ../nodist/lib/sdi/)

...

obj/

bin/

promax/

...

exe/

exec/

golden.a

libxcgm.a

...

c_exec.o

Known Problems

Expanded Directory Structure316

Developers Programming Guide

exec.o

toolcall.o

...

autostat/

...

lib/

maxtool/

cgmplot/

.cgmplot.o

.c_cgmplot.o

.cgmplot_combined.o

rf/

.cfstack.o

....

...

...

nodist/

lib/

sdi/

...

libxcgm.a

.
decmips/ (sys/ -> decmips/ on DEC MIPS Rx000
machines)
.

Other Docs

...

Known Problems

Expanded Directory Structure317

Other Docs

Developers Programming Guide

sgimips/ (sys/ -> sgimips/ on SGI MIPS Rx000 machines)

sparc/ (sys/ -> sparc/ on SUN SPARC machines)

...

port/

bin/

Makeexec

...

misc/

header.inc

color_tbl_b

...

fontimage0

fontimage1

...

menu/

promax/

Processes

agc.menu

...

prospector/

...

...

Processes

Known Problems

Expanded Directory Structure318

Other Docs

Developers Programming Guide

agc.menu

...

...

promaxvsp/

Processes

agc.menu

...

promax3d/

Processes

agc.menu

...

help/

promax/

agc.help

...

prospector/

agc.help

...

promaxvsp/

agc.help

...

promax3d/

agc.help

Known Problems

Expanded Directory Structure319

Other Docs

Developers Programming Guide

...

man/

man1/

gmake.1

...

...

include/

SCCS/

header.inc

cglobal.h

cpromax.h

cwp.h

...

private/

interface/

make/

advance.make

maxexec.make

maxprog.make

rs6000.make

...

...

...

Known Problems

Expanded Directory Structure320

Other Docs

Developers Programming Guide

X11/

Xaw/

SCCS/

Box.h

...

...

geoquest/

portable.h

portable.par

...

sdi/ ( -> ../nodist/include/sdi/)

cgm.h

portable.h

...

src/

bin/

promax/

emacs/

gmake/

...

...

...

...

Known Problems

Expanded Directory Structure321

Other Docs

Developers Programming Guide

...

exe/

exec/

Makefile

SCCS/

c_exec.c

exec.f

toolcall.f or toolcall.c

...

autostat/

Makefile

...

...

lib/

maxtool/

Makefile

agc/

.SCCS/

.agc.f

...

maxexec/

Makefile

SCCS/

Known Problems

Expanded Directory Structure322

Other Docs

Developers Programming Guide

table.f

ex.c

err.c

par.c

...

maxutil/

Makefile

c_promax/

.SCCS/

.hdr.c

....

table/

.SCCS/

.table.f

....

...

maxui/

Makefile

...

cwp/

Makefile

...

X11/

Known Problems

Expanded Directory Structure323

Other Docs

Developers Programming Guide

Xaw/

.Makefile

.SCCS/

.Box.c

....

...

...

...

nodist/

include/

sdi/

cgm.h

portable.h

etc/

config_file

...

data/

scratch/

...

...

Known Problems

Expanded Directory Structure324

Other Docs

Developers Programming Guide

Known Problems

325

Developers Programming Guide

Appendix: C Programming Examples

This appendix provides examples of introductory C


programming processes.

Topics covered in this appendix:

Example include files

cglobal.h

cpromax.h
Example simple processes

simple.menu

simple.c

ampRatio.c

Other Docs

Known Problems

Example Include Files326

Developers Programming Guide

Example Include Files


The following pages contain samples of two important .h files
in the ProMAX C environment, cglobal.h and cpromax.h. Both
files are kept in the ProMAX environment under the
$PROMAX_HOME/port/include directory. We encourage you
to look at the files sent with the release because they will reflect
the most recent changes.
The file cglobal.h gives you access to the global variables, such
as numsmp (number of samples per trace), along with a variety
of standard headers. The file cpromax.h contains the #include
statements for standard C .h files, such as math.h and stdlib.h.
It also contains function definitions for the ProMAX C
environment.

Other Docs

Known Problems

cglobal.h327

Developers Programming Guide

cglobal.h

/* C globals for ProMAX - equivalent to global.inc */


#ifndef CGLOBAL_H
#define CGLOBAL_H
/* define logical variables as integers */
typedef int logical;
/* character globals */
typedef struct globalCharStruct {
char cproj[16];
/* current project name */
char cline[16];
/* current line name */
char carea[16];
/* current area name */
char cflow[16];
/* current flow name */
char cpad[64];
/* pad to 128 */
} GlobalChar;
#ifdef DEFINE_CGLOBALS
#if defined (CRAY)
GlobalChar GLOBAL_CHARCZ;
GlobalChar *globalChar = &GLOBAL_CHARCZ;
#elif defined (CONVEX)
GlobalChar _global_charcz_;
GlobalChar *globalChar = &_global_charcz_;
#else
GlobalChar global_charcz_;
GlobalChar *globalChar = &global_charcz_;
#endif /* CRAY */
#else
#if defined (CRAY)
extern GlobalChar GLOBAL_CHARCZ, *globalChar;
#elif defined (CONVEX)
extern GlobalChar _global_charcz_, *globalChar;
#else
extern GlobalChar global_charcz_, *globalChar;
#endif /* CRAY */
#endif /* DEFINE_CGLOBALS */
/* miscellaneous globals */
typedef struct globalMiscStruct {
float exdatum; /* final processing datum elevation (if not variable) */
float vxdatum; /* final datum replacement velocity (if not variable) */
int iunits;
/* type of units (see choices below) */
logical i3d;
/* true if data is 3-D */
logical imultc; /* true if data is multi-component */
int ntrace;
/* number of traces used to initialize database */
logical icdpasn; /* true if CDP bins have been assigned */
logical igeoasn; /* true if geometry has been assigned */
int ipad[8];
/* padding to 16 words */

Other Docs

Known Problems

cglobal.h328

Developers Programming Guide

} GlobalMisc;
#ifdef DEFINE_CGLOBALS
#if defined (CRAY)
GlobalMisc GLOBAL_MISCCZ;
GlobalMisc *globalMisc = &GLOBAL_MISCCZ;
#elif defined (CONVEX)
GlobalMisc _global_misccz_;
GlobalMisc *globalMisc = &_global_misccz_;
#else
GlobalMisc global_misccz_;
GlobalMisc *globalMisc = &global_misccz_;
#endif /* CRAY */
#else
#if defined (CRAY)
extern GlobalMisc GLOBAL_MISCCZ, *globalMisc;
#elif defined (CONVEX)
extern GlobalMisc _global_misccz_, *globalMisc;
#else
extern GlobalMisc global_misccz_, *globalMisc;
#endif /* CRAY */
#endif /* DEFINE_CGLOBALS */
/* choices for globalMisc->iunits - type of units */
#define IENGLISH 1
#define IMETRIC 3
/* shorthand for easier typing and reading of code */
#define IUNITSz(globalMisc->iunits)
/* runtime globals */
typedef struct globalRuntimeStruct {
float samprat;
/* time sampling interval in milliseconds */
int numsmp;
/* number of samples per trace */
int ipsort;
/* physical primary sort flag (see choices below) */
int maxdtr;
/* maximum number of data traces per ensemble */
int idtyp;
/* primary data type (see choices below) */
int nth;
/* number of 4-byte words in trace header */
int mode;
/* processing executive mode (see choices below) */
int iounit;
/* Fortran I/O unit for output diagnostics */
int ipkey;
/* trace header index of primary sort key */
int iskey;
/* trace header index of secondary sort key */
int idate;
/* current date (seconds since 00:00:00 GMT, 1/1/70 */
int idomain;
/* domain type (see choices below) */
logical cleanup;
/* true if system is in cleanup mode */
logical ierror; /* true if system in error mode (trying to cleanup) */
logical igeom_match; /* true if header geometry matches database */
logical itrno_valid; /* true if trace number can index database */
logical init_only;
/* true if initialization phase only */
int ipad[15];
/* padding to 32 words */
} GlobalRuntime;
#ifdef DEFINE_CGLOBALS
#if defined (CRAY)
GlobalRuntime GLOBAL_RUNTIMECZ;

Other Docs

Known Problems

cglobal.h329

Developers Programming Guide

GlobalRuntime *globalRuntime = &GLOBAL_RUNTIMECZ;


#elif defined (CONVEX)
GlobalRuntime _global_runtimecz_;
GlobalRuntime *globalRuntime = &_global_runtimecz_;
#else
GlobalRuntime global_runtimecz_;
GlobalRuntime *globalRuntime = &global_runtimecz_;
#endif /* CRAY */
#else
#if defined (CRAY)
extern GlobalRuntime GLOBAL_RUNTIMECZ, *globalRuntime;
#elif defined (CONVEX)
extern GlobalRuntime _global_runtimecz_, *globalRuntime;
#else
extern GlobalRuntime global_runtimecz_, *globalRuntime;
#endif /* CRAY */
#endif /* DEFINE_GLOBALS */
/* shorthand for easier typing and reading of code */
#define NUMSMPz(globalRuntime->numsmp)
#define SAMPRATz(globalRuntime->samprat)
#define NTHz(globalRuntime->nth)
/* choices for globalRuntime->ipsort - physical primary sort key */
#define ICDP 1
/* cdp bin */
#define ISIN 2
/* source index number */
#define IRECSLOC 3
/* receiver surface location */
#define IOFFSET 4
/* offset */
#define ICHAN 5
/* channel number */
#define IUNKNOWN 6
/* none of the above */
/* choices for globalRuntime->idtyp - primary data type */
#define INORMAL 0
/* normal unstacked data */
#define IUP_HOLES 1
/* uphole data */
#define IUS_TRANS 2
/* transformed unstacked (e.g., frequency domain) data */
#define IST_TRANS 3
/* transformed stacked (e.g., frequency domain) data */
#define ISTACKED 7
/* normal stacked data */
#define ISNAPSHOTS 8 /* Movie Snap shots from finite difference modeling */
/* tape types (should NOT overlap with primary data types) */
#define IFIELD 9
#define IARCHIVE 10
#define IOTHER_TAPE 11
/* globalRuntime->mode - processing executive mode */
#define INTER 1
/* interactive */
#define IBACKG 2 /* background */
#define IBATCH 3 /* batch */
/* globalRuntime->idomain - domain type */
#define ITX 0
/* normal time-space domain */
#define IFX 1
/* frequency-space domain */
#define IFT 2
/* frequency-time domain */
#define IFK 3
/* frequency-wavenumber domain */
#define ITAUP 4
/* tau-p domain */
#define ISEMB 5
/* semblance domain */
#define IMBT 6
/* model-based transform */

Other Docs

Known Problems

cglobal.h330

#define IDEPTH 7

Developers Programming Guide

/* depth-space domain */

/* geometry globals */
typedef struct globalGeomStruct {
int minsloc;
/* minimum surface location number */
int maxsloc;
/* maximum surface location number */
int incsloc;
/* surface location number increment (always 1) */
int nrcvrs;
/* total number of live groups */
int maxtpr;
/* maximum traces per receiver ensemble */
int mincdp;
/* minimum cdp number */
int maxcdp;
/* maximum cdp number */
int inccdp;
/* cdp number increment (always 1) */
int numcdp;
/* total number of cdps */
int ntrcdp;
/* maximum cdp fold */
int minsin;
/* minimum source index number */
int maxsin;
/* maximum source index number */
int incsin;
/* source index number increment (always 1) */
int nsins;
/* total number of SINs (records of all types) */
int maxcps;
/* maximum channels per source */
int nshots;
/* total number of live sources */
int minofb;
/* minimum offset bin number */
int maxofb;
/* maximum offset bin number */
int incofb;
/* offset bin number increment (always 1) */
int nofbins;
/* number of offset bins */
float offbinc; /* offset increment between bins */
float offmax; /* longest offset of line */
int minchn;
/* minimum channel number */
int maxchn;
/* maximum channel number */
int incchn;
/* increment between channel numbers (always 1) */
int nslocs;
/* total number of surface locations of all types */
float x3dorig; /* x coordinate of origin of 3D grid (rel. to xref) */
float y3dorig; /* y coordinate of origin of 3D grid (rel. to yref) */
int nilines;
/* number of inlines */
int minilin;
/* minimum inline number */
int maxilin;
/* maximum inline number */
float xilnend; /* x coordinate of far end of first inline */
float yilnend; /* y coordinate of far end of first inline */
float dcdpiln; /* distance between CDPs in the inline direction for
* 3D; mean distance between CDPs for 2D */
int nxlines;
/* number of crosslines */
int minxlin;
/* minimum crossline number */
int maxxlin;
/* maximum crossline number */
float xxlnend; /* x coordinate of far end of first crossline */
float yxlnend; /* y coordinate of far end of first crossline */
float dcdpxln; /* distance between CDPs in the crossline direction */
int ipad[24]; /* padding to 64 words */
} GlobalGeom;
#ifdef DEFINE_CGLOBALS
#if defined (CRAY)
GlobalGeom GLOBAL_GEOMCZ;
GlobalGeom *globalGeom = &GLOBAL_GEOMCZ;
#elif defined (CONVEX)
GlobalGeom _global_geomcz_;
GlobalGeom *globalGeom = &_global_geomcz_;
#else
GlobalGeom global_geomcz_;
GlobalGeom *globalGeom = &global_geomcz_;

Other Docs

Known Problems

cglobal.h331

Developers Programming Guide

#endif /* CRAY */
#else
#if defined (CRAY)
extern GlobalGeom GLOBAL_GEOMCZ, *globalGeom;
#elif defined (CONVEX)
extern GlobalGeom _global_geomcz_, *globalGeom;
#else
extern GlobalGeom global_geomcz_, *globalGeom;
#endif /* CRAY */
#endif /* DEFINE_CGLOBALS */
/*

***** ADD 3D STUFF HERE WHEN IT IS READY *****

*/

/* coordinates globals */
typedef struct globalCoordStruct {
float azimx1;
/* azimuth towards increasing SURFLOC number */
float sloc1x;
/* X coordinate of first surface location */
float sloc1y;
/* Y coordinate of first surface location */
int ipad[5];
/* pad to 8 words */
} GlobalCoord;
#ifdef DEFINE_CGLOBALS
#if defined (CRAY)
GlobalCoord GLOBAL_COORDCZ;
GlobalCoord *globalCoord = &GLOBAL_COORDCZ;
#elif defined (CONVEX)
GlobalCoord _global_coordcz_;
GlobalCoord *globalCoord = &_global_coordcz_;
#else
GlobalCoord global_coordcz_;
GlobalCoord *globalCoord = &global_coordcz_;
#endif /* CRAY */
#else
#if defined (CRAY)
extern GlobalCoord GLOBAL_COORDCZ, *globalCoord;
#elif defined (CONVEX)
extern GlobalCoord _global_coordcz_, *globalCoord;
#else
extern GlobalCoord global_coordcz_, *globalCoord;
#endif /* CRAY */
#endif
typedef struct globalXYStruct {
double xref;
/* X reference point for the line */
double yref;
/* Y reference point for the line */
int ipad[4];
/* pad to 8 words */
} GlobalXY;
#ifdef DEFINE_CGLOBALS
#if defined (CRAY)
GlobalXY GLOBAL_XYCZ;
GlobalXY *globalXY = &GLOBAL_XYCZ;

Other Docs

Known Problems

cglobal.h332

Developers Programming Guide

#elif defined (CONVEX)


GlobalXY _global_xycz_;
GlobalXY *globalXY = &_global_xycz_;
#else
GlobalXY global_xycz_;
GlobalXY *globalXY = &global_xycz_;
#endif /* CRAY */
#else
#if defined (CRAY)
extern GlobalXY GLOBAL_XYCZ, *globalXY;
#elif defined (CONVEX)
extern GlobalXY _global_xycz_, *globalXY;
#else
extern GlobalXY global_xycz_, *globalXY;
#endif /* CRAY */
#endif /* DEFINE_CGLOBALS */
/* acquisition globals */
typedef struct globalAcquisStruct {
int isrctyp;
/* source type */
int idatrec;
/* date recorded */
int igainx;
/* gain mode of field instruments */
float prexamp; /* instrument preamp gain constant */
float earlyg;
/* instrument early or initial gain */
float aaxfilt; /* instrument anti-alias filter frequency */
float aaxslop; /* instrument anti-alias filter slope */
float freqxn;
/* instrument notch filter frequency */
float fxnslop; /* instrument notch filter slope */
float freqxl;
/* instrument low-cut filter frequency */
float freqxh;
/* instrument high-cut filter frequency */
float fxlslop; /* instrument low-cut filter slope */
float fxhslop; /* instrument high-cut filter slope */
int nsrecd;
/* number of samples per trace on field data */
float origdt;
/* sample rate on field data */
int ixform;
/* recording system format code */
int manfact;
/* recording system manufacturing code */
int iserial;
/* recording system serial number */
int nxauxs;
/* number of aux channels on field records */
float rcconst; /* recording system "dial in constant */
int ipad[12];
/* pad to 32 words */
} GlobalAcquis;
#ifdef DEFINE_CGLOBALS
#if defined (CRAY)
GlobalAcquis GLOBAL_AQUISCZ;
GlobalAcquis *globalAcquis = &GLOBAL_AQUISCZ;
#elif defined (CONVEX)
GlobalAcquis _global_aquiscz_;
GlobalAcquis *globalAcquis = &_global_aquiscz_;
#else
GlobalAcquis global_aquiscz_;
GlobalAcquis *globalAcquis = &global_aquiscz_;
#endif /* CRAY */
#else

Other Docs

Known Problems

cglobal.h333

Developers Programming Guide

#if defined (CONVEX)


extern GlobalAcquis GLOBAL_AQUISCZ, *globalAcquis;
#elif defined (CONVEX)
extern GlobalAcquis _global_aquiscz_, *globalAcquis;
#else
extern GlobalAcquis global_aquiscz_, *globalAcquis;
#endif /* CRAY */
#endif /* DEFINE_CGLOBALS */
/* ****************************************************************************
IF YOU CHANGE THIS struct, DON'T FORGET TO CHANGE header.inc,
OR YOU WILL BE TRANSFERRED TO THE SUPPORT DEPARTMENT
**************************************************************************** */
/* Standard header entries */
typedef struct stdHdrStruct {
int
isource,
icdp,
irec_sloc, ioffset,
ichan,
ifb_pick, iaoffset, iseqno,
iffid,
isin,
isou_sloc, isou_x,
isou_y,
isou_elev, inchans,
irec_x,
irec_y,
irec_elev, irec_nfld, icdp_sloc,
icdp_x,
icdp_y,
icdp_elev, icdp_nfld,
itot_stat, ina_stat, iskewstat, irec_stat,
isou_stat, iend_ens, ieoj,
itraceno,
itrc_type, itlive_s, itfull_s, itfull_e,
itlive_e, ilen_surg, iamp_norm, itr_fold,
idepth,
iuphole,
isr_azim, ipad_trc,
igeo_comp, ircdp,
irec_h2od, isou_h2od,
inmo_stat, ifnl_stat, iseq_disk, irepeat,
ifk_waven, ifk_wavel, ift_freq, ics_stat,
icr_stat, ips_stat, ipr_stat, itrimstat,
ilseg_end, ilseg_seq, idmooff,
isrc_dep,
ircvr_dep, isou_comp, ids_seqno, n_datum,
iofb_cntr, iofb_no,
iline_no, ifrn_trno,
iiline_no, ixline_no, idiskiter, irrec_slo,
irsou_slo, iriline_n, irxline_n, irchan;
} StdHdr;
#ifdef DEFINE_CGLOBALS
#if defined (CRAY)
StdHdr STD_HDRCZ;
StdHdr *stdHdr = &STD_HDRCZ;
#elif defined (CONVEX)
StdHdr _std_hdrcz_;
StdHdr *stdHdr = &_std_hdrcz_;
#else
StdHdr std_hdrcz_;
StdHdr *stdHdr = &std_hdrcz_;
#endif /* CRAY */
#else
#if defined (CRAY)
extern StdHdr STD_HDRCZ, *stdHdr;
#elif defined (CONVEX)

Other Docs

Known Problems

cglobal.h334

Developers Programming Guide

extern StdHdr _std_hdrcz_, *stdHdr;


#else
extern StdHdr std_hdrcz_, *stdHdr;
#endif /* CRAY */
#endif /* DEFINE_CGLOBALS */
/* space global */
typedef struct globalSpaceStruct {
int ispace[49152]; /* match dimension of FORTRAN ISPACEz array */
} GlobalSpace;
#ifdef DEFINE_CGLOBALS
#if defined (CRAY)
GlobalSpace SPACEZ;
GlobalSpace *globalSpace = &SPACEZ;
#elif defined (CONVEX)
GlobalSpace _spacez_;
GlobalSpace *globalSpace = &_spacez_;
#else
GlobalSpace spacez_;
GlobalSpace *globalSpace = &spacez_;
#endif /* CRAY */
#else
#if defined (CRAY)
extern GlobalSpace SPACEZ, *globalSpace;
#elif defined (CONVEX)
extern GlobalSpace _spacez_, *globalSpace;
#else
extern GlobalSpace spacez_, *globalSpace;
#endif /* CRAY */
#endif
/* macros to assist C programmer in declaring saved parameters */
/* Note: NSAVEDPARMS must match dimension of SAVE_AR in global.inc */
#define NSAVEDPARMS 1000
#if defined (CRAY)
struct {
float buffer[NSAVEDPARMS];
} SAVED_PARMS;
#define ENDPARMS(p) } *(p)=(void*)(&SAVED_PARMS.buffer[1]);
#elif defined (CONVEX)
extern struct block {
float buffer[NSAVEDPARMS];
} _saved_parms_;
#define ENDPARMS(p) } *(p)=(void*)(&_saved_parms_.buffer[1]);
#else
extern struct {
float buffer[NSAVEDPARMS];
} saved_parms_;
#define ENDPARMS(p) } *(p)=(void*)(&saved_parms_.buffer[1]);
#endif /* CRAY */
#define BEGINPARMS static struct {

Other Docs

Known Problems

cglobal.h335

#define

Developers Programming Guide

NPARMS(p) (2+sizeof(*p)/sizeof(float));

/* last-trace-in-ensemble flag */
#define LASTTR 1
#define NLAST 0
/* trace type */
#define IAUX 0
#define ILIVE 1
#define IDEAD 2
#define IDUMMY 3
#define ITBREAK 4
#define IUPHOLE 5
#define ISWEEP 6
#define ITIMING 7
#define IWBREAK 8
#define IOTHER 9
#define IWLOG 10
/* tool
#define
#define
#define
#define
#define
#define
#define
#define
#define

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

types */
ISIMPLE 1
IENSEMBLE 2
ICOMPLEX 3
IFLOW 4
INPUT 6
IROLLGATE 7
IPANEL 8
ISNL_BUFF 9
IDBL_BUFF 10

general auxiliary trace */


live data trace */
dead trace */
dummy trace */
time-break trace */
uphole trace */
sweep trace */
timing trace */
water break trace */
any other trace */
well log trace */

/*
/*
/*
/*
/*
/*
/*
/*
/*

simple (trace in, trace out) tool */


ensemble tool */
complex tool */
flow control tool (not valid for user tools)
input tool (implies complex tool) */
rolling gate tool */
panel tool */
one-buffer tool */
two-buffer tool */

/* The following numbers might be better in cpromax.h


/* system-wide formats */
#define INT4 1
#define IREAL4 2
#define IREAL8 3
#define INTCHAR 4
#define ICHAR 5
#define ICHARR 6
#define ILOGIC 7
/* system-wide NULL numbers.
#include <cnull.h>

*/

*/

*/

/* include the resource type definitions */


#include "resource.inc
/* release numbers */
#define SOFTRL 5.0 /* software */
#define GEORLS 5.0 /* geometry */
/* Global errno set by system after error on calling a UNIX function
#include <errno.h>

*/

#endif /* CGLOBAL_H */
/* SCCS: @(#)cglobal.h

Other Docs

50.17

11/18/93 */

Known Problems

cpromax.h336

Developers Programming Guide

cpromax.h
/*
/*

Created by Dave Hale, 9/91 */


Additions by Christof Stork */

/* include file for C interface to ProMAX */


#ifndef CPROMAX_H
#define CPROMAX_H
#include "agfc.h"
#include "cglobal.h"
/************/
/* includes */
/************/
#ifndef __MATH__
#define __MATH__
#endif
#ifndef TRUE
#define TRUE(1)
#endif
#ifndef FALSE
#define FALSE(0)
#endif
/* For compatability with Xlib */
#undefBool
#defineBoolint
#undefTrue
#defineTrue1
#undefFalse
#defineFalse0
#undefYes
#defineYes1
#undefNo
#defineNo0
#include
#include
#include
#include
#include

<math.h>
<limits.h>
<stdlib.h>
<stdio.h>
<string.h>

#ifdef DEC
#defineusleep(x)sleep((x)/1000000)
#endif
#ifdef SGI
#defineusleep(x)sleep((x)/1000000)
#endif
#ifdef CONVEX
#defineusleep(x)sleep((x)/1000000)

Other Docs

Known Problems

cpromax.h337

Developers Programming Guide

#endif
/*********************************************/
/* C defines and functions useful for ProMAX */
/*********************************************/

/**-**
char * listDesc( void *l)
Macro that returns the description of a list
****/
/* parameter list */
typedef struct DatabaseStruct {
int ikey;
int lock;
char domain[4];
int last_err;
int loc_min;
int loc_max;
int loc_inc;
int nstored;
int softrlse;
int igdate;
int igtime;
int ngtrace;
} Database;
typedef struct dbDomainProjectStruct {
int itoken;
char domain1[9];
char domain2[9];
} DomainProject;
typedef struct dbEnsembleMapStruct {
int itoken;
char domain1[9];
char domain2[9];
char domain3[9];
} EnsembleMap;
typedef struct dbTraceMapStruct {
int itoken;
char domain1[9];
char domain2[9];
char domain3[9];
} TraceMap;
typedef struct dbBufGetStruct {
int itoken;
Database *db;
char cinfo[9];
char cname[9];
int length;
int format;
void *buffer;
} BufGet;

Other Docs

Known Problems

cpromax.h338

Developers Programming Guide

typedef struct dbBufPutStruct {


int itoken;
Database *db;
char cinfo[9];
char cname[9];
int length;
int format;
void *buffer;
} BufPut;
typedef struct dbGetXYStruct {
int itoken;
Database *db;
void *xptr;
void *yptr;
} GetXY;

typedef struct dataSetInfo {


char cLabel[10];
int
idDataSet, iReadOnly, nDFiles, iSwapEnds;
int
iTrTotal;
int
nTraces;
float
softRlp, georLsp;
GlobalRuntime
gr;
} DataSetInfo;
/* FUNCTION PROTOTYPES */
/* If C++, specify external linkage to C functions. */
#ifdef __cplusplus
extern "C" {
#endif
/* executive control functions */
void exFillMode (void);
void exFlushMode (void);
void exPipeMode (void);
void exTraceHeadersOnlyOK (void);
void exSetPanels (int *, int *, int *, int *);
/* input parameter formats */
#define PARINT 1
#define PARFLOAT 2
#define PARDOUBLE 3
#define PARCHAR 4
/* input parameter functions */
int exParNOccurs (char *name);
int exParNValues (char *name);
void exParInfo (char *name, int *format, int *nwrdpval, int *nvals);
int exParFormat (char *name);
int exParExists (char *name);
int exParWordsPerValue (char *name);
void exParGetIntN (char *name, int n,int *i);
void exParGetFloatN (char *name, int n, float *f);
void exParGetInt (char *name, int *i);
void exParGetFloat (char *name, float *f);
void exParGetDouble (char *name, double *f);

Other Docs

Known Problems

cpromax.h339

Developers Programming Guide

int getPar (char *, char *, void *);


void exParGetString (char *name, char **s);
void exParGetStringN (char *name, int n, char **s);
/* trace header entry formats */
#define HDRUNDEFINED
0
#define HDRINT 1
#define HDRFLOAT 2
#define HDRDOUBLE 3
#define HDRCHAR 4
/* trace header functions */
#define STDHDR(x)((stdHdr->x) - 1)
void hdrInfo (char *name, char **desc,
int *length, int *format, int *index, int *err);
int hdrExists (char *name);
char *hdrDesc (char *name);
int hdrLength (char *name);
int hdrFormat (char *name);
int hdrIndex (char *name);
int hdrAdd (char *name, char *desc, int length, int format);
void hdrIndexInfo (int index, char **name, char **desc,
int *length, int *format, int *err);
int hdrIndexExists (int index);
char *hdrIndexDesc (int index);
char *hdrIndexName (int index);
int hdrIndexLength (int index);
int hdrIndexFormat (int index);
void padn(char *,char *, int);
void padname8(char *,char *);
void stripn(char *,char **, int);
void addNull(char *, int);
void hdrAddStd(char *);
void defStdHdr();
void initStdHdr (int *ihead, float *rhead);
void headerStackN(void *hip, void **heads, int nheads, void *headOut);
void headerStack(void *hip, void *head1, float weight1, void *head2, float
weight2, void *head3);
void headerInterpolate(void *hip, void *head1, float loc1, void *head2, float
loc2, void *head3,
float loc3);
void *initHeaderManip(int nth);

/* error functions */
void exErrFatal (char *format, ...);
void exErrMessage (char *format, ...);
void exErrWarn (char *format, ...);
int exErrHelp (char *format, ...);
void uErrFatal (char *format, ...);
void uErrMessage (char *format, ...);
void uErrWarn (char *format, ...);
int uErrHelp (char *format, ...);
/* parameter table
void *tblAllocate(
void *tblAllocTmp(
void tblFree( void

Other Docs

functions */
int nz, char *xdesc, char *ydesc, char *zdesc, char *desc );
int nz );
*tbl );

Known Problems

cpromax.h340

Developers Programming Guide

void *tblFetchTb3( void *tbl );


void tblSetExtrap( void *tbl, int xExt, int yExt );
int tblResolveX1X2( void *tbl, float x, float *x1, float *x2 );
void tblAddXY( void *tbl, float x, float y, float *z );
void tblAddXYs( void *tbl, float x, float *y, int ny, float *z );
int tblGetX( void *tbl, int ix_counter, float *x_loc );
int tblGetXYs( void *tbl, int ix_counter, int ny_max, float *x_loc,
float *y_locs, float *z_vals, int *ny );
int tblDeleteXY( void *tbl, float x, float y );
int tblDeleteX( void *tbl, float x );
void tblClear( void *tbl );
int tblInterpXY( void *tbl, float x, float y, float *z );
int tblInterpXYu( void *tbl, float x, float fy, float dy, int ny, float *z );
int dbTblUpdate( char *type, char *label, int trustCoords );
void *tblFromDatabase( char *type, char *label );
char *tblDescFromDatabase( char *type, char *label );
int tblToDatabase( void *tbl, char *type );
int tblToDatabaseHashName( void *tbl, char *type, char *label );
void *tblFromVelPar( char *loc, char *vel );
float tblXMax( void *tbl );
float tblXMin( void *tbl );
float tblX1Min( void *tbl );
float tblX1Max( void *tbl );
float tblX2Min( void *tbl );
float tblX2Max( void *tbl );
float tblYMin( void *tbl );
float tblYMax( void *tbl );
float tblZMax( void *tbl );
float tblZMin( void *tbl );
int tblCountX( void *tbl );
int tblCountMaxY( void *tbl );
int tblCountZ( void *tbl );
char *tblDesc( void *tbl );
char *tblDescX( void *tbl );
char *tblDescY( void *tbl );
char *tblDescZ( void *tbl );
int tblIndexX(void *tbl,int ix, float *x1, float *x2);
int tblGetYZ(void* t, float x1, float x2, int* ny, float* dy, float *fy,
float* y, float* z);
/* 3D table access functions */
void tblSetYZ( void *tbl, int ie, float x1, float x2, int ny, float dy,float fy,
float *y, float *z );
int tblDeleteYZ( void *tbl, float x1, float x2, int ny, float dy,
float fy, float *y );
int tblDelete( void *tbl, float x1, float x2 );
int tblInterpZ( void *tbl, float x1, float x2, int ny, float dy, float fy,
float *y, float *z );

/* parameter list functions */


void *listAlloc (int );
void listFree (void *list);
void listReady (void *list);
void listInfoUpdate (void *list);
void listDescribe (void *list, char *desc);
void listAdd (void *list, int igroup, int ilevel, int nvals, float *val1, float
*val2, float *dval);

Other Docs

Known Problems

cpromax.h341

Developers Programming Guide

void *listFromDatabase (char *type, char *label);


int listToDatabase (void *list, char *type);
void *listDecode (char *clist, int nlevels);
void listGet (void *list, float *vals, int nMax, float *val1, float *val2, float
*dval, int *n);
int listCheck (void *list, float *vals);
char *listDesc(void * l);
/* mute handling functions */
void *muteAlloc (void);
void *saMuteAlloc (void);
void muteFree (void *mute);
void muteGetTimes (void *mute, void *header,
float *tfl, float *tff, float *tlf, float *tll);
void muteSetTimes (void *mute, void *header,
float tfl, float tff, float tlf, float tll);
void muteApply (void *mute, void *header, float *trace);
void muteSlide (void *mute, void *header, float *trace);
void *muteFindZeros (void *mute, float *trace);
void muteRezero (void *mute, void *zeros, void *header, float *trace);
/* token parsing functions */
void tokensCreate (char *string, char *delim, int *ntoken, char ***token);
void tokensCompress (int ntoken, char **token);
int tokenInt (char *token, int *i);
int tokenPairInt (char *token, int *i1, int *i2);
int tokenReplicatedInt (char *token, int *n, int *i);
int tokenIteratedInt (char *token, int *n, int *d, int *i);
int tokenDecodeInts (char *string, int *n, int **i, char **bad);
int tokenFloat (char *token, float *f);
int tokenPairFloat (char *token, float *f1, float *f2);
int tokenReplicatedFloat (char *token, int *n, float *f);
int tokenIteratedFloat (char *token, int *n, float *d, float *f);
int tokenDecodeFloats (char *string, int *n, float **f, char **bad);
/* vector routines */
void vClr (float *a, int inc, int n);
void vMov (void *a, int inca, void *b, int incb, int n);
void vsMul (float *a, int inca, float scale, float *b, int incb, int n) ;
void vAdd (float *a, int inca, float *b, int incb, float *c, int incc, int n) ;
void vsMA (float *a, int inca, float scale, float *b, int incb, float *c, int
incc, int n) ;
/* utilities for casting pointers */
void *intToPtr( int i );
int ptrToInt( void *p );
void *fltToPtr( float r );
float ptrToFlt( void *p );
/* stand alone routines */
void initStandAlone( int, char **, char *);
void openDataset(char *);
int getTraceHdr( int, int *);
int getTrace(int, int *, float *);
int getTraceOnly(int, float *);
void closeStandAlone();
void uParInfo (char *name, int *format, int *nwrdpval, int *nvals);
int uParExists (char *name);
void uParGetInt (char *name, int *i);

Other Docs

Known Problems

cpromax.h342

Developers Programming Guide

void uParGetFloat (char *name, float *f);


void uParGetString (char *name, char **s);
int uGetPar(char *, char *, void *);
int uParNOccurs (char *name);
int uParNValues (char *name);
void uParInfo (char *name, int *format, int *nwrdpval, int *nvals);
int uParFormat (char *name);
/* database routines */
int opfCreate( char *domain, int locMin, int locMax );
int opfExists( char *domain );
void *dbInitDomainProject (char *domain1, char *domain2);
float dbDomainProject (void *, int loc);
void *dbInitEnsembleMap (char *domain1, char *domain2, char *domain3);
int dbEnsembleMap (void *ptr, int loc, void *result, int *ierr);
void *dbInitTraceMap (char *domain1, char *domain2, char *domain3);
void *opfOpen( char *name );
void *opfInfo( char *name );
int opfClose( void *opf );
int opfGet( void *opf, char *info, char *name, int loc, void *value );
int opfGetChar( void *opf, char *info, char *name, int loc, char *value );
int opfGetAll( void *opf, char *info, char *name, void *parms );
int opfGetRange( void *opf, char *info, char *name, void *parms,
int irone, int irlast );
void* opfLock ( char *name );
int opfParmCreate( void *opf, char *order, char *name, char *desc,
int length, int type );
int opfParmDelete( void *opf, char *info, char *name );
int opfParmExists( void *opf, char *order, char *name );
int opfParmFormat( void *opf, char *info, char *name );
int opfParmLength( void *opf, char *order, char *name );
void *opfInitBufGet( void *opf, char *, char * );
int opfBufGet( void *ptr, int loc, void *value );
int opfBufGetDouble( void *ptr, int loc, double *value );
int opfBufGetFloat( void *ptr, int loc, float *value );
int opfBufGetInt( void *ptr, int loc, int *value );
int opfCloseBufGet( void *ptr );
int opfCloseBufPut( void *ptr );
void *opfInitBufPut( void *opf, char *cinfo, char *cname );
void opfBufPutDouble( void *ptr, int loc, double value );
void opfBufPutDoubles( void *ptr, int loc, double *value );
void opfBufPutFloat( void *ptr, int loc, float value );
void opfBufPutFloats( void *ptr, int loc, float *value );
void opfBufPutInt( void *ptr, int loc, int value );
void opfBufPutInts( void *ptr, int loc, int *value );
void *opfInitGetXY( void *opf );
void opfGetXY( void *ptr, int loc, float *x, float *y );
void opfCloseGetXY( void *ptr );
void dbLineParmPut(char *name, float value);
char *getHashName(char *fname, char *ftype);
char *getFullName(char *fname, char *ftype);
int opfPutFloat( void *opf, char *info, char *name, int loc, float value);
int opfPutFloats( void *opf, char *info, char *name, int loc, float *value);
int opfPutDouble( void *opf, char *info, char *name, int loc, double value);
int opfPutDoubles( void *opf, char *info, char *name, int loc, double *value);
int opfPutInt( void *opf, char *info, char *name, int loc, int value);
int opfPutInts( void *opf, char *info, char *name, int loc, int *value);
int opfPutAll( void *opf, char *info, char *name, void *parms);
int opfPutRange( void *opf, char *info, char *name, void *parms,

Other Docs

Known Problems

cpromax.h343

Developers Programming Guide

int irone, int irlast);


char *opfParmList( void *opf, char *info );
int dbCreateParmFile(char *, char *);
int dbOpenParmFile(char *, char *, int);
float dbProjectXY(void *,float,float);
typedef struct SRFtoCDPmappingStruct {
float x1, x2;
} SRFtoCDPmapping;
void *dbInitSRFtoCDPmap(int **, int);
float dbSRFtoCDPmap(void *,float);
float dbCDPtoSRFmap(void *,float);
char **configDevList( char *type, int *n );
char *promaxPathName( char *);
void promaxPath( char *, char *);
/* Velocity Table convenience routines */
void convertVTable(void *t_in, char *in_type, void *t_out, char *out_type, float
in_step, float out_step);
void vIntStepConv(void *tin, void *tout);
void resampleTbl(void *t_in, void *t_out, float step);
void smoothVelMatrix( float **vel1, int nz, int nx, float hsmooth, float
vsmooth, int slowness);
void tblToMatrix (void *v_tbl, float *vel, float pos1, float pos2, float datum,
int nx,int nz,float dz);
void matrixToTbl (void *v_tbl, float *vel, float pos1, float pos2, float datum,
int nx,int nz,float dz);
float getTblAvg( void *tbl, float ymin, float ymax) ;
float getResampTblAvg( void *tbl, float xmin, float xmax, float dx, float ymin,
float ymax, float dy) ;
void avgTbl(void *t_in, void *t_out, float step, int slow);

void int_mix_vec_( int *id_num, int *ix_xtrap, int *iy_xtrap, float *x,
float *yStart, float *yInc, int *npts, float *zVec, int *noInterp,
float *mixWidth, float *dxMix);
int tblMixInterpXYu( void *tbl,
float x, float ymin, float dy, int numy,
float *z, float mixWidth, float dxMix);
void convert_v_table_( int *t_in_id, char *in_type, int *t_out_id,
char *out_type, float *in_step, float *out_step);

/* Miscellaneous routines */
double roundUpInc(double inc);
double roundDownInc(double inc);
/* packet file manipulation routines */
int pktFileClose(void *ptr);
void * pktFileOpen(char *name);
void * pktFileCreate(char *name);
int pktInit(void *ptr, char *name);
int pktGroupInit(void *ptr, char *gname);
int pktOutParmN(void *ptr, char *name, int format, int nwrdpval, int nvalues,
void *buf);
int pktOutInt(void *ptr, char *name, int val);

Other Docs

Known Problems

cpromax.h344

Developers Programming Guide

int pktOutFloat(void *ptr, char *name, float val);


int pktOutDouble(void *ptr, char *name, double val);
int pktOutString(void *ptr, char *name, char *val);
int pktGetNGroups(void *ptr);
void pktGroupCopy(void *ptrIn, void *ptrOut, char *name);
int pktParmInfo(void *ptr, int gnum, int pnum, char *name, int *format, int
*nwrdpval, int *nvalues)
;
int pktGroupInfo(void *ptr, int gnum, char *name, int *nparms);
int pktGetMaxParmLength(void *ptr);
void *pktGetExecPtr();
/* 3D geometry routines */
void d3CDPToXY( int icdp, float *x, float *y);
int d3XYToCDP( float x, float y);
int d3XYToXline( float x, float y);
int d3XYToInline( float x, float y);
int d3LinesToCDP( int iiline, int ixline);
void d3CDPToLines( int icdp, int *iiline, int *ixline);
void d3LinesToXY(int iiline, int ixline, float *x, float *y);
/* end of C++ block for specifing external linkage to C functions. */
#ifdef __cplusplus
}
#endif
#include "misc.h"
#include "db_err.h"
#include "hdr_err.h"
#endif /* CPROMAX_H */

Other Docs

Known Problems

Example Simple Processes345

Developers Programming Guide

Example Simple Processes


The simple.menu and simple.c programs on the following pages
provide an example of a simple ProMAX C process and its
menu. While the routine does not do a very important job, it has
the same structure as much more complicated ProMAX C
processes. Pay attention to the following important procedures:

how the parameters are saved between the BEGINPARMS


and ENDPARMS Macros
how information is passed through the parms structure by
use of the parms->varName syntax
how the global variables are accessed by including
cglobal.h and the globalRuntime pointers (in this example,
we get the trace length in samples through the pointer gr>numsmp)
how parameters are brought into the menu by use of the
routine getPar()

The amp_Ratio.c program provides an example of another C


ProMAX process. It is more complicated than the previous
example, but the structure is very similar. This process uses
table interpolation. Note that this routine uses a lot of the error
checking conveniences of ProMAX.

Other Docs

Known Problems

simple.menu346

Developers Programming Guide

simple.menu
'(
name: SIMPLE
label: "A Simple C Module"
value_tab: 48
parameter: ZMULT
text: "Input a positive multiplier"
type: typein:
type_desc: ( real: 6 0.0 nil )
value: 1.0
mouse_text: "Input a positive valued multiplier."
exec_data: ("SIMPLE"
("GENERAL"
("ZMULT

" implicit: (value 'ZMULT ))

)
)
)

Other Docs

Known Problems

simple.c347

Developers Programming Guide

simple.c
/* this is a really simple example of a C promax module */
/* include ProMAX prototypes and globals */
#include "cpromax.h
#include "cglobal.h
/* define the saved parameters (user input, etc) */
BEGINPARMS
int sampsPerTrace;
float zmult;
ENDPARMS (parms);
/* declare the functions used internally */
void multTrc( float* trace, float zmult, int sampsPerTrace );
/*-------------------------------------------------------------------*/
/* init_simple_()
/*
/* initialization routine for ProMAX module simple
/*
/*
/*-------------------------------------------------------------------*/
void init_simple_( int *len_sav, int *itooltype )
{
/* declare a local version of an external parameter */
float zmult;
/* set a pointer to the globalRuntime structure */
GlobalRuntime *gr = globalRuntime;
/* get the number of samples per trace, set the external parm too */
parms->sampsPerTrace = gr->numsmp;
/* get the multiplier for the trace from the menu */
exPerGetFloat("ZMULT, &zmult);
if( zmult < 0.0 ){
exErrFatal("The multiplier cannot be less than 0.0.);
}
/* now set the external parameter */
parms->zmult = zmult;
/* set the number of words that need to be saved for re-entrancy */
*len_sav = NPARMS(parms);
/* set the tool type to simple, (one trace in one trace out). */
/* ISIMPLE is defined in cglobal.h */
*itooltype = ISIMPLE;

}
/*-------------------------------------------------------------------*/
/* exec_simple_()

Other Docs

Known Problems

simple.c348

Developers Programming Guide

/*
/* execution routine for ProMAX module simple
/*
/*
/*-------------------------------------------------------------------*/
void exec_simple_( float* trace, float* rthdr, int* ithdr )
{
/* set a pointer to the globalRuntime structure */
GlobalRuntime *gr = globalRuntime;
/* see if we are in cleanup phase */
if( gr->cleanup ){
return;
}
/* process the trace */
multTrc( trace, parms->zmult, parms->sampsPerTrace );

}
/*-------------------------------------------------------------------*/
/*
/* multTrc()
/* multiplies trace samples by a scalar
/*
/* input arguments:
/*
zmult - float the multiplier
/*
sampsPerTrace int number of samples per trace
/* output argument:
/*
float *trace the data trace to be scaled
/*
/*-------------------------------------------------------------------*/
void multTrc( float *trace, float zmult, int sampsPerTrace )
{
int i;
for( i = 0; i < sampsPerTrace; i++ ){
trace[i] *= zmult;
}
}

Other Docs

Known Problems

ampRatio.c349

Developers Programming Guide

ampRatio.c
/* include ProMAX prototypes and globals */
#include "cpromax.h
#include "cglobal.h
/* define saved parameters */
BEGINPARMS
int
ngate, ih_ratio_max, ih_ratio_time, load_hdr, load_db,
id_max, id_time, itraceno, use_gate,
itabl_handle, ih_pkey, ih_skey, iformat_pkey, iformat_skey;
float
*scratch;
void
*gate_tbl;
void *db_trc, *dbPtr1,*dbPtr2;
ENDPARMS(parms)
int n_trc;
void
amp_ratio_work (float *trace, float *scratch, int nsams, int ngate,
int imin_samp, int imax_samp, float samprate, float
*ratio_max, float *ratio_time);
/***
C------------------------------------------------------------------C
C
C
Description:
C
Standard initialization routine
C
C
output arguments:
C
LEN_SAVE - number of 4-byte words to save for re-entrancy
C
ITOOLTYPE - processing tool type
C
C--------------------------------------------------------------------***/
void
init_amp_ratio_(int *len_sav, int *itooltype)
{
extern int n_trc;
float
gatelen;
char
*cgatename ;
n_trc = 0;
/* get the gate length */
gatelen=-1.0;
exParGetFloat ("GATELEN,

&gatelen);

/* convert the gate length from time to samples*/


parms->ngate = (int) (gatelen / globalRuntime->samprat+0.5);
/* check for reasonable input */
if (parms->ngate < 1 || parms->ngate * 2 + 1 >globalRuntime->numsmp)
exErrFatal ("Gate length is illegal);

Other Docs

Known Problems

ampRatio.c350

Developers Programming Guide

/* See if the user wants to confine the maximum to fall within a


gate*/
parms->use_gate = FALSE;
exParGetString ("GATENAME, &cgatename);
if (strcmp (cgatename, "") != 0 && strcmp (cgatename, "NO__GATE) != 0) {
parms->use_gate = TRUE;
/* Get the gate from the database */
parms->gate_tbl = tblFromDatabase ("GAT, cgatename);
if (parms->gate_tbl == NULL)
exErrFatal ("Cannot open time gate %s !!, cgatename);
if (tblCountZ(parms->gate_tbl) != 2)
exErrFatal ("invalid gate (Gate must have an upper and lower
gate!));
/* We will need the index of the primary and secondary key

*/

parms->ih_pkey = hdrIndex (tblDescX(parms->gate_tbl) );


if (!parms->ih_pkey)
exErrFatal ("The primary key of the time gate (%s) is not in the
header!, tblDescX(parms->gate_tbl) );
parms->ih_skey= hdrIndex ( tblDescY(parms->gate_tbl) );
if (!parms->ih_skey)
exErrFatal ("The secondary key of the time gate is (%s) is not in
the header!, tblDescY(parms->gate_tbl) );
}
/* See if the user wants to load the results into the trace header
parms->load_hdr = 0;
exParGetInt ("LOAD_HDR, &parms->load_hdr);
if (parms->load_hdr ) {
/* Add new trace header entries

*/

*/

if (hdrExists ("RATIOMAX) ) {
if (hdrFormat ("RATIOMAX) == HDRFLOAT)
exErrWarn ("RATIOMAX header already exists!);
else
exErrFatal ("RATIOMAX header already exists but is of wrong
type!);
} else {
parms->ih_ratio_max = hdrAdd ("RATIOMAX, "Time of amp ratio
maximum, 1, HDRFLOAT);
if (parms->ih_ratio_max== 0) {
/* This should virtually never happen. */
exErrFatal("Error adding header RATIOMAX);
}
}
if (hdrExists ("RATIOTIM) ) {
if (hdrFormat ("RATIOTIM) == HDRFLOAT)
exErrWarn ("RATIOTIM header already exists!);
else
exErrFatal ("RATIOTIM header already exists but is of wrong
type!);
} else {

Other Docs

Known Problems

ampRatio.c351

Developers Programming Guide

parms->ih_ratio_time = hdrAdd ("RATIOTIM, "Time of amp ratio


maximum, 1, HDRFLOAT);
if (parms->ih_ratio_time== 0) {
/* This should virtually never happen. */
exErrFatal("Error adding header RATIOTIM);
}
}
}
/* See if the user wants to load the results into the database*/
parms->load_db = 0;
exParGetInt ("LOAD_DB, &parms->load_db);
if (parms->load_db){
int
ierr;
/* Open the database to store the amp ratio information against
trace*/
if (globalRuntime->itrno_valid != 1){
fprintf(stderr,itrno_valid = %d\n,globalRuntime->itrno_valid);
exErrFatal ("Cannot load data into the TRC order without valid trace
numbers (geom assigned?));
}
else{
fprintf(stdout,itrno_valid = 1, continuing in init phase\n);
}
if (!hdrExists ("TRACENO)) {
exErrFatal ("TRACENO not found in header);
}
/* Lock the TRC order since we will be writing to it

*/

parms->db_trc = opfLock ("TRC);


if (!opfExists ( "TRC) )
exErrFatal ("Error locking TRC database.);
/* Create the new entries in the database
*/
if (!opfParmExists(parms->db_trc, "F_B_PICK, "RATIOMAX) ) {
ierr = opfParmCreate (parms->db_trc , "F_B_PICK,
"RATIOMAX, "Maximum value of amp ratio, 1, PARFLOAT);
if (ierr !=0 )
exErrFatal ("Error creating database entry);
else{
fprintf(stdout,created new db entry RATIOMAX\n);
}
}
if (!opfParmExists(parms->db_trc, "F_B_PICK, "RATIOTIM) ) {
ierr = opfParmCreate (parms->db_trc, "F_B_PICK, "RATIOTIM,
"Time of amp ration maximum, 1, PARFLOAT);
if (ierr !=0 )
exErrFatal ("Error creating database entry);
else{
fprintf(stdout,created new db entry RATIOTIM\n);
}
}
/* Initialize the token for buffered database I/O

Other Docs

*/

Known Problems

ampRatio.c352

Developers Programming Guide

parms->dbPtr1= opfInitBufPut(parms->db_trc,F_B_PICK,RATIOMAX);
parms->dbPtr2= opfInitBufPut(parms->db_trc,F_B_PICK,RATIOTIM);
}
/* Reserve a scratch buffer that we will need in exec phase */
parms->scratch = (float *) malloc (globalRuntime->numsmp * sizeof (float) );
/* Set the number of words that need to be saved for re-entrancy.

*/

*len_sav = NPARMS (parms);


/* Set the tool type to simple (one trace in, one trace out) */
*itooltype = ISIMPLE;
}
/*********************************************************************
*
*
Description:
*
Standard execution routine
*
*
Input/output arguments:
*
trace - array of trace samples
*
ithdr - trace header (as integer)
*
rthdr - trace header (as floating [point)
*
**********************************************************************/

void exec_amp_ratio_(float *trace, int *ithdr, float *rthdr)


{
int
loc_trc, ierr, isave, imin_samp, imax_samp;
float
ratio_max, ratio_time, pkeyval, skeyval, tgate[2];
/*
extern int n_trc, errno;
n_trc++;
fprintf(stdout,%d\n,n_trc);
*/
/* get the gate length */
if (globalRuntime->cleanup) {
if (parms->load_db) {
/* Flush the buffers for buffered database I/O Note that
errors only give rise to warnings in cleanup phase. Also note
that the "location is now 0.
*/

if (opfCloseBufPut (parms->dbPtr1) !=0)


exErrWarn ("Error loading data into
}
if (opfCloseBufPut (parms->dbPtr2) !=0)
exErrWarn ("Error loading data into
}
opfClose (parms->db_trc);

{
database.);
{
database.);

}
/* We don't want control to pass into the main body

Other Docs

*/

Known Problems

ampRatio.c353

Developers Programming Guide

return;
}
if (parms->use_gate){
/* Interpolate the gate times from the table*/
if (tblInterpXY (parms->gate_tbl, rthdr [parms->ih_pkey],
rthdr[parms->ih_skey], tgate)) {
exErrFatal ("Error interpolating time gate);
}
}
else {
/* use entire trace */
tgate[0]=0.0;
tgate[1]= (globalRuntime->numsmp-1)*globalRuntime->samprat;
}
/* Convert the time gate values to samples */
imin_samp = tgate[0] / globalRuntime->samprat +
imax_samp = tgate[1] / globalRuntime->samprat +
imin_samp = MAX (imin_samp, 0);
imin_samp = MIN (imin_samp, globalRuntime->numsmp
imax_samp = MAX (imax_samp, 0);
imax_samp = MIN (imax_samp, globalRuntime->numsmp
if (imin_samp > imax_samp) {
int
isave;
/* assume that they were menat to be reversed
isave= imin_samp;
imin_samp= imax_samp;
imax_samp=isave;
}

0.5;
0.5;
- 1);
- 1);

*/

/* Pass the buffers off to a routine where the real work is done */
amp_ratio_work (trace, parms->scratch, globalRuntime->numsmp,
parms->ngate, imin_samp, imax_samp, globalRuntime->samprat,
&ratio_max,&ratio_time);
if (parms->load_hdr == 1) {
/* Load the values into the header */
rthdr [parms->ih_ratio_max] = ratio_max;
rthdr [parms->ih_ratio_time] = ratio_time;
}
if (parms->load_db) {
/* Load the values into the database

*/

loc_trc = ithdr [STDHDR (itraceno)];


fprintf(stdout,loc_trc = %d\n,loc_trc);
if (loc_trc != INULL) {
opfBufPutFloat (parms->dbPtr1, loc_trc, ratio_max);
opfBufPutFloat (parms->dbPtr2, loc_trc, ratio_time);
}
}

}
/**
C--------------------------------------------------------------------C
C Actual work routine
C

Other Docs

Known Problems

ampRatio.c354

Developers Programming Guide

C--------------------------------------------------------------------**/
void
amp_ratio_work (float *trace, float *scratch, int nsamps, int ngate,
int imin_samp, int imax_samp, float samprate, float
*ratio_max, float *ratio_time)
{
int
i, istart, iend, ind_max;
float
sum_above, sum_below, rabove, rbelow;
/* Set the starting and end of the zone of interest
istart = 0 - ngate;
iend = nsamps + ngate;
/* Sum the first two gates
sum_above = 0.0;
rabove = 0.0;

*/

*/

sum_below = 0.0;
rbelow = 0.0;
for (i = istart + ngate; i< istart + ngate * 2; i ++)
if (i >=0 && i< nsamps && trace[i]!=0.0) {
sum_below = sum_below + fabs (trace[i]);
rbelow = rbelow + 1.0;
}
for (i = istart + ngate; i< iend - ngate ; i ++) {
/* Compute the ratio */
if (sum_above > 0.0 && rabove >0.0 && rbelow >0.0) {
scratch [i] = (sum_below/ rbelow) / (sum_above / rabove);
}
else if (trace[i] != 0.0) {
scratch [i] = 0.0;
}
/* Drop a sample from each gate and add the next one */
if (i - ngate >= 0) {
sum_above = sum_above - fabs (trace [i - ngate]) + fabs (trace [i]);
}
else {
sum_above = sum_above + fabs (trace[i]);
rabove = rabove + 1.0;
}
if (i + ngate +1< nsamps) {
sum_below = sum_below - fabs (trace[i + 1])
+ fabs (trace [i + ngate + 1]);
}
else {
if (i +1 < nsamps && trace[i+1]!=0.0) {
sum_below = sum_below - fabs (trace[i + 1]);
rbelow = rbelow - 1.0;
}
}

Other Docs

Known Problems

ampRatio.c355

Developers Programming Guide

}
/* Put the final results in place. Note that we have not handled the
edge problem, we have simply made the function undefined */
for (i = 0; i < nsamps; i++) {
trace [i] = scratch[i];
}
/* Find the maximum of the ratio function */
*ratio_max = trace [imin_samp ];
ind_max = imin_samp;
for (i = imin_samp ; i< imax_samp; i++) {
if (trace [i] > *ratio_max) {
ind_max = i;
*ratio_max = trace [i];
}
}
/* Covert the index of the maximum to time*/
*ratio_time = (float) (ind_max ) * samprate;
}

Other Docs

Known Problems

ampRatio.c356

Other Docs

Developers Programming Guide

Known Problems

357

Developers Programming Guide

Appendix: Simple Tool Examples

This appendix provides an example of a simple tool, a tool that


processes one data trace at a time. It demonstrates the creation
and use of trace headers, ordered parameter files, and database
tables. The program is a crude first break picker. It allows the
option of loading some of the derived parameters into the trace
headers and the database, and limiting the time window in
which the first break picker will search. The menu and
FORTRAN examples are presented first, then the C source code
is presented. The menu file can be used with either the C or
FORTRAN code.

Topics covered in this appendix:

Other Docs

amp_ratio.menu
amp_ratio.inc
amp_ratio.f
ampRatio.c

Known Problems

amp_ratio.menu358

Developers Programming Guide

amp_ratio.menu
'(
name: AMP_RATIO
label: "Amplitude Ratio"
value_tab: 35
parameter: GATELEN
text: "Amplitude gate length"
type: typein:
type_desc: ( real: 7 1.0e-5 nil )
value: 100.0
mouse_text: "Enter the sliding gate length used to compute amplitude ratios."
parameter: time_gate_opt
text: "Confine the maximum?"
type: boolean:
value: nil
mouse_text: "Select 'Yes' if you wish to use a gate to constrain the search for
the maximum in the amp ratio."
parameter: GATENAME
text: " Select gate parameter file"
type: function:
type_desc: ((parm_list "GAT") parms)
value: "INVALID"
selected_item: "** No Parameter File Selected **"
mouse_text: "Use Mouse Button 1 to select a gate parameter file from the
parameter file menu."
parameter: LOAD_HDR
text: "Load the results into the header?
type: boolean:
value: t
mouse_text: "Select 'Yes' if you wish to load the maximum of the amp ratio and
its time into the trace header."
parameter: LOAD_DB
text: "Load the results into the database?
type: boolean:
value: t
mouse_text: "Select 'Yes' if you wish to load the maximum of the amp ratio and
its time into the database."
exec_data: ("AMP_RATIO"
("GENERAL"
("GATELEN"
implicit: (value 'GATELEN))
("GATENAME" implicit: ( if (value 'time_gate_opt)
(value 'GATENAME) "NO__GATE" ))
("LOAD_HDR" implicit: ( if (value 'LOAD_HDR) 1 0 ) )
("LOAD_DB"
implicit: ( if (value 'LOAD_DB) 1 0 ) )
)
)
rules: (
(rule1 ( value 'time_gate_opt
)

) (do_show 'GATENAME)

(do_not_show 'GATENAME))

Other Docs

Known Problems

amp_ratio.inc359

Developers Programming Guide

amp_ratio.inc
C-----------------------------------------------------------------------------C Include file for AMP_RATIO
C-----------------------------------------------------------------------------IMPLICIT NONE
#include "global.inc"

&
&
&

COMMON /SAVED_PARMS/ SAVE1z, NGATE, IX_SCRATCH, IH_RATIO_MAX,


IH_RATIO_TIME, LOAD_HDR, LOAD_DB, ID_MAX, ID_TIME,
IH_TRACENO, IKEY_TRC, USE_GATE, ITBL_HANDLE, IH_PKEY,
IH_SKEY, IFORMAT_PKEY, IFORMAT_SKEY

&
&
&

INTEGER NGATE, IX_SCRATCH, LENSAVED, IH_RATIO_MAX,


IH_RATIO_TIME, LOAD_HDR, LOAD_DB, ID_MAX, ID_TIME,
IH_TRACENO, IKEY_TRC, ITBL_HANDLE, IH_PKEY, IH_SKEY,
IFORMAT_PKEY, IFORMAT_SKEY
LOGICAL USE_GATE

C
C
C
C

.....
.....
.....
.....

Specify the number of variables to save. This is set here (rather


than in the initialization routine) so that programmers don't forget
to change it when they are changing the contents of the common
block SAVED_PARMS.
DATA LENSAVED /17/

C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C

.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....

NGATE - number of samples in gate


IX_SCRATCH - index of scratch buffer
IH_RATIO_MAX - index in header of amp ratio maximum
IH_RATIO_TIME - index in header of amp ratio time
LOAD_HDR - flag for option to load the results into the trace header
LOAD_DB - flag for option to load the results into the database
ID_MAX - token for buffered database I/O for amp ratio max
ID_TIME - token for buffered database I/O for amp ratio time
IH_TRACENO - index in header of trace number
IKEY_TRC - key to the trace ordered database
USE_GATE - logical flag to use a gate to confine the amp ratio max
ITBL_HANDLE - handle for the time gate table
IH_PKEY - header index of the primary key of the time gate table
IH_SKEY - header index of the secondary key of the time gate table
IFORMAT_PKEY - format of the primary key of the time table
IFORMAT_SKEY - format of the secondary key of the time table

Other Docs

Known Problems

amp_ratio.f360

Developers Programming Guide

amp_ratio.f
C-----------------------------------------------------------------------------C
C
Description:
C
Standard initialization routine
C
C
Output arguments:
C
LEN_SAVE - number of 4-byte words to save for re-entrancy
C
ITOOLTYPE - processing tool type
C
C-----------------------------------------------------------------------------SUBROUTINE INIT_AMP_RATIO( LEN_SAV, ITOOLTYPE )
C ..... The include file 'amp_ratio.inc' contains a nested include
C
for the global parameters
#include "amp_ratio.inc"
C ..... Include file with error definitions
#include "hdr_err.inc"
#include "db_err.inc"
INTEGER LEN_SAV, ITOOLTYPE, IERR, LENGTH, IFORMAT, NCHARS,
&
IDUMMY(3), NTIMES
REAL GATELEN, RDUMMY(6)
CHARACTER CDESC_HDR*32, CDESC_DB*80, CGATENAME*8, CPRIM_KEY*8,
&
CSCND_KEY*8, CTABLE_DESC*128, CZ_DESC*8
C ..... Set a default that is illegal (in case there is a menu problem)
GATELEN = -1.0
C ..... Call for the input parameter by name. Note the padding in the
C ..... character constant. It is the programmers responsibility to
C ..... provide the correct type of return argument.
CALL EX_GETPARM( 'GATELEN ', 1, GATELEN )
C ..... Convert the gate length to samples
NGATE = NINT( GATELEN / SAMPRATz )
C ..... Check for reasonable input
IF ( NGATE .LT. 1 .OR. NGATE*2+1 .GT. NUMSMPz ) THEN
CALL EX_ERR_FATAL( 'Gate length is illegal' )
ENDIF
C ..... See if the user wants to confine the maximum to fall within a gate
USE_GATE = .FALSE.
CGATENAME = '
'
CALL EX_CGETPARM( 'GATENAME', 1, CGATENAME, NCHARS )
IF ( CGATENAME .NE. '
'
&
.AND. CGATENAME .NE. 'NO__GATE' ) THEN
C ......... Something was specified
USE_GATE = .TRUE.
C ......... Get the gate from the database
CALL DB_TBL_GET( 'GAT', CGATENAME, ITBL_HANDLE, IERR )
IF ( IERR .NE. 0 ) THEN
CALL REPORT_PROMAX_ERR( IERR )
CALL EX_ERR_FATAL(

Other Docs

Known Problems

amp_ratio.f361

&

Developers Programming Guide

'Cannot open time gate ' //CGATENAME )


ENDIF

C ......... Get info on the gate table


CALL TBL_INFO( .TRUE., ITBL_HANDLE, CPRIM_KEY, CSCND_KEY,
&
CZ_DESC, CTABLE_DESC, IDUMMY(1), IDUMMY(2), IDUMMY(3),
&
NTIMES, RDUMMY(1), RDUMMY(2), RDUMMY(3), RDUMMY(4),
&
RDUMMY(5), RDUMMY(6) )
C ......... There had better be two time values (upper and lower gate)
IF ( NTIMES .NE. 2 ) CALL EX_ERR_FATAL(
&
'Invalid gate (must have an upper and lower gate)' )
C ......... We will need the index of the primary and secondary key
CALL HDR_NAMINFO( CPRIM_KEY, CDESC_DB, LENGTH, IFORMAT_PKEY,
&
IH_PKEY, IERR )
IF ( IERR .NE. 0 ) CALL EX_ERR_FATAL(
&
'The primary key of the time gate (' //CPRIM_KEY
&
//') is not in the header' )

&
&
&

CALL HDR_NAMINFO( CSCND_KEY, CDESC_DB, LENGTH, IFORMAT_SKEY,


IH_SKEY, IERR )
IF ( IERR .NE. 0 ) CALL EX_ERR_FATAL(
'The secondary key of the time gate (' //CSCND_KEY
//') is not in the header' )
ENDIF

C ..... See if the user wants to load the results into the trace header
LOAD_HDR = 0
CALL EX_GETPARM( 'LOAD_HDR', 1, LOAD_HDR )
IF ( LOAD_HDR .EQ. 1 ) THEN
C ......... Add new trace header entries
CDESC_HDR = 'Maximum value of amp ratio'
CALL HDR_ADD( 'RATIOMAX', CDESC_HDR, 1, IREAL4pz,
&
IH_RATIO_MAX, IERR )
IF ( IERR .NE. 0 ) THEN
IF ( IERR .EQ. IERR_HDR_EXSTpz ) THEN
C ................. That's OK, but somewhat unexpected
CALL EX_ERR_WARN(
&
'RATIOMAX already exists in header' )
ELSE
C ................. This will virtually never happen, but just in case
CALL EX_ERR_FATAL( 'Error adding header entry' )
ENDIF
ENDIF
CDESC_HDR = 'Time of amp ratio maximum'
CALL HDR_ADD( 'RATIOTIM', CDESC_HDR, 1, IREAL4pz,
&
IH_RATIO_TIME, IERR )
IF ( IERR .NE. 0 ) THEN
IF ( IERR .EQ. IERR_HDR_EXSTpz ) THEN
C ................. That's OK, but somewhat unexpected
CALL EX_ERR_WARN(
&
'RATIOTIM already exists in header' )
ELSE
C ................. This will virtually never happen, but just in case

Other Docs

Known Problems

amp_ratio.f362

Developers Programming Guide

CALL EX_ERR_FATAL( 'Error adding header entry' )


ENDIF
ENDIF
ENDIF
C ..... See if the user wants to load the results into the database
LOAD_DB = 0
CALL EX_GETPARM( 'LOAD_DB ', 1, LOAD_DB )
IF ( LOAD_DB .EQ. 1 ) THEN
C ......... Open the database to store the amp ratio information
C
against trace

&

IF ( ITRNO_VALIDz .NE. 1 ) THEN


CALL EX_ERR_FATAL( 'Cannot load data into the TRC order'
//' without valid trace numbers (geom assigned)' )
ENDIF

C ......... We will need the index of the trace number


CALL HDR_NAMINFO( 'TRACENO ', CDESC_HDR, LENGTH, IFORMAT,
&
IH_TRACENO, IERR )
IF ( IERR .NE. 0 ) CALL EX_ERR_FATAL(
&
'TRACENO not found in header' )
C ......... Lock the TRC order since we will be writing to it
CALL DB_ORDLOCK( 'TRC', IKEY_TRC, IERR )
IF ( IERR .NE. 0 ) THEN
CALL REPORT_PROMAX_ERR( IERR )
CALL EX_ERR_FATAL( 'Error locking TRC database' )
ENDIF
C ......... Create the new entries in the database
CDESC_DB = 'Maximum value of amp ratio'
CALL DB_PARMCRE( IKEY_TRC, '
', 'F_B_PICK', 'RATIOMAX',
&
CDESC_DB, 1, IREAL4pz, RNULLpz, IERR )
IF ( IERR .NE. 0 .AND. IERR .NE. IERR_DB_PEXSpz ) THEN
CALL REPORT_PROMAX_ERR( IERR )
CALL EX_ERR_FATAL( 'Error creating database entry' )
ENDIF

&

CDESC_DB = 'Time of amp ratio maximum'


CALL DB_PARMCRE( IKEY_TRC, '
', 'F_B_PICK', 'RATIOTIM',
CDESC_DB, 1, IREAL4pz, RNULLpz, IERR )
IF ( IERR .NE. 0 .AND. IERR .NE. IERR_DB_PEXSpz ) THEN
CALL REPORT_PROMAX_ERR( IERR )
CALL EX_ERR_FATAL( 'Error creating database entry' )
ENDIF

C ......... Initialize the token for buffered database I/O


ID_MAX = 0
ID_TIME = 0
ENDIF
C ..... Reserve a scratch buffer that we will need in exec phase
CALL MEM_RESBUFF( NUMSMPz, IX_SCRATCH, IERR )
C ..... Set the number of words that need to be saved for re-entrancy.

Other Docs

Known Problems

amp_ratio.f363

Developers Programming Guide

C ..... Note that LENSAVED declared within the include file, hopefully
C ..... to avoid oversights
LEN_SAV = LENSAVED
C ..... Set the tool type to simple (one trace in, one trace out)
ITOOLTYPE = ISIMPLEpz
RETURN
END

C-----------------------------------------------------------------------------C
C
Description:
C
Standard execution routine
C
C
Input/output arguments:
C
TRACE - array of trace samples
C
ITHDR - trace header (as integer)
C
RTHDR - trace header (as floating point)
C
C-----------------------------------------------------------------------------SUBROUTINE EXEC_AMP_RATIO( TRACE, ITHDR, RTHDR )
#include "amp_ratio.inc"
C ..... Include the file that allows use of the "space array" and memory
C ..... management routines.
#include "mem.inc"
INTEGER ITHDR(NTHz), LOC_TRC, IERR, ISAVE, IMIN_SAMP, IMAX_SAMP
REAL TRACE(NUMSMPz), RTHDR(NTHz), RATIO_MAX, RATIO_TIME,
&
PKEYVAL, SKEYVAL, TGATE(2)

C
C
C

IF ( CLEANUPz ) THEN
IF ( LOAD_DB .EQ. 1 ) THEN
............. Flush the buffers for buffered database I/O
............. Note that errors only give rise to warnings in cleanup phase.
............. Also note that the "location" is now 0.
CALL DB_BUFFRDPUT( ID_MAX, IKEY_TRC, 'F_B_PICK',
&
'RATIOMAX', 0, 0.0, .TRUE., IERR )
IF ( IERR .NE. 0 ) THEN
CALL REPORT_PROMAX_ERR( IERR )
CALL EX_ERR_WARN(
&
'Error loading data into database' )
ENDIF
CALL DB_BUFFRDPUT( ID_TIME, IKEY_TRC, 'F_B_PICK',
&
'RATIOTIM', 0, 0.0, .TRUE., IERR )
IF ( IERR .NE. 0 ) THEN
CALL REPORT_PROMAX_ERR( IERR )
CALL EX_ERR_WARN(
&
'Error loading data into database' )
ENDIF
ENDIF
......... We don't want control to pass into the main body
RETURN
ENDIF

IF ( USE_GATE ) THEN
C ......... Interpolate the gate times from the table

Other Docs

Known Problems

amp_ratio.f364

Developers Programming Guide

&

CALL EX_GET_REALKEY( RTHDR(IH_PKEY), IFORMAT_PKEY, PKEYVAL )


CALL EX_GET_REALKEY( RTHDR(IH_SKEY), IFORMAT_SKEY, SKEYVAL )
CALL INT_GET( ITBL_HANDLE, 0, 0, PKEYVAL, SKEYVAL,
TGATE, IERR )
IF ( IERR .NE. 0 ) CALL EX_ERR_FATAL(
'Error interpolating time gate' )

&

ELSE
C ......... Use the entire trace
TGATE(1) = 0.0
TGATE(2) = FLOAT(NUMSMPz-1) * SAMPRATz
ENDIF
C ..... Convert the time gate values to samples
IMIN_SAMP = NINT( TGATE(1) / SAMPRATz ) + 1
IMAX_SAMP = NINT( TGATE(2) / SAMPRATz ) + 1
C ..... Don't let them go out of bounds
IMIN_SAMP = MAX0( IMIN_SAMP, 1 )
IMIN_SAMP = MIN0( IMIN_SAMP, NUMSMPz )
IMAX_SAMP = MAX0( IMAX_SAMP, 1 )
IMAX_SAMP = MIN0( IMAX_SAMP, NUMSMPz )
IF ( IMIN_SAMP .GT. IMAX_SAMP ) THEN
C ......... Let's assume that they were meant to be reversed
ISAVE = IMIN_SAMP
IMIN_SAMP = IMAX_SAMP
IMAX_SAMP = ISAVE
ENDIF
C ..... Pass
CALL
&
&

the buffers off to a routine where the real work is done


AMP_RATIO_WORK( TRACE, RSPACEz(IX_SCRATCH), NUMSMPz,
NGATE, IMIN_SAMP, IMAX_SAMP, SAMPRATz, RATIO_MAX,
RATIO_TIME )

IF ( LOAD_HDR .EQ. 1 ) THEN


C ......... Load the values into the header
RTHDR(IH_RATIO_MAX) = RATIO_MAX
RTHDR(IH_RATIO_TIME) = RATIO_TIME
ENDIF
IF ( LOAD_DB .EQ. 1 ) THEN
C ......... Load the values into the database
LOC_TRC = ITHDR( IH_TRACENO )
IF ( LOC_TRC .NE. INULLpz ) THEN

&

&

&

&

Other Docs

CALL DB_BUFFRDPUT( ID_MAX, IKEY_TRC, 'F_B_PICK',


'RATIOMAX', LOC_TRC, RATIO_MAX, .FALSE., IERR )
IF ( IERR .NE. 0 ) THEN
CALL REPORT_PROMAX_ERR( IERR )
CALL EX_ERR_FATAL(
'Error loading data into database' )
ENDIF
CALL DB_BUFFRDPUT( ID_TIME, IKEY_TRC, 'F_B_PICK',
'RATIOTIM', LOC_TRC, RATIO_TIME, .FALSE., IERR )
IF ( IERR .NE. 0 ) THEN
CALL REPORT_PROMAX_ERR( IERR )
CALL EX_ERR_FATAL(
'Error loading data into database' )

Known Problems

amp_ratio.f365

Developers Programming Guide

ENDIF
ENDIF
ENDIF
RETURN
END

C-----------------------------------------------------------------------------C
C
Actual work routine
C
C------------------------------------------------------------------------------

&

&
&

SUBROUTINE AMP_RATIO_WORK( TRACE, SCRATCH, NSAMPS, NGATE,


IMIN_SAMP, IMAX_SAMP, SAMPRATE, RATIO_MAX, RATIO_TIME )
IMPLICIT NONE
INTEGER NSAMPS, NGATE, I, ISTART, IEND, IND_MAX, IMIN_SAMP,
IMAX_SAMP
REAL TRACE(NSAMPS), SCRATCH(NSAMPS), SUM_ABOVE, SUM_BELOW,
RATIO_MAX, RATIO_TIME, SAMPRATE, RABOVE, RBELOW

C ..... Set the starting and end of the zone of interest


ISTART = 1 - NGATE
IEND = NSAMPS + NGATE
C ..... Sum the first two gates
SUM_ABOVE = 0.0
RABOVE = 0.0

110

SUM_BELOW = 0.0
RBELOW = 0.0
DO 110 I=ISTART+NGATE+1,ISTART+NGATE*2
IF ( I .GE. 1 .AND. I .LE. NSAMPS ) THEN
SUM_BELOW = SUM_BELOW + ABS( TRACE(I) )
RBELOW = RBELOW + 1.0
ENDIF
CONTINUE

C ..... Now move down the trace


DO 120 I=ISTART+NGATE,IEND-NGATE
C ......... Compute the ratio
IF ( SUM_ABOVE .GT. 0.0 .AND. RABOVE .GT. 0.0
&
.AND. RBELOW .GT. 0.0 ) THEN
SCRATCH(I) = (SUM_BELOW/RBELOW) / (SUM_ABOVE/RABOVE)
ELSE
SCRATCH(I) = 0.0
ENDIF
C ......... Drop a sample from each gate and add the next one
IF ( I-NGATE .GE. 1 ) THEN
SUM_ABOVE = SUM_ABOVE - ABS( TRACE(I-NGATE) )
&
+ ABS( TRACE(I) )
ELSE
SUM_ABOVE = SUM_ABOVE + ABS( TRACE(I) )

Other Docs

Known Problems

amp_ratio.f366

Developers Programming Guide

RABOVE = RABOVE + 1.0


ENDIF

&

120

IF ( I+NGATE+1 .LE. NSAMPS ) THEN


SUM_BELOW = SUM_BELOW - ABS( TRACE(I+1) )
+ ABS( TRACE(I+NGATE+1) )
ELSE
IF ( I+1 .LE. NSAMPS ) THEN
SUM_BELOW = SUM_BELOW - ABS( TRACE(I+1) )
RBELOW = RBELOW - 1.0
ENDIF
ENDIF
CONTINUE

C ..... Put the final results in place. Note that we have not handled the
C ..... edge problem, we have simply made the function undefined.
DO 130 I=1,NSAMPS
IF ( I .LE. ISTART+NGATE-1 ) THEN
TRACE(I) = 0.0
ELSEIF ( I .GE. IEND-NGATE+1 ) THEN
TRACE(I) = 0.0
ELSE
TRACE(I) = SCRATCH(I)
ENDIF
130
CONTINUE
C ..... Find the maximum of the ratio function
RATIO_MAX = TRACE(IMIN_SAMP)
IND_MAX = IMIN_SAMP
DO 140 I=IMIN_SAMP,IMAX_SAMP
IF ( TRACE(I) .GT. RATIO_MAX ) THEN
IND_MAX = I
RATIO_MAX = TRACE(I)
ENDIF
140
CONTINUE
C ..... Convert the index of the maximum to time
RATIO_TIME = FLOAT( IND_MAX - 1 ) * SAMPRATE
RETURN
END

Other Docs

Known Problems

ampRatio.c367

Developers Programming Guide

ampRatio.c

/* include ProMAX prototypes and globals */


#include "cpromax.h"
#include "cglobal.h"
/* define saved parameters */
BEGINPARMS
int
ngate, ih_ratio_max, ih_ratio_time, load_hdr, load_db,
id_max, id_time, itraceno, use_gate,
itabl_handle, ih_pkey, ih_skey, iformat_pkey, iformat_skey;
float
*scratch;
void
*gate_tbl;
void *db_trc, *dbPtr1,*dbPtr2;
ENDPARMS(parms)
int n_trc;
static char *sccsid = "@(#)

ampRatio.c 50.2 4/8/94";

void
amp_ratio_work (float *trace, float *scratch, int nsams, int ngate,
int imin_samp, int imax_samp, float samprate, float
*ratio_max, float *ratio_time);
/***------------------------------------------------------------------Description:
Standard initialization routine
output arguments:
LEN_SAVE - number of 4-byte words to save for re-entrancy
ITOOLTYPE - processing tool type
---------------------------------------------------------------------***/
void
init_amp_ratio_(int *len_sav, int *itooltype)
{
extern int n_trc;
float
gatelen;
char
*cgatename ;
n_trc = 0;
/* get the gate length */
gatelen=-1.0;
exParGetFloat ("GATELEN",

&gatelen);

/* convert the gate length from time to samples*/


parms->ngate = (int) (gatelen / globalRuntime->samprat+0.5);
/* check for reasonable input */
if (parms->ngate < 1 || parms->ngate * 2 + 1 >globalRuntime->numsmp)
exErrFatal ("Gate length is illegal");

Other Docs

Known Problems

ampRatio.c368

Developers Programming Guide

/* See if the user wants to confine the maximum to fall within a


gate*/
parms->use_gate = FALSE;
exParGetString ("GATENAME", &cgatename);
if (strcmp (cgatename, "") != 0 && strcmp (cgatename, "NO__GATE") != 0) {
parms->use_gate = TRUE;
/* Get the gate from the database */
parms->gate_tbl = tblFromDatabase ("GAT", cgatename);
if (parms->gate_tbl == NULL)
exErrFatal ("Cannot open time gate %s !!", cgatename);
if (tblCountZ(parms->gate_tbl) != 2)
exErrFatal ("invalid gate (Gate must have an upper and lower
gate!)");
/* We will need the index of the primary and secondary key

*/

parms->ih_pkey = hdrIndex (tblDescX(parms->gate_tbl) );


if (!parms->ih_pkey)
exErrFatal ("The primary key of the time gate (%s) is not in the
header!", tblDescX(parms->gate_tbl) );
parms->ih_skey= hdrIndex ( tblDescY(parms->gate_tbl) );
if (!parms->ih_skey)
exErrFatal ("The secondary key of the time gate is (%s) is not in
the header!", tblDescY(parms->gate_tbl) );
}
/* See if the user wants to load the results into the trace header
parms->load_hdr = 0;
exParGetInt ("LOAD_HDR", &parms->load_hdr);
if (parms->load_hdr ) {
/* Add new trace header entries

*/

*/

if (hdrExists ("RATIOMAX") ) {
if (hdrFormat ("RATIOMAX") == HDRFLOAT)
exErrWarn ("RATIOMAX header already exists!");
else
exErrFatal ("RATIOMAX header already exists but is of wrong
type!");
} else {
parms->ih_ratio_max = hdrAdd ("RATIOMAX", "Time of amp ratio
maximum", 1, HDRFLOAT);
if (parms->ih_ratio_max== 0) {
/* This should virtually never happen. */
exErrFatal("Error adding header RATIOMAX");
}
}
if (hdrExists ("RATIOTIM") ) {
if (hdrFormat ("RATIOTIM") == HDRFLOAT)
exErrWarn ("RATIOTIM header already exists!");
else
exErrFatal ("RATIOTIM header already exists but is of wrong
type!");
} else {

Other Docs

Known Problems

ampRatio.c369

Developers Programming Guide

parms->ih_ratio_time = hdrAdd ("RATIOTIM", "Time of amp ratio


maximum", 1, HDRFLOAT);
if (parms->ih_ratio_time== 0) {
/* This should virtually never happen. */
exErrFatal("Error adding header RATIOTIM");
}
}
}
/* See if the user wants to load the results into the database*/
parms->load_db = 0;
exParGetInt ("LOAD_DB", &parms->load_db);
if (parms->load_db){
int
ierr;
/* Open the database to store the amp ratio information against
trace*/
if (globalRuntime->itrno_valid != 1){
fprintf(stderr,"itrno_valid = %d\n",globalRuntime->itrno_valid);
exErrFatal ("Cannot load data into the TRC order without valid trace
numbers (geom assigned?)");
}
else{
fprintf(stdout,"itrno_valid = 1, continuing in init phase\n");
}
if (!hdrExists ("TRACENO")) {
exErrFatal ("TRACENO not found in header");
}
/* Lock the TRC order since we will be writing to it

*/

parms->db_trc = opfLock ("TRC");


if (!opfExists ( "TRC") )
exErrFatal ("Error locking TRC database.");
/* Create the new entries in the database
*/
if (!opfParmExists(parms->db_trc, "F_B_PICK", "RATIOMAX") ) {
ierr = opfParmCreate (parms->db_trc , "F_B_PICK",
"RATIOMAX", "Maximum value of amp ratio", 1, PARFLOAT);
if (ierr !=0 )
exErrFatal ("Error creating database entry");
else{
fprintf(stdout,"created new db entry RATIOMAX\n");
}
}
if (!opfParmExists(parms->db_trc, "F_B_PICK", "RATIOTIM") ) {
ierr = opfParmCreate (parms->db_trc, "F_B_PICK", "RATIOTIM",
"Time of amp ration maximum", 1, PARFLOAT);
if (ierr !=0 )
exErrFatal ("Error creating database entry");
else{
fprintf(stdout,"created new db entry RATIOTIM\n");
}
}
/* Initialize the token for buffered database I/O

Other Docs

*/

Known Problems

ampRatio.c370

Developers Programming Guide

parms->dbPtr1= opfInitBufPut(parms->db_trc,"F_B_PICK","RATIOMAX");
parms->dbPtr2= opfInitBufPut(parms->db_trc,"F_B_PICK","RATIOTIM");
}
/* Reserve a scratch buffer that we will need in exec phase */
parms->scratch = (float *) malloc (globalRuntime->numsmp * sizeof (float) );
/* Set the number of words that need to be saved for re-entrancy.

*/

*len_sav = NPARMS (parms);


/* Set the tool type to simple (one trace in, one trace out) */
*itooltype = ISIMPLE;
}
/*********************************************************************
*
*
Description:
*
Standard execution routine
*
*
Input/output arguments:
*
trace - array of trace samples
*
ithdr - trace header (as integer)
*
rthdr - trace header (as floating [point)
*
**********************************************************************/

void exec_amp_ratio_(float *trace, int *ithdr, float *rthdr)


{
int
loc_trc, ierr, isave, imin_samp, imax_samp;
float
ratio_max, ratio_time, pkeyval, skeyval, tgate[2];
float
fltPkey, fltSkey;
/* get the gate length */
if (globalRuntime->cleanup) {
if (parms->load_db) {
/* Flush the buffers for buffered database I/O Note that
errors only give rise to warnings in cleanup phase. Also note
that the "location" is now 0.
*/

if (opfCloseBufPut (parms->dbPtr1) !=0)


exErrWarn ("Error loading data into
}
if (opfCloseBufPut (parms->dbPtr2) !=0)
exErrWarn ("Error loading data into
}
opfClose (parms->db_trc);

{
database.");
{
database.");

}
/* We don't want control to pass into the main body
return;

*/

}
if (parms->use_gate){
/* Interpolate the gate times from the table*/
if( hdrIndexFormat(parms->ih_pkey) == HDRINT ){
fltPkey = (float)ithdr[parms->ih_pkey];

Other Docs

Known Problems

ampRatio.c371

Developers Programming Guide

}
else{
fltPkey = rthdr[parms->ih_pkey];
}
if( hdrIndexFormat(parms->ih_skey) == HDRINT ){
fltSkey = (float)ithdr[parms->ih_skey];
}
else{
fltSkey = rthdr[parms->ih_skey];
}
if (tblInterpXY (parms->gate_tbl, fltPkey, fltSkey, tgate )){
exErrFatal ("Error interpolating time gate");
}
}
else {
/* use entire trace */
tgate[0]=0.0;
tgate[1]= (globalRuntime->numsmp-1)*globalRuntime->samprat;
}
/* Convert the time gate values to samples */
imin_samp = tgate[0] / globalRuntime->samprat +
imax_samp = tgate[1] / globalRuntime->samprat +
imin_samp = MAX (imin_samp, 0);
imin_samp = MIN (imin_samp, globalRuntime->numsmp
imax_samp = MAX (imax_samp, 0);
imax_samp = MIN (imax_samp, globalRuntime->numsmp
if (imin_samp > imax_samp) {
int
isave;
/* assume that they were meant to be reversed
isave= imin_samp;
imin_samp= imax_samp;
imax_samp=isave;
}

0.5;
0.5;
- 1);
- 1);

*/

/* Pass the buffers off to a routine where the real work is done */
amp_ratio_work(trace, parms->scratch, globalRuntime->numsmp,
parms->ngate, imin_samp, imax_samp, globalRuntime->samprat,
&ratio_max,&ratio_time);
if (parms->load_hdr == 1) {
/* Load the values into the header */
rthdr [parms->ih_ratio_max] = ratio_max;
rthdr [parms->ih_ratio_time] = ratio_time;
}
if (parms->load_db) {
/* Load the values into the database

*/

loc_trc = ithdr [STDHDR (itraceno)];


fprintf(stdout,"loc_trc = %d\n",loc_trc);
if (loc_trc != INULL) {
opfBufPutFloat (parms->dbPtr1, loc_trc, ratio_max);
opfBufPutFloat (parms->dbPtr2, loc_trc, ratio_time);
}
}

Other Docs

Known Problems

ampRatio.c372

Developers Programming Guide

}
/*--------------------------------------------------------------------Actual work routine
----------------------------------------------------------------------*/
void
amp_ratio_work (float *trace, float *scratch, int nsamps, int ngate,
int imin_samp, int imax_samp, float samprate, float
*ratio_max, float *ratio_time)
{
int
i, istart, iend, ind_max;
float
sum_above, sum_below, rabove, rbelow;
/* Set the starting and end of the zone of interest
istart = 0 - ngate;
iend = nsamps + ngate;
/* Sum the first two gates
sum_above = 0.0;
rabove = 0.0;

*/

*/

sum_below = 0.0;
rbelow = 0.0;
for (i = istart + ngate; i< istart + ngate * 2; i ++)
if (i >=0 && i< nsamps && trace[i]!=0.0) {
sum_below = sum_below + fabs (trace[i]);
rbelow = rbelow + 1.0;
}
for (i = istart + ngate; i< iend - ngate ; i ++) {
/* Compute the ratio */
if (sum_above > 0.0 && rabove >0.0 && rbelow >0.0) {
scratch [i] = (sum_below/ rbelow) / (sum_above / rabove);
}
else if (trace[i] != 0.0) {
scratch [i] = 0.0;
}
/* Drop a sample from each gate and add the next one */
if (i - ngate >= 0) {
sum_above = sum_above - fabs (trace [i - ngate]) + fabs (trace [i]);
}
else {
sum_above = sum_above + fabs (trace[i]);
rabove = rabove + 1.0;
}
if (i + ngate +1< nsamps) {
sum_below = sum_below - fabs (trace[i + 1])
+ fabs (trace [i + ngate + 1]);
}
else {
if (i +1 < nsamps && trace[i+1]!=0.0) {
sum_below = sum_below - fabs (trace[i + 1]);

Other Docs

Known Problems

ampRatio.c373

Developers Programming Guide

rbelow = rbelow - 1.0;


}
}

}
/* Put the final results in place. Note that we have not handled the
edge problem, we have simply made the function undefined */
for (i = 0; i < nsamps; i++) {
trace [i] = scratch[i];
}
/* Find the maximum of the ratio function */
*ratio_max = trace [imin_samp ];
ind_max = imin_samp;
for (i = imin_samp ; i< imax_samp; i++) {
if (trace [i] > *ratio_max) {
ind_max = i;
*ratio_max = trace [i];
}
}
/* Covert the index of the maximum to time*/
*ratio_time = (float) (ind_max ) * samprate;

Other Docs

Known Problems

ampRatio.c374

Other Docs

Developers Programming Guide

Known Problems

375

Developers Programming Guide

Appendix: Ensemble Tool Examples

The appendix provides examples of two types of ProMAX


Ensemble tools: AVO and trace interpolation. The AVO routine
outputs a single trace for each trace ensemble that is input. The
trace interpolation routine creates and outputs a trace between
each of the input traces.

Topics covered in this appendix:

AVO Ensemble Tools

avo.menu

avo.inc

avo.f

avoC.c
Trace Interpolation Tools

prestk_interp.menu

prestk_interp.inc

prestk_interp.f

prestk_interp.c

Other Docs

Known Problems

AVO Ensemble Tools376

Developers Programming Guide

AVO Ensemble Tools


This routine outputs a single trace for each trace ensemble that
is input. The trace sample values are the slope or intercept of a
least squares fit line through the trace amplitudes, as a function
of offset at a given time. The menu file is presented, then the
FORTRAN version and C versions of the code are presented.
The menu file works with either the FORTRAN or C versions.

Fortran Note:
This example shows things that are often done in ensemble
tools. The important points to remember from the INIT_
subroutine are that MAXDTRz (the maximum number of traces
in an ensemble that will be leaving the EXEC_ subroutine) is
set to 1, the type of data is set to ISTACKEDpz, and the trace
number is no longer valid after this process, so
ITRNO_VALIDz is set to 0. The important points in the
EXEC_ subroutine are that the trace header values (particularly
the end-of-ensemble flag) are set, and the trace executive is
notified that the number of traces to be returned from
EXEC_ AVO_DEMO is 1. This is accomplished through setting
the calling argument NSTORED to 1.

C Note:
This example shows things that are often done in ensemble
tools. The important points to remember from the init_
subroutine are that globalRuntime->maxdtr (the maximum
number of traces in an ensemble that will be leaving the exec_
subroutine) is set to 1, the type of data is set to ISTACKED, and
the trace number is no longer valid after this process, so
ITRNO_VALID is set to 0. The important points in the exec_
subroutine are that the trace header values (particularly the
end-of-ensemble flag) are set, and the trace executive is notified
that the number of traces to be returned from exec_avo_demo_
is 1. This is accomplished through setting the calling argument
*nStored to 1.

Other Docs

Known Problems

avo.menu377

Developers Programming Guide

avo.menu
'(
name: AVO_DEMO
label: "AVO Demo"
value_tab: 35
parameter: AVO_OPT
text: "Type of AVO output"
type: circular:
type_desc: (
("Slope"
1 "Output AVO slope." )
("Intercept" 2 "Output AVO intercept." )
)
value: 1
mouse_text: "Use MB1 to rotate between choices for type of AVO output."
exec_data: ("AVO_DEMO"
("GENERAL"
("AVO_OPT"
implicit: (value 'AVO_OPT))
)
)
)

Other Docs

Known Problems

avo.inc378

Developers Programming Guide

avo.inc
C-----------------------------------------------------------------------------C
Include file for AVO_DEMO
C-----------------------------------------------------------------------------IMPLICIT NONE
#include "global.inc"

&

COMMON /SAVED_PARMS/ SAVE1z, IH_OFFSET, IH_END_ENS, IH_TRACENO,


IH_TR_FOLD, IX_X, IX_Y, IX_WT, IOPT

&

INTEGER LENSAVED, IX_X, IX_Y, IH_OFFSET, IH_END_ENS, IH_TRACENO,


IH_TR_FOLD, IX_WT, IOPT

C
C
C
C

.....
.....
.....
.....

Specify the number of variables to save. This is set here (rather


than in the initialization routine) so that programmers don't forget
to change it when they are changing the contents of the common
block SAVED_PARMS.
DATA LENSAVED /8/

C
C
C
C
C
C
C
C

.....
.....
.....
.....
.....
.....
.....
.....

IH_OFFSET - index in header of offset


IH_END_ENS - index in header of end-of-ensemble flag
IH_TRACENO - index in header of trace number
IH_TR_FOLD - index in header of trace fold
IX_X - index of buffer to store X values before linear regression
IX_Y - index of buffer to store Y values before linear regression
IX_WT - index of buffer to store weight values before linear regression
IOPT - option for slope or intercept

Other Docs

Known Problems

avo.f379

Developers Programming Guide

avo.f
C-----------------------------------------------------------------------------C
C
Description:
C
Standard initialization routine
C
C
Output arguments:
C
LEN_SAVE - number of 4-byte words to save for re-entrancy
C
ITOOLTYPE - processing tool type
C
C-----------------------------------------------------------------------------SUBROUTINE INIT_AVO_DEMO( LEN_SAV, ITOOLTYPE )
C ..... The include file "avo.inc" contains an include for the global
C ..... parameters ("global.inc")
#include "avo.inc"
INTEGER LEN_SAV, ITOOLTYPE, IERR, LENGTH, IFORMAT, ISLOPEPZ,
&
INTERCEPTPZ
CHARACTER CDESC*32
PARAMETER ( ISLOPEPZ=1, INTERCEPTPZ=2 )
C ..... Issue a fatal error if the data is already stacked
IF ( IDTYPz .EQ. ISTACKEDpz ) CALL EX_ERR_FATAL(
&
'This process cannot operate on stacked data' )
C ..... Call for the input parameters by name. Allow user to output
C ..... slope or intercept.
IOPT = 0
CALL EX_GETPARM( 'AVO_OPT ', 1, IOPT )
IF ( IOPT .NE. ISLOPEPZ .AND. IOPT .NE. INTERCEPTPZ ) THEN
CALL EX_ERR_FATAL( 'AVO_OPT not recognized' )
ENDIF
C ..... Get buffers to store the values before linear regression
CALL MEM_RESBUFF( MAXDTRz, IX_X, IERR )
CALL MEM_RESBUFF( MAXDTRz, IX_Y, IERR )
CALL MEM_RESBUFF( MAXDTRz, IX_WT, IERR )
C ..... Get the indices of the headers that we need
CALL HDR_NAMINFO( 'OFFSET ', CDESC, LENGTH,
&
IH_OFFSET, IERR )
IF ( IERR .NE. 0 ) CALL EX_ERR_FATAL(
&
'OFFSET not found in header' )
CALL HDR_NAMINFO( 'END_ENS ', CDESC, LENGTH,
&
IH_END_ENS, IERR )
IF ( IERR .NE. 0 ) CALL EX_ERR_FATAL(
&
'END_ENS not found in header' )
CALL HDR_NAMINFO( 'TRACENO ', CDESC, LENGTH,
&
IH_TRACENO, IERR )
IF ( IERR .NE. 0 ) CALL EX_ERR_FATAL(
&
'TRACENO not found in header' )
CALL HDR_NAMINFO( 'TR_FOLD ', CDESC, LENGTH,
&
IH_TR_FOLD, IERR )
IF ( IERR .NE. 0 ) CALL EX_ERR_FATAL(

Other Docs

IFORMAT,

IFORMAT,

IFORMAT,

IFORMAT,

Known Problems

avo.f380

Developers Programming Guide

&

'TR_FOLD not found in header' )

C ..... The trace number is no longer valid, since we are now stacked
ITRNO_VALIDz = 0
C ..... Set the general data type to stacked (not really stacked, but
C ..... more similar to stacked than other types)
IDTYPz = ISTACKEDpz
C ..... Reset the maximum number of data traces per ensemble, for
C ..... subsequent tools.
MAXDTRz = 1
C ..... Set the number of words that need to be saved for re-entrancy
LEN_SAV = LENSAVED
C ..... Set the tool type to ensemble
ITOOLTYPE = IENSEMBLEpz
RETURN
END

C-----------------------------------------------------------------------------C
C
Description:
C
Standard execution routine
C
C
Input/output arguments:
C
TRACES - 2-d array of trace samples
C
ITHDRS - 2-d array of trace header (as integer)
C
RTHDRS - 2-d array of trace header (as floating point)
C
NSTORED - number of stored traces
C
C-----------------------------------------------------------------------------SUBROUTINE EXEC_AVO_DEMO( TRACES, ITHDRS, RTHDRS, NSTORED )
C ..... The include file "avo.inc" contains an include for the global
C ..... parameters ("global.inc")
#include "avo.inc"
C ..... Include the file that allows use of the "space array"
#include "mem.inc"
INTEGER NSTORED, ITHDRS(NTHz,NSTORED), INDEX, IERR
REAL TRACES(NUMSMPz,NSTORED), RTHDRS(NTHz,NSTORED)
C ..... No action required in cleanup phase
IF ( CLEANUPz ) RETURN
C ..... Call
CALL
&
&

the actual work routine


AVO_DEMO_WORK( TRACES, ITHDRS, NUMSMPz, NTHz, NSTORED,
IH_OFFSET, IOPT, RSPACEz(IX_X), RSPACEz(IX_Y),
RSPACEz(IX_WT), TRACES )

C ..... The output trace is the end of a one-trace ensemble


ITHDRS(IH_END_ENS,1) = LASTTRpz
C ..... Assign the "fold"
RTHDRS(IH_TR_FOLD,1) = FLOAT(NSTORED)

Other Docs

Known Problems

avo.f381

Developers Programming Guide

C ..... Make the trace number null


ITHDRS(IH_TRACENO,1) = INULLpz
C ..... Set the number of output traces
NSTORED = 1
RETURN
END

C-----------------------------------------------------------------------------C
C
Actual work routine
C
C------------------------------------------------------------------------------

&

&
&

SUBROUTINE AVO_DEMO_WORK( TRACES, RTHDRS, NUMSMP, NTH, NSTORED,


IH_OFFSET, IOPT, X, Y, WT, TRACE )
IMPLICIT NONE
INTEGER NUMSMP, NTH, NSTORED, IH_OFFSET, I, J, ISLOPEPZ,
INTERCEPTPZ, IOPT
REAL TRACES(NUMSMP,NSTORED), RTHDRS(NTH,NSTORED), TRACE(NUMSMP),
SLOPE, RINTER, X(NSTORED), Y(NSTORED), WT(NSTORED)
PARAMETER ( ISLOPEPZ=1, INTERCEPTPZ=2 )

C ..... Special case for one trace


IF ( NSTORED .EQ. 1 ) THEN
IF ( IOPT .EQ. ISLOPEPZ ) THEN
C ............. The slope is undefined, but let's use zero
CALL VFILL( 0.0, TRACE, 1, NUMSMP )
ELSEIF ( IOPT .EQ. INTERCEPTPZ ) THEN
C ............. The intercept is just the sample values
CALL VMOV( TRACES, 1, TRACE, 1, NUMSMP )
ENDIF
RETURN
ENDIF
C ..... The X values (offset) will not change, so let's get them once
DO 100 J=1,NSTORED
X(J) = RTHDRS(IH_OFFSET,J)
C ......... While we're at it, let's set the weights
WT(J) = 1.0
100
CONTINUE
C ..... Loop over all of the samples in the traces
DO 120 I=1,NUMSMP
C ......... Load the values at a particular time
DO 110 J=1,NSTORED
Y(J) = TRACES(I,J)
110
CONTINUE
C ......... Regress a line through the points
CALL WT_LIN_REG( X, Y, WT, NSTORED, SLOPE, RINTER )
IF ( IOPT .EQ. ISLOPEPZ ) THEN
TRACE(I) = SLOPE
ELSEIF ( IOPT .EQ. INTERCEPTPZ ) THEN

Other Docs

Known Problems

avo.f382

Developers Programming Guide

TRACE(I) = RINTER
ENDIF
120

CONTINUE
RETURN
END

C-----------------------------------------------------------------------------C
SUBROUTINE WT_LIN_REG( X_IN, Y_IN, WT, NPTS, A, B )
C-----------------------------------------------------------------------------C
C
Description:
C
C
Weighted linear regression routine. Least squares analysis
C
is performed to solve y = Ax + B. Does not handle infinite
C
slope.
C
C
Input arguments:
C
X_IN - array of X values
C
Y_IN - array of Y values
C
WT
- array of weights
C
C
Output arguments:
C
A
- slope
C
B
- intercept
C
C-----------------------------------------------------------------------------SUBROUTINE WT_LIN_REG( X_IN, Y_IN, WT, NPTS, A, B )
IMPLICIT NONE
INTEGER I, NPTS
REAL X_IN(NPTS), Y_IN(NPTS), WT(NPTS)
REAL X, SWX, SWY, SW, SWXY, SWX2, B, A
C ..... Initialize:
SWX = 0.0
SWY = 0.0
SW
= 0.0
SWXY = 0.0
SWX2 = 0.0
C ..... Compute the constants for a weighted linear regression
DO 100 I=1, NPTS
X = WT(I) * X_IN(I)
SWX = SWX + X
SWY = SWY + WT(I) * Y_IN(I)
SW
= SW
+ WT(I)
SWXY = SWXY + X * Y_IN(I)
SWX2 = SWX2 + X * X_IN(I)
100
CONTINUE
C ..... Compute the slope and intercept
A = (SW * SWXY - SWY * SWX) / (SW * SWX2 - SWX * SWX)
B = (SWY - A * SWX) / SW
RETURN
END

Other Docs

Known Problems

avoC.c383

Developers Programming Guide

avoC.c
/* include ProMAX prototypes and globals */
#include "cpromax.h"
#include "cglobal.h"
/* define the saved
BEGINPARMS
int outputOpt ;
float *xVals ;
float *yVals ;
float *weights;
ENDPARMS (parms)

parameters (user input, etc) */


/*
/*
/*
/*

flag to output slope or intercept */


vector of x values for lin regression */
vector of y values for lin regression */
vector of weights used in lin regression */

/* functions defined and used internally */


static void avoDemoWork( float*, float*, int );
static void avoDemoWtLinReg( float*, float*, float*,
int, float*, float* );
/* functions defined elsewhere and used here */
float **fVecTo2d( float*, int, int );

/* define option names */


#define ISLOPE 1
#define INTERCEPT 2
/*-------------------------------------------------------------------*/
/* init_avo_exer
/*
/* initialization routine for ProMAX module avo_exer
/*
/*-------------------------------------------------------------------*/
void init_avo_demo_( int *len_sav, int *itooltype )
{
/* local versions
int
outputOpt
float *xVals
float *yVals
float *weights

of external parameters */
;
;
;
;

/* local variables */
int iErr;
/* connect with global variables */
GlobalRuntime *gr = globalRuntime;
/* issue a fatal error if data is already stacked */
if( gr->idtyp == ISTACKED ){
exErrFatal("This process does not operate on stacked data.");
}
/* see if the user wants to output slope or intercept */
outputOpt = 0;
exParGetInt( "AVO_OPT", &outputOpt );

Other Docs

Known Problems

avoC.c384

Developers Programming Guide

if( outputOpt != ISLOPE && outputOpt != INTERCEPT ){


exErrFatal("Output option not recognized.");
}
/* allocate space needed for linear regression */
xVals
= (float*)malloc( gr->maxdtr * sizeof(float));
yVals
= (float*)malloc( gr->maxdtr * sizeof(float));
weights = (float*)malloc( gr->maxdtr * sizeof(float));
if( xVals == NULL || yVals == NULL || weights == NULL ){
exErrFatal("Memory allocation error in init phase.");
}
/* check for the existance of headers we will need */
if( hdrExists("OFFSET") != 1 ){
exErrFatal(" 'OFFSET' was not found in the trace headers.");
}
if( hdrExists("END_ENS") != 1 ){
exErrFatal(" 'END_ENS' was not found in the trace headers.");
}
if( hdrExists("TRACENO") != 1 ){
exErrFatal(" 'TRACENO' was not found in the trace headers.");
}
if( hdrExists("TR_FOLD") != 1 ){
exErrFatal(" 'TR_FOLD' was not found in the trace headers.");
}
/* the trace number is no longer valid, 1 trace/ensemble output */
gr->itrno_valid = 0;
/* set the general data type to stacked. Its not really stacked */
/* but it is closer to stacked than any of the other types.
*/
gr->idtyp = ISTACKED;
/* reset the maximum number of data traces output per ensemble. */
/* This value is set for subsequent tools */
gr->maxdtr = 1;
/* set the number of words that need to be saved for re-entrancy */
*len_sav = NPARMS(parms);
/* set the tool type */
*itooltype = IENSEMBLE;
/* set the external
parms->outputOpt
parms->xVals
parms->yVals
parms->weights

saved parameters */
= outputOpt;
= xVals
;
= yVals
;
= weights ;

}
/*-------------------------------------------------------------------*/
/* exec_avo_exer
/*
/* execution routine for ProMAX module avo_exe
/*
/* input and output args:
/* traces - the data traces in continuous memory
/* rthdrs - floating point trace headers

Other Docs

Known Problems

avoC.c385

Developers Programming Guide

/* ithdrs - integer trace headers


/* nStored - number of traces in the input array
/*-------------------------------------------------------------------*/

void exec_avo_demo_( float *traces, float *rthdrs, int *ithdrs,


int *nStored )
{

/* local
int
float
float
float

versions of
outputOpt =
*xVals
=
*yVals
=
*weights =

external parameters */
parms->outputOpt;
parms->xVals
;
parms->yVals
;
parms->weights ;

/* local variables */
int iErr;
/* connect with global variables */
GlobalRuntime *gr = globalRuntime;
/* see if we are in cleanup phase */
if( gr->cleanup ){
free( xVals );
free( yVals );
free( weights );
return;
}
/* call the actual work routine */
avoDemoWork( traces, rthdrs, *nStored );
/* the header being output is the first one in the array. */
/* the output trace is the last one in the ensemble */
ithdrs[hdrIndex("END_ENS")] = LASTTR;
/* assign the fold */
rthdrs[hdrIndex("TR_FOLD")] = (float)(*nStored);
/* make the trace number NULL */
ithdrs[hdrIndex("TRACENO")] = INULL;
/* set the number of output traces to be picked up by the */
/* trace executive and sent to subsequent modules */
*nStored = 1;
}
/*-------------------------------------------------------------------*/
/* acutual work routine
/* input/output
/*
traces - the input traces in continuous memory
/* input:
/*
rthdrs - floating point header array, in continuous memory
/*
nStored - number of traces in the ensemble
/*-------------------------------------------------------------------*/

Other Docs

Known Problems

avoC.c386

Developers Programming Guide

void avoDemoWork( float *traces, float *rthdrs, int nStored )


{
/* local variables */
int i, j, iErr;
float **rhdrs, **tracs;
float slope, intercept;
/* connect with global variables */
GlobalRuntime *gr = globalRuntime;
/* handle the special case of one trace */
if( nStored == 1 ){
if( parms->outputOpt == ISLOPE ){
/* ..... the slope is undefined, use zero for output */
vFill( 0.0, traces, 1, gr->numsmp );
}
else{
/* ..... the intercept is just the sample values in the trace */
return;
}
}
/* put the 1D array into a more convenient form for C */
rhdrs = fVecTo2d( rthdrs, nStored, gr->nth );
tracs = fVecTo2d( traces, nStored, gr->numsmp );
/* the offset values will not change, get them just once */
for( i = 0; i < nStored; i++ ){
parms->xVals[i] = rhdrs[i][hdrIndex("OFFSET")];
/* .. fill the weighting array while were at it */
parms->weights[i] = 1.0;
}
/* loop over all the samples */
for( i = 0; i < gr->numsmp; i++ ){
/* .. load the sample amplitudes at the current time */
for( j = 0; j < nStored ; j++ ){
parms->yVals[j] = tracs[j][i];
}
/* .. fit a lsf line through the points */
avoDemoWtLinReg( parms->xVals, parms->yVals, parms->weights,
nStored, &slope, &intercept );
/* .. output the appropriate value */
if( parms->outputOpt == ISLOPE ){
traces[i] = slope;
}
else{
traces[i] = intercept;
}
}
/* free the memory allocated in fVecTo2D */
free( rhdrs );
free( tracs );

Other Docs

Known Problems

avoC.c387

Developers Programming Guide

}
/*-------------------------------------------------------------------*/
/* weighted linear regression routine. A least squares analysis is
/* performed to solve y=ax+ b. Does not handle infinite slope.
/*
/* input:
/*
x_in - array of input x values
/*
y_in - arrry of input y values
/*
wt
- array of input weights
/*
npts - number of points in regression
/*
/* output:
/*
a - slope
/*
b - intercept
/*
/*-------------------------------------------------------------------*/
void avoDemoWtLinReg( float *x_in, float *y_in, float *wt, int npts,
float *a, float *b )
{
/* variables */
int i;
float x, swx, swy, sw, swxy, swx2;
/* initialize */
swx = 0.0;
swy = 0.0;
sw
= 0.0;
swxy = 0.0;
swx2 = 0.0;
/* compute the constants for a linear regression */
for( i= 0; i< npts; i++ ){
x = wt[i] * x_in[i];
swx += x;
swy += wt[i]*y_in[i];
sw
+= wt[i];
swxy += x*y_in[i];
swx2 += x*x_in[i];
}
/* compute the slope and intercept */
*a = ( (sw*swxy)-(swy*swx))/( (sw*swx2)-(swx*swx));
*b = (swy - (*a * swx) )/sw;
}

Other Docs

Known Problems

Trace Interpolation Tools388

Developers Programming Guide

Trace Interpolation Tools


The following sections show how an ensemble tool can output
more traces than it inputs. The tool simply creates and outputs a
trace between each of the input traces.

Other Docs

Known Problems

prestk_interp.menu389

Developers Programming Guide

prestk_interp.menu
'(
name: PRESTK_INTERP
label: "Prestack Interpolation"
value_tab: 35
exec_data: ("PRESTK_INTERP"
("GENERAL"
("dummy"
implicit: 1)
)
)
)

Other Docs

Known Problems

prestk_interp.inc390

Developers Programming Guide

prestk_interp.inc
C-----------------------------------------------------------------------------C
Include file for PRESTK_INTERP
C-----------------------------------------------------------------------------IMPLICIT NONE
#include "global.inc"
COMMON /SAVED_PARMS/ SAVE1z
INTEGER LENSAVED
DATA LENSAVED /1/

Other Docs

Known Problems

prestk_interp.f391

Developers Programming Guide

prestk_interp.f
C
C
C
C

.....
.....
.....
.....

This is an example of an ensemble tool that outputs MORE traces


than it inputs. It is a simple minded pre-stack trace interpolator,
that outputs one traces between every existing pair of traces (as the
simple mean of the sample values).
SUBROUTINE INIT_PRESTK_INTERP( LEN_SAV, ITOOLTYPE )

#include "prestk_interp.inc"
INTEGER LEN_SAV, ITOOLTYPE

&

IF ( IDTYPz .EQ. ISTACKEDpz ) CALL EX_ERR_FATAL(


'This process not intended for stacked data' )

C ..... The trace number is no longer valid, since we are adding new traces
C ..... that have no corresponding slots in the database.
ITRNO_VALIDz = 0
C ..... Reset the maximum number of data traces per ensemble
MAXDTRz = MAXDTRz*2 - 1
C ..... Set the number of words for re-entrancy and the tool type
LEN_SAV = LENSAVED
ITOOLTYPE = IENSEMBLEpz
RETURN
END

SUBROUTINE EXEC_PRESTK_INTERP( TRACES, ITHDRS, RTHDRS, NSTORED )


#include "prestk_interp.inc"
INTEGER NSTORED, ITHDRS(NTHz,NSTORED), I, J
REAL TRACES(NUMSMPz,NSTORED), RTHDRS(NTHz,NSTORED)
C ..... No action required in cleanup phase
IF ( CLEANUPz ) RETURN
C ..... Can't interpolate with just one trace in the ensemble
IF ( NSTORED .EQ. 1 ) RETURN
C ..... Interpolate the sample values
DO 110 I=1,NUMSMPz
DO 100 J=NSTORED,2,-1
TRACES(I,J*2-1) = TRACES(I,J)
TRACES(I,J*2-2) = (TRACES(I,J) + TRACES(I,J-1)) / 2.0
100
CONTINUE
110
CONTINUE
C ..... Take care of the headers too (interpolated traces will have a copy
C ..... of the header just before them)
DO 130 I=1,NTHz
DO 120 J=NSTORED,2,-1
ITHDRS(I,J*2-1) = ITHDRS(I,J)

Other Docs

Known Problems

prestk_interp.f392

120
130

Developers Programming Guide

ITHDRS(I,J*2-2) = ITHDRS(I,J-1)
CONTINUE
CONTINUE

C ..... Set the number of output traces


NSTORED = NSTORED*2 - 1
RETURN
END

Other Docs

Known Problems

prestk_interp.c393

Developers Programming Guide

prestk_interp.c
/* include ProMAX prototypes and globals */
#include "cpromax.h"
#include "cglobal.h"
/* define saved parameters */
BEGINPARMS
int dummy; /* doesn't actually have to be here */
ENDPARMS(parms)
void init_prestk_interp_(int *len_sav, int *itooltype);
void exec_prestk_interp_(float *trace, int *ithdr,
float *rthdr, int* nStored);

/*------------------------------------------------------------------Description:
Initialization routine for prestack interp
output arguments:
len_save - number of 4-byte words to save for re-entrancy
itooltype - processing tool type
---------------------------------------------------------------------*/
void init_prestk_interp_(int *len_sav, int *itooltype)
{
/* get access to global runtime variables */
GlobalRuntime *gr = globalRuntime;
/* The trace number is no longer valid, since we are adding new traces */
/* that have no corresponding slots in the database.*/
gr->itrno_valid = FALSE;
/* Reset the maximum number of data traces per ensemble */
gr->maxdtr = 2*gr->maxdtr - 1;

/* Set the number of words that need to be saved for re-entrancy.


*len_sav = NPARMS (parms);

*/

/* set the tool type */


*itooltype = IENSEMBLE;
}

/*********************************************************************
*
*
Description:
*
Execution routine for prestack interp

Other Docs

Known Problems

prestk_interp.c394

Developers Programming Guide

*
*
Input/output arguments:
*
traces - array of trace samples
*
ithdrs - trace header (as integer)
*
rthdrs - trace header (as floating [point)
/*
nStored - number of traces input and output
*
**********************************************************************/

void exec_prestk_interp_(float *traces, int *ithdrs,


float *rthdrs, int*nStored)
{
GlobalRuntime *gr = globalRuntime;
int i, j;
/* A place to store the 2-d input array, these are just pointers */
/* to locations in the input traces and rthdrs arrays. */
float **trcs, **rhdrs;
/* No action required in cleanup phase */
if( gr->cleanup ){
return;
}
/* Can't interpolate with just one trace in the ensemble */
if( *nStored == 1 ){
return;
}

/* Put all
/* that is
trcs =
rhdrs =

available trace and header locations into an array */


easy to handle. */
fVecTo2d( traces, 2*(*nStored)-1, gr->numsmp );
fVecTo2d( rthdrs, 2*(*nStored)-1, gr->nth );

/* Interpolate the sample values */


for( i = 0; i < gr->numsmp; i++ ){
for( j = *nStored-1; j > 0; j-- ){
trcs[2*j][i]
= trcs[j][i];
trcs[2*j-1][i] = (trcs[j][i] + trcs[j-1][i])/2.;
}
}
/* Take care of the headers too, interpolated traces will have a copy */
/* of the header just before them */
for( i = 0; i < gr->nth; i++ ){
for( j = *nStored-1; j > 0; j-- ){
rhdrs[2*j][i]
= rhdrs[j][i];
rhdrs[2*j-1][i] = rhdrs[j-1][i];
}
}
/* Set the number of output traces */
*nStored = 2*(*nStored) - 1;

Other Docs

Known Problems

prestk_interp.c395

Developers Programming Guide

free( trcs );
free( rhdrs );

Other Docs

Known Problems

prestk_interp.c396

Other Docs

Developers Programming Guide

Known Problems

397

Developers Programming Guide

Appendix: Panel Tool Examples

This appendix provides examples of panel tools. The examples


demonstrate several important points:

the panel parameters must be chosen

the panel parameters must be reported to the trace


executive through the routine EX_PANEL_PARMS, and
the panel parameters can be changed by
EX_PANEL_PARMS

the programmer should be aware of how to handle the


padded trace array

The examples also demonstrate how panels overlap and mix,


depending upon the panel parameters chosen.
A menu file is presented first, followed by FORTRAN and C
examples. The menu file serves both the C and FORTRAN
code.

Topics covered in this appendix:

Other Docs

panel_test.menu
panel_test.inc
panel_test.f
panelTest.c

Known Problems

panel_test.menu398

Developers Programming Guide

panel_test.menu
'(
name: PANEL_TEST
label: "Panel Test"
value_tab: 42
parameter: PANLSIZE
text: "Panel size"
type: typein:
type_desc: ( int: 7 nil nil )
value: 21
mouse_text "Enter the number of traces per panel."
parameter: PANLEDGE
text: "Panel edge"
type: typein:
type_desc: ( int: 7 nil nil )
value: 5
mouse_text "Enter the size of the panel edge."
parameter: PANL_MIX
text: "Panel mix"
type: typein:
type_desc: ( int: 7 nil nil )
value: 0
mouse_text "Enter the size of the panel mix."
parameter: PANL_TPD
text: "Panel trace pad"
type: typein:
type_desc: ( int: 7 nil nil )
value: 0
mouse_text "Enter the size of the panel trace pad."
parameter: PANL_SPD
text: "Panel sample pad"
type: typein:
type_desc: ( int: 7 nil nil )
value: 0
mouse_text "Enter the size of the panel sample pad."
exec_data: ("PANEL_TEST"
("GENERAL"
("version" implicit: "%Z%%M%
("PANLSIZE" implicit: (value
("PANLEDGE" implicit: (value
("PANL_MIX" implicit: (value
("PANL_TPD" implicit: (value
("PANL_SPD" implicit: (value
)
)
)

Other Docs

%I% %G%" )
'PANLSIZE))
'PANLEDGE))
'PANL_MIX))
'PANL_TPD))
'PANL_SPD))

Known Problems

panel_test.inc399

Developers Programming Guide

panel_test.inc
C-----------------------------------------------------------------------------C
Include file for PANEL_TEST
C-----------------------------------------------------------------------------IMPLICIT NONE
#include "global.inc"
COMMON /SAVED_PARMS/ SAVE1z, RVAL, NPAD_SAMPS, NPAD_TRACES
INTEGER LENSAVED, NPAD_SAMPS, NPAD_TRACES
REAL RVAL
C ..... Specify the number of variables to save
DATA LENSAVED /4/
C ..... SCCS:

Other Docs

@(#)panel_test.inc

50.1

3/10/94

Known Problems

panel_test.f400

Developers Programming Guide

panel_test.f

SUBROUTINE INIT_PANEL_TEST( LEN_SAV, ITOOLTYPE )


#include "panel_test.inc"
INTEGER LEN_SAV, ITOOLTYPE, NPANEL_SIZE, NPANEL_EDGE,
&
NPANEL_MIX
CHARACTER CSCCS_KEY*50
CALL EX_GETPARM( 'PANLSIZE', 1,
CALL EX_GETPARM( 'PANLEDGE', 1,
CALL EX_GETPARM( 'PANL_MIX', 1,
C ..... Get padding in time and traces,
CALL EX_GETPARM( 'PANL_TPD', 1,
CALL EX_GETPARM( 'PANL_SPD', 1,

NPANEL_SIZE )
NPANEL_EDGE )
NPANEL_MIX )
send through .inc file
NPAD_TRACES )
NPAD_SAMPS )

C ..... Set the panel parameters (and allow them to be returned with a
C ..... different value).
CALL EX_PANEL_PARMS( NPANEL_SIZE, NPANEL_EDGE, NPANEL_MIX,
&
NPAD_TRACES, NPAD_SAMPS )
RVAL = 1.0
LEN_SAV = LENSAVED
ITOOLTYPE = IPANELpz
RETURN
END

SUBROUTINE EXEC_PANEL_TEST( TRACES, ITHDRS, RTHDRS, NSTORED )


#include "panel_test.inc"
INTEGER NSTORED, ITHDRS(NTHz,NSTORED), I, J
REAL TRACES(NUMSMPz+NPAD_SAMPS,NSTORED), RTHDRS(NTHz,NSTORED)
IF ( CLEANUPz ) RETURN

100
110

DO 110 J=1,NSTORED
DO 100 I=1,NUMSMPz+NPAD_SAMPS
TRACES(I,J) = RVAL
CONTINUE
CONTINUE

C ..... increase the sample value for this panel


RVAL = RVAL + 1.0
C ..... Write values to padded traces, you will not see the result,
C ..... this is just to demonstrate where the padded traces are.
DO 130 J = NSTORED+1, NSTORED+NPAD_TRACES
DO 120 I = 1, NUMSMPz+NPAD_SAMPS
TRACES(I,J) = RVAL
120
CONTINUE

Other Docs

Known Problems

panel_test.f401

130

Developers Programming Guide

CONTINUE

RETURN
END

Other Docs

Known Problems

panelTest.c402

Developers Programming Guide

panelTest.c
/* include ProMAX prototypes and globals */
#include "cpromax.h"
#include "cglobal.h"
/* define the saved parameters (user input, etc) */
BEGINPARMS
int nPadTraces; /* number of padding traces */
int nPadSamples; /* number of padding samples */
float sampValue;
/* value of trace samples */

ENDPARMS (parms)
/*-------------------------------------------------------------------*/
/* init_panel_test
/*
/* initialization routine for ProMAX module sine_wave
/*
/*-------------------------------------------------------------------*/
void init_panel_test_( int *len_sav, int *itooltype )
{
/* local variables */
int panelSize;
int panelEdge;
int panelMix;
/* local versions of external parms */
int nPadTraces;
int nPadSamples;
/* get the panel parameters
exParGetInt( "PANLSIZE",
exParGetInt( "PANLEDGE",
exParGetInt( "PANL_MIX",

*/
&panelSize );
&panelEdge );
&panelMix );

/* get the padding parameters and pass to exec */


exParGetInt( "PANL_TPD", &nPadTraces );
exParGetInt( "PANL_SPD", &nPadSamples );
parms->nPadTraces = nPadTraces;
parms->nPadSamples = nPadSamples;
/* set the panel parameters. Note that the argument values can be */
/* changed by this routine*/
exPanelParms( &panelSize, &panelEdge, &panelMix,
&nPadTraces, &nPadSamples );
/* initialize the trace sample value */
parms->sampValue = 1.0;
/* set the number of words that need to be saved for re-entrancy */
*len_sav = NPARMS(parms);

Other Docs

Known Problems

panelTest.c403

Developers Programming Guide

/* set the tool type to panel */


*itooltype = IPANEL;
}
/*-------------------------------------------------------------------*/
/* exec_panelTest
/*
/* execution routine for ProMAX module panel_test
/* input and output args:
/* traces - the data traces in continuous memory
/* rthdrs - floating point trace headers
/* ithdrs - integer trace headers
/* nStored - number of traces in the input array panel
/*-------------------------------------------------------------------*/
void exec_panel_test_( float *traces, float *rthdrs, int *ithdrs,
int *nStored )
{
/* local variables */
float **tracs;
int i,j;
int nTraces, nSamples;
/* connect with global variables */
GlobalRuntime *gr = globalRuntime;
/* see if we are in cleanup phase */
if( gr->cleanup ){
return;
}
/*
/*
/*
/*

calculate the number of samples per trace in the */


padded array. The trace length in the padded array is NOT */
reflected in the global parameter gr->numsmp. The programmer */
must account for the padding.*/
nSamples = gr->numsmp + parms->nPadSamples;

/* calculate the number of traces that are actually in the array. */


/* The value *nStored is the number of live data traces. The */
/* programmer must also keep track of the padding traces. */
nTraces = *nStored + parms->nPadTraces;
/* put the 1D traces array into a more convenient form for C */
tracs = fVecTo2d( traces, nTraces, nSamples );
/* set the trace sample values for the live traces in the panel */
for( i = 0; i < *nStored; i++ ){
for( j = 0; j < nSamples; j++ ){
tracs[i][j] = parms->sampValue;
}
}
/* set the trace sample values for the padding traces. You won't */
/* see the result of this, it is just for demonstration of where */
/* the padding traces are located in the trace array */
for( i = *nStored; i < nTraces; i++ ){

Other Docs

Known Problems

panelTest.c404

Developers Programming Guide

for( j = 0; j < nSamples; j++ ){


tracs[i][j] = parms->sampValue;
}
}
/* increase the trace sample value for the next panel */
parms->sampValue += 1.0;
/* free the memory allocated by fVecTo2d() */
free( tracs );
}

Other Docs

Known Problems

405

Developers Programming Guide

Appendix: Single Buffer Tool


Examples

This appendix provides examples of two types of single buffer


tools. The first type is an ensemble definition program in
FORTRAN. The second type is a pre-stack trace interpolation
program that has the same output as prestk_interp, a C language
ensemble tool.

Topics covered in this appendix:

Other Docs

ens_define.menu
ens_define.inc
ens_define.f
interp_sb.menu
interp_sb.c

Known Problems

ens_define.menu406

Developers Programming Guide

ens_define.menu
'(
name: ENS_DEFINE
label: "Ensemble Re-define"
value_tab: 51

parameter: PRIM_KEY
text: "Select PRIMARY key to re-define output ensembles"
type: function:
type_desc: (header_list headers)
value: "NONE
"
selected_item: "**INVALID**"
mouse_text: "Use MB1 to select a header word from the headers menu as the PRIMARY
key for re-defining input ensembles."

parameter: MAXTR
text: "Maximum traces per output ensemble"
type: typein:
type_desc: ( int: 5 1 nil )
value: 0
mouse_text: "What is the maximum number of traces per output ensemble AFTER redefining the ensembes?"

exec_data: ("ENS_DEFINE"
("GENERAL"
("version" implicit: "@(#)ens_define.menu
("PRIM_KEY" implicit: (value 'PRIM_KEY))
("MAXTR"
implicit: (value 'MAXTR))
)
)

40.1

11/24/92" )

Other Docs

Known Problems

ens_define.inc407

Developers Programming Guide

ens_define.inc
C-----------------------------------------------------------------------------C
Include file for ENS_DEFINE.
C
C
Original code by S. Rutt Bridges, April 30, 1991.
C-----------------------------------------------------------------------------IMPLICIT NONE
#include "global.inc"

&

C
C
C
C
C
C
C

.....
.....
.....
.....
.....
.....
.....

COMMON /SAVED_PARMS/ SAVE1z, IH_PRIM, ITRC_COUNT, IX_TRACE,


IX_THDR, IFIRST_ENTRY, NOUT_EXEC
INTEGER IH_PRIM, ITRC_COUNT, IX_TRACE, IX_THDR, IFIRST_ENTRY
INTEGER LENSAVED, NOUT_EXEC
DATA LENSAVED /7/
IH_PRIM - index of the primary key used to merge ensembles
ITRC_COUNT - counter for the number of dumped traces in an ensemble
IX_TRACE - address of the memory used to hold the last trace
IX_THDR - address of the memory used to hold the last trace header
IFIRST_ENTRY - value is 1 the very first time the executive is entered
Number of traces to output in exec phase
SCCS: @(#)ens_define.inc 31.4 6/18/92

Other Docs

Known Problems

ens_define.f408

Developers Programming Guide

ens_define.f
C-----------------------------------------------------------------------------C
C
Initialization routine for ENS_DEFINE
C
C
ENS_DEFINE is an ensemble definition tool. It resets ensemble flags
C
based on a change in a header word. Output ensembles may be larger
C
or smaller, depending on the changes in the header word. Examples of
C
the use of this tool:
C
C
1. In the Ensemble Decon Parameter Test macro, we input data that
C
has a primary sort key of 'REPEAT' and a secondary sort key of
C
'CDP'. For the subsequent CDP stack, we need to have ensembles
C
defined by CDP. ENS_DEFINE provides this function.
C
C
2. Typically for Radon Filtering, we need to use Ensemble Split to
C
seperate the positive and negative offsets. However, for a
C
subsequent CDP stack these traces need to form a single ensemble.
C
ENS_DEFINE provides this function.
C
C
3. To create a single ensemble from a CDP stack, you should use the
C
special option of setting the primary header key word to NONE
C
which will force the entire dataset to be combined into a single
C
ensemble.
C
C
Output parameters:
C
LEN_SAV - the number of parameters that must be saved
C
ITOOLTYPE
- the tool type
C
C
Original code by S. Rutt Bridges, April 30, 1991.
C-----------------------------------------------------------------------------SUBROUTINE INIT_ENS_DEFINE( LEN_SAV, ITOOLTYPE )
#include "ens_define.inc"
#include "runtime.inc"
CHARACTER CDESC*32, CPRIM_KEY*8
INTEGER LEN_SAV, ITOOLTYPE, IERR, LENGTH, IFORMAT, NCHARS
INTEGER MAXDTR, IOPTION
CHARACTER CSCCS_KEY*50
DATA CSCCS_KEY /'@(#)ens_define.f 31.5 6/18/92'/
C ..... issue a stern warning if the tool is within an IF conditional
IF (IF_DEPTHrz.NE.0) CALL EX_ERR_HELP( 'Warning: Ensemble '
&
// 'Re-define should not be used within IF''s !'
&
//'|Click here to CONTINUE (job may fail)'
&
//'|Click here to STOP'//CNULLpz, IOPTION )
IF (IOPTION.EQ.3) CALL EX_ERR_STOP(
&
'Stopping execution as requested...' )
C ..... initialize for the exec phase
ITRC_COUNT = 0
IFIRST_ENTRY = 1
C ..... get the primary key name for ensemble redefinition

Other Docs

Known Problems

ens_define.f409

Developers Programming Guide

CALL EX_CGETPARM( 'PRIM_KEY', 1, CPRIM_KEY, NCHARS )


cdd - this in now allowed, as a way of indicating that we don't care what the
cdd
primary key is
c
IF (CPRIM_KEY(1:4) .EQ. 'NONE')
c
&
CALL EX_ERR_FATAL( 'Primary key must be specified.' )
IF ( CPRIM_KEY(1:4) .EQ. 'NONE' ) THEN
IH_PRIM = 0
ELSE
C ......... get the index in the trace header of the primary key
CALL HDR_NAMINFO( CPRIM_KEY, CDESC, LENGTH, IFORMAT,
&
IH_PRIM, IERR )
IF (IERR.NE.0) CALL EX_ERR_FATAL('Primary key '//CPRIM_KEY//
&
' does not occur in the trace header.')
ENDIF
C ..... reset the primary ensemble sort order
IF (CPRIM_KEY(1:3).EQ.'CDP') THEN
IPSORTz = ICDPpz
ELSEIF (CPRIM_KEY(1:6).EQ.'SOURCE') THEN
IPSORTz = ISINpz
ELSEIF (CPRIM_KEY(1:3).EQ.'SIN') THEN
IPSORTz = ISINpz
ELSEIF (CPRIM_KEY(1:4).EQ.'FFID') THEN
IPSORTz = ISINpz
ELSEIF (CPRIM_KEY(1:8).EQ.'REC_SLOC') THEN
IPSORTz = IRECSLOCpz
ELSEIF (CPRIM_KEY(1:4).EQ.'CHAN') THEN
IPSORTz = ICHANpz
ELSEIF (CPRIM_KEY(1:6).EQ.'OFFSET') THEN
IPSORTz = IOFFSETpz
ELSEIF (CPRIM_KEY(1:7).EQ.'AOFFSET') THEN
IPSORTz = IOFFSETpz
ELSE
IPSORTz = IUNKNOWNpz
ENDIF
C ..... get the maximum number of traces per output ensemble
CALL EX_GETPARM( 'MAXTR
', 1, MAXDTR )
IF (MAXDTR.LE.0) CALL EX_ERR_FATAL( 'The maximum number of '
& // 'traces per output ensemble MUST be specified!' )
MAXDTRz = MAXDTR
C ..... Set the maximum number of traces to buffer, and the trace and
C ..... sample padding.
CALL EX_BUFF_PARMS( MAXDTRz+1, 0, 0 )
C ..... This tool can process trace headers only
CALL EX_THDRONLY_OK
C ..... set the number of words that need to be saved and the tool type
LEN_SAV
= LENSAVED
ITOOLTYPE = ISNL_BUFFpz
RETURN
END

Other Docs

Known Problems

ens_define.f410

Developers Programming Guide

C-----------------------------------------------------------------------------C
Flow routine for ENS_DEFINE.
C------------------------------------------------------------------------------

&

SUBROUTINE FLOW_ENS_DEFINE( TRACES, ITHDRS, RTHDRS, NSTORED,


IFOUND_EOJ, NOUTPUT, NOVERLAP )

#include "ens_define.inc"
INTEGER NSTORED, ITHDRS(NTHz,NSTORED), IFOUND_EOJ, NOUTPUT,
&
NOVERLAP, J
REAL TRACES(NUMSMPz,NSTORED), RTHDRS(NTHz,NSTORED)
C ..... Initialize the number to output to zero (not ready yet)
NOUTPUT = 0
IF ( IFOUND_EOJ .EQ. 1 ) THEN
C ......... We have reached the end of the data, output whatever we have
NOUTPUT = NSTORED
RETURN
ENDIF
IF ( IH_PRIM .NE. 0 ) THEN
C ......... We are looking for the primary key value to change
DO 100 J=2,NSTORED
IF ( ITHDRS(IH_PRIM,J) .NE. ITHDRS(IH_PRIM,J-1) ) THEN
C ................. Output up to the change
NOUTPUT = J-1
NOUT_EXEC = NOUTPUT
C ................. Save what it not output for next time
NOVERLAP = NSTORED - NOUTPUT
RETURN
ENDIF
100
CONTINUE
ENDIF
RETURN
END

C-----------------------------------------------------------------------------C
C
Execution routine for ENS_DEFINE
C
C
Input parameters:
C
NTR_BUFF - size of the trace buffer (MAX(NSTORED, NOUTPUT)
C
from FLOW_ENS_DEFINE
C
C
Input/output parameters:
C
ITHDRS - 2-d array of INTEGER*4 trace header entries
C
RTHDRS - 2-d array of REAL*4 trace header entries
C
C
Unused parameters:
C
TRACES - 2-D array of trace samples
C
C
Original code by S. Rutt Bridges, April 30, 1991.

Other Docs

Known Problems

ens_define.f411

Developers Programming Guide

C
Rewritten as a single buffered tools by D.E. Diller, May 12, 1992
C
C-----------------------------------------------------------------------------SUBROUTINE EXEC_ENS_DEFINE( TRACES, ITHDRS, RTHDRS, NTR_BUFF )
#include "ens_define.inc"
#include "header.inc"
INTEGER NTR_BUFF, J, ITHDRS(NTHz,NTR_BUFF)
REAL TRACES(NUMSMPz,NTR_BUFF), RTHDRS(NTHz,NTR_BUFF)
C ..... no action needed for cleanup mode
IF (CLEANUPz) RETURN
C ..... Set the header values
DO 100 J=1,NOUT_EXEC
ITHDRS(ISEQNOz,J) = J
ITHDRS(IEND_ENSz,J) = NLASTpz
100
CONTINUE
ITHDRS(IEND_ENSz,NOUT_EXEC) = LASTTRpz
RETURN
END

Other Docs

Known Problems

interp_sb.menu412

Developers Programming Guide

interp_sb.menu
'(
name: INTERP_SB
label: "Single Buffer Trace Interpolation"
value_tab: 35
exec_data: ("INTERP_SB"
("GENERAL"
("dummy"
implicit: 1)
)
)
)

Other Docs

Known Problems

interp_sb.c413

Developers Programming Guide

interp_sb.c
/*--------------------------------------------------------------------------*/
/* interp_sb
/* An example of a single buffer tool in C. The program collects an ensemble
/* of data traces then passes the ensemble on to the exec_ subroutine.
/* The program uses a change in Primary sort key value to detect that
/* there has been a change in the ensemble rather than by using the END_ENS
/* flag. This is done for demonstration of the nOverlap variable in
/* the flow routine. The output data traces are the original traces
/* plus a trace that is linearly interpolated between each input trace.
/* The output ensemble therefore has 2*N - 1 traces where
/* N is the number of input traces.
/*
/* The example called interp_db.c is identical to this example except that
/* this is a single buffer tool and therefore the input trace buffer also
/* serves as the ouptut trace buffer.
/*-------------------------------------------------------------------------*/
/* include promax interface, globals, error codes, etc */
#include "cpromax.h"
#include "cglobal.h"
/* define saved parameters */
BEGINPARMS
int nInEnsemble; /* the number of traces passed to the exec subroutine */
int pKeyHdrIndx; /* index of the primary sort key trace header (FFID, CDP etc)
*/
ENDPARMS(parms)
/*-------------------------------------------------------------------*/
/*
/* description:
/*
initialization routine for interp_sb:
/*
/* output arguments:
/*
len_sav - length of the saved common block
/*
itooltype - type of tool
/*
/*-------------------------------------------------------------------*/
void init_interp_sb_( len_sav, itooltype )
int *len_sav, *itooltype;
{
int max_to_buffer, nPadTraces, nPadSamples;
/* set the global pointers */
GlobalRuntime *gr = globalRuntime;
/* set the number of words that need to be saved */
*len_sav = NPARMS(parms);

Other Docs

Known Problems

interp_sb.c414

/*
/*
/*
/*
/*
/*

Developers Programming Guide

Get the header array index for the primary sort key of the input data. */
Note that 1 is subracted from the value of globalRuntime->ipkey */
to obtain the index of the primary sort key that is appropriate for */
the C language. The global variable trace indicies are indexed for */
FORTRAN. This rule is true for globalRuntime->iskey as well as */
the standard headers. */
parms->pKeyHdrIndx = gr->ipkey - 1;

/*
/*
/*
/*
/*

Notify trace exec of maximum number of traces it will have to hold for */
this module. The ex_buff_parms_() routine must be called in the init */
subroutine of any buffered tool. NOTE that the routine is a FORTRAN */
routine that is being directly called by this C routine so the address of */
the variables are passed. */
max_to_buffer = 2*gr->maxdtr;
nPadTraces = 0;
nPadSamples = 0;
ex_buff_parms_( &max_to_buffer, &nPadTraces, &nPadSamples );

/* we are going to output more traces per ensemble than are input */
gr->maxdtr = (2*gr->maxdtr) - 1;
/* set the tool type */
*itooltype = ISNL_BUFF;
}

/*--------------------------------------------------------------------*/
/*
/* flow tool for interp_sb
/*
/* input args
/*
traces - 2d array of data traces
/*
ithdrs - 2-d array of input integer trace headers
/*
rthdrs - 2-d array of input float trace headers
/*
/*
/*--------------------------------------------------------------------*/
flow_interp_sb_( float *traces, int *ithdrs, float *rthdrs,
int *nStored, int *ifound_eoj, int *nOutput, int *nOverlap )
{
GlobalRuntime *gr = globalRuntime;
float **rhdrs;

/*
/*
/*
/*
/*

if( *nStored == 1 ){
.. There is only one trace so we can't compare it to anything. This */
.. situtation should only occur on the first call to the routine unless */
.. the last trace input is a single-trace ensemble in which case more */
.. code would be needed to handle that special case. We leave out that */
.. extra code here as it would clutter the example. */
*nOutput = 0;
return;
}

Other Docs

Known Problems

interp_sb.c415

Developers Programming Guide

/* put the trace headers into a 2d array that is easy to handle */


rhdrs = fVecTo2d( rthdrs, *nStored, gr->nth );
/* see if the primary key header value of most recent input trace has changed */
if( rhdrs[*nStored-2][parms->pKeyHdrIndx] != rhdrs[*nStored-1][parms>pKeyHdrIndx] ||
*ifound_eoj != 0 ){
/* .. we have found enough traces to process */
/* .. Set the number of traces to output from exec, a non-zero value tells */
/* .. the trace executive that it is time to pass the traces to */
/* .. exec_interp_sb_ */
*nOutput = 2*(*nStored-1) - 1;
/* .. set the number of traces that are being passed to the exec_ subroutine */
parms->nInEnsemble = *nStored - 1;
/* .. Let the last trace input on this call be the first trace input */
/* .. on the next call since it is part of the next ensemble that we */
/* .. will be collecting. */
*nOverlap = 1;
}
else{
/* .. signal the trace executive that we aren't ready to pass traces exec_ */
*nOutput = 0;
}
free( rhdrs );

}
/*-------------------------------------------------------------------*/
/*
/*
description:
/*
exectution routine for interp_sb
/*
/*
input arguments:
/*
nStored - the amount of memory available (in traces) in the
/*
traces array. NOTE that the actual number of traces
/*
input was determined in the flow_interp_sb routine and
/*
passed to exec_interp_sb via the parms->nInEnsemble
/*
variable.
/*
/*
input/output arguments:
/*
traces - 2-d array of traces
/*
ithdrs - 2-d array of integer trace headers
/*
rthdrs - 2-d array of float trace headers
/*
/*-------------------------------------------------------------------*/
void exec_interp_sb_( float *traces, int *ithdrs,
float *rthdrs, int *nStored )
{
float **rhdrs, **tracs;

Other Docs

Known Problems

interp_sb.c416

Developers Programming Guide

int i,j;
/* set the global pointers */
GlobalRuntime *gr = globalRuntime;
/* if cleaning up release memory, close files, in this case there is nothing to
do */
if( gr->cleanup){
return;
}

/* Arrange the trace and header arrays into 2d arrays that are easy to handle. */
tracs = fVecTo2d( traces, *nStored, gr->numsmp );
rhdrs = fVecTo2d( rthdrs, *nStored, gr->nth );
/* Interpolate the sample values */
for( i = 0; i < gr->numsmp; i++ ){
for( j = parms->nInEnsemble-1; j > 0; j-- ){
tracs[2*j][i]
= tracs[j][i];
tracs[2*j-1][i] = (tracs[j][i] + tracs[j-1][i])/2.;
}
}
/* Take care of the headers too, interpolated traces will have a copy */
/* of the header just before them */
for( i = 0; i < gr->nth; i++ ){
for( j = parms->nInEnsemble-1; j > 0; j-- ){
rhdrs[2*j][i]
= rhdrs[j][i];
rhdrs[2*j-1][i] = rhdrs[j-1][i];
}
}
free( tracs );
free( rhdrs );
}

Other Docs

Known Problems

417

Developers Programming Guide

Appendix: Double Buffer Tool


Examples

This appendix provides examples of a double buffer tool. The


FORTRAN example calculates semblance for an input CDP
gather. The C example is a pre-stack interpolation routine that
outputs the same result as interp_sb.c, a single buffer tool.

Topics covered in this appendix:

Other Docs

semblance.menu
semblance.inc
semblance.f
interp_db.menu
interp_db.c

Known Problems

semblance.menu418

Developers Programming Guide

semblance.menu
'(
name: SEMBLANCE
label: "Semblance Vel Analysis"
parameter: VSTART
text: "Minimum analysis velocity"
type: typein:
type_desc: ( real: 7 1.0e-5 nil )
value: -1.0
mouse_text: "Minimum expected stacking velocity."
parameter: VEND
text: "Maximum analysis velocity"
type: typein:
type_desc: ( real: 7 1.0e-4 nil )
value: -1.0
mouse_text: "Maximum expected stacking velocity."
parameter: NVELS
text: "Number of test velocities"
type: typein:
type_desc: ( int: 3 1 999 )
value: 25
mouse_text: "Number of constant velocities to use to compute semblance values."
parameter: NORM
text: "Semblance normalization mode"
type: pop_choose:
type_desc: (
("Scale Time Slice"
1 "Divide time slice of semblance values by the maximum in
time slice.")
("Scale Panel" 2 "Divide all semblance values by the maximum semblance in
panel.")
("No Scaling"
3 "Do no scaling of semblance values.")
)
mouse_text: "Choose method of normalizing semblances."
parameter: RNOISE
text: "Noise factor for normalization"
type: typein:
type_desc: ( real: 3 0.0 nil )
value: 0.1
mouse_text: "Add this value to maximum semblance (in time slice, or panel) before
scaling. Recommend 0.0 to 0.4"
parameter: STRETCH
text: "Stretch factor"
type: typein:
type_desc: ( real: 3 0.0 999.0 )
value: 50.0
mouse_text: "Maximum percentage stretch allowed in NMO calculation?"
parameter: MIN_FOLD
text: "Minimum fold"
type: typein:

Other Docs

Known Problems

semblance.menu419

Developers Programming Guide

type_desc: ( int: 2 1 99 )
value: 4
mouse_text: "Minimum fold required for semblance calculation?"

exec_data: ("SEMBLANCE"
("GENERAL"
("version " implicit: "@(#)semblance.menu
("VSTART " implicit: (value 'VSTART))
("VEND
" implicit: (value 'VEND))
("NVELS
" implicit: (value 'NVELS))
("NORM
" implicit: (value 'NORM))
("RNOISE " implicit: (value 'RNOISE))
("STRETCH " implicit: (value 'STRETCH))
("MIN_FOLD" implicit: (value 'MIN_FOLD))
)
)

40.1

11/24/92" )

rules: (

(rule1 ( or ( = (value 'NORM) 1 ) ( = (value 'NORM) 2 ) )


(progn (do_show 'RNOISE))
(progn (do_not_show 'RNOISE)))

(VEL_default_rule1 (and ( = ( value 'VSTART) -1.0 )


( = ( db_parmget_line "IUNITSz") 1 ) ) (set_value 'VSTART 4500.0 )
)
(VEL_default_rule2 ( = ( value 'VSTART) -1.0 ) (set_value 'VSTART 1400.0 )
)
(VEL_default_rule3 (and ( = ( value 'VEND) -1.0 )
( = ( db_parmget_line "IUNITSz") 1 ) ) (set_value 'VEND 20000.0 )
)
(VEL_default_rule4 ( = ( value 'VEND) -1.0 ) (set_value 'VEND 7000.0 ) )
)
)

Other Docs

Known Problems

semblance.inc420

Developers Programming Guide

semblance.inc
IMPLICIT NONE
C-----------------------------------------------------------------------------C
Include file for SEMBLANCE
C-----------------------------------------------------------------------------#include "global.inc"

&
&

COMMON /SAVED_PARMS/ SAVE1z, VSTART, VEND, NVELS, IX_VELSAVE,


IH_VEL, MIN_FOLD, RNOISE, NORM, STRETCH, NOUT, NFFT,
IX_WORK2, IX_WORK3, IX_VNMO

&

REAL VSTART, VEND, RNOISE, STRETCH


INTEGER NVELS, LENSAVED, IX_VELSAVE, MIN_FOLD, NORM,
IX_VELS, IH_VEL, NOUT, NFFT, IX_WORK2, IX_WORK3, IX_VNMO

C ..... Specify the number of variables to save


DATA LENSAVED /15/
C
C
C
C
C
C
C
C
C
C
C
C
C
C

.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....

VSTART - starting velocity


VEND - ending velocity
NVELS - number of velocities
IX_VELS - index of buffer of semblance velocities
IH_VEL - index of new trace header word
MIN_FOLD - min fold to calculate semblance
NORM - semblance normalization option
RNOISE - noise factor
STRETCH - maximum stretch allowed for nmo
NOUT - number of "traces" to output
NFFT - length of FFT for envelope calculation
IX_WORK2 - index of work buffer 1
IX_WORK3 - index of work buffer 2
IX_VNMO - index of buffer for VNMO

C ..... SCCS: @(#)semblance.inc

Other Docs

31.4

5/14/92

Known Problems

semblance.f421

Developers Programming Guide

semblance.f
C-----------------------------------------------------------------------------C
Initialization routine for SEMBLANCE
C-----------------------------------------------------------------------------SUBROUTINE INIT_SEMBLANCE( LEN_SAV, ITOOLTYPE )
#include "semblance.inc"
#include "hdr_err.inc"
#include "header.inc"
CHARACTER CDESC*32
INTEGER IERR, IFORMAT, LEN_SAV, ITOOLTYPE, LENGTH, IOK_HDR,
&
MAXDTRZ_SAVE
CHARACTER CSCCS_KEY*50
DATA CSCCS_KEY /'@(#)semblance.f 31.6 5/14/92'/
C ..... Must not be stacked data
IF ( IDTYPz .EQ. ISTACKEDpz ) CALL EX_ERR_FATAL(
&
'Cannnot operate on stacked data' )
C ..... The trace number is no longer valid, and the geometry no longer matches
ITRNO_VALIDz = 0
IGEOM_MATCHz = 0
C ..... Get the starting velocity
VSTART = -1.0
CALL EX_GETPARM( 'VSTART ', 1, VSTART )
IF ( VSTART .EQ. -1.0 ) CALL EX_ERR_FATAL(
&
'Starting velocity must be specified' )
C ..... Get the ending velocity
VEND = -1.0
CALL EX_GETPARM( 'VEND
', 1, VEND )
IF ( VEND .EQ. -1.0 ) CALL EX_ERR_FATAL(
&
'Ending velocity must be specified' )
C ..... Get the number of velocities
NVELS = 0
CALL EX_GETPARM( 'NVELS
', 1, NVELS )
IF ( NVELS .LE. 0 ) CALL EX_ERR_FATAL(
&
'Number of velocities must be specified' )
C ..... We will actually output 3 extra traces
NOUT = NVELS + 3
C ..... get the normalization method
NORM = 0
CALL EX_GETPARM( 'NORM
', 1, NORM )
IF ( NORM .LE. 0 ) CALL EX_ERR_FATAL(
&
'Norm method is not specified' )
C ..... Get the noise factor
RNOISE = 0.1
CALL EX_GETPARM( 'RNOISE ', 1, RNOISE )
IF ( RNOISE .LT. 0.0 ) CALL EX_ERR_FATAL(

Other Docs

Known Problems

semblance.f422

&

Developers Programming Guide

'Noise factor must be specified' )

C ..... Get the minimum fold


MIN_FOLD = 3
CALL EX_GETPARM( 'MIN_FOLD', 1, MIN_FOLD )
IF ( MIN_FOLD .LT. 0 ) CALL EX_ERR_FATAL(
&
'Minimum fold must be specified' )
C ..... Get the nmo stretch factor in percent
STRETCH = 50.0
CALL EX_GETPARM( 'STRETCH ', 1, STRETCH )
IF ( STRETCH .LE. 0 ) CALL EX_ERR_FATAL(
&
'Stretch factor must be specified' )
C ..... Reserve a buffer to save the velocities
CALL MEM_RESBUFF( NVELS, IX_VELSAVE, IERR )
C ..... Deal with the maximum number of traces per ensemble
MAXDTRZ_SAVE = MAXDTRz
IF ( NOUT .GT. MAXDTRz ) THEN
MAXDTRz = NOUT
ENDIF
C ..... Get length of FFT for envelope calculation
CALL GET_NFFT(NINT(NUMSMPz*1.25), NFFT)
C ..... Get and keep some
CALL MEM_RESBUFF(
CALL MEM_RESBUFF(
CALL MEM_RESBUFF(

small working buffers


NFFT+2, IX_WORK2, IERR )
NFFT+2, IX_WORK3, IERR )
NUMSMPz, IX_VNMO, IERR )

cdd - No, lie so we can use branched flows


cddC ..... Reset the data type to transformed unstacked data
cdd
IDTYPz = IUS_TRANSpz
cdd - No, lie so we can use branched flows
cddC ..... Reset the domain to semblance
cdd
IDOMAINz = ISEMBpz
C ..... Made
IF (
&
IF (
&
IF (
&

sure that OFFSET, END_ENS, and TRACENO are present


IOK_HDR(IOFFSETz) .NE. 1 ) CALL EX_ERR_FATAL(
'OFFSET not found in trace header' )
IOK_HDR(IEND_ENSz) .NE. 1 ) CALL EX_ERR_FATAL(
'END_ENS not found in trace header' )
IOK_HDR(ITRACENOz) .NE. 1 ) CALL EX_ERR_FATAL(
'TRACENO not found in trace header' )

C ..... Create a velocity trace header word


CDESC = 'Semblance velocity'
CALL HDR_ADD( 'SEMB_VEL', CDESC, 1, IREAL4pz, IH_VEL, IERR )
IF ( IERR .EQ. IERR_HDR_EXSTpz ) THEN
CALL EX_ERR_WARN(
&
'Semblance velocity already exists in trace header' )
IERR = 0
ELSEIF ( IERR .NE. 0 ) THEN
CALL EX_ERR_FATAL( 'Cannot create new trace header word' )
ENDIF
C ..... Set the maximum number of traces to buffer, and the trace and

Other Docs

Known Problems

semblance.f423

Developers Programming Guide

C ..... sample padding.


CALL EX_BUFF_PARMS( MAXDTRZ_SAVE, 0, 0 )
C ..... Set the number of words that need to be saved and set the tool type
LEN_SAV = LENSAVED
ITOOLTYPE = IDBL_BUFFpz
RETURN
END

C-----------------------------------------------------------------------------C
Flow routine for SEMBLANCE.
C------------------------------------------------------------------------------

&

SUBROUTINE FLOW_SEMBLANCE( TRACES, ITHDRS, RTHDRS, NSTORED,


IFOUND_EOJ, NOUTPUT, NOVERLAP )

#include "semblance.inc"
#include "header.inc"
INTEGER NSTORED, ITHDRS(NTHz,NSTORED), IFOUND_EOJ, NOUTPUT,
&
NOVERLAP
REAL TRACES(NUMSMPz,NSTORED), RTHDRS(NTHz,NSTORED)
C ..... We're just looking for the end of an ensemble
IF ( IFOUND_EOJ .EQ. 1
&
.OR. ITHDRS(IEND_ENSz,NSTORED) .EQ. LASTTRpz ) THEN
NOUTPUT = NOUT
ELSE
NOUTPUT = 0
ENDIF
C ..... We don't want to see any of the input traces again
NOVERLAP = 0
RETURN
END

C-----------------------------------------------------------------------------C
Execution routine for SEMBLANCE.
C------------------------------------------------------------------------------

&
&

SUBROUTINE EXEC_SEMBLANCE( TRACES_IN, ITHDRS_IN, RTHDRS_IN,


NTR_BUFF_IN, TRACES_OUT, ITHDRS_OUT, RTHDRS_OUT,
NTR_BUFF_OUT )

#include "semblance.inc"
#include "mem.inc"
#include "header.inc"
INTEGER NTR_BUFF_IN, NTR_BUFF_OUT, J, IERR, IX_WORK1,
&
ITHDRS_IN(NTHz,NTR_BUFF_IN),
&
ITHDRS_OUT(NTHz,NTR_BUFF_OUT)
REAL TRACES_IN(NUMSMPz,NTR_BUFF_IN),
&
TRACES_OUT(NUMSMPz,NTR_BUFF_OUT),

Other Docs

Known Problems

semblance.f424

&
&

Developers Programming Guide

RTHDRS_IN(NTHz,NTR_BUFF_IN),
RTHDRS_OUT(NTHz,NTR_BUFF_OUT)
IF (CLEANUPz) RETURN

C ..... Calculate the semblance (also need one addition scratch buffer)
CALL MEM_RESBUFF( NTR_BUFF_IN*NUMSMPz, IX_WORK1, IERR )
CALL SEMBLANCE_WORK( TRACES_IN, NUMSMPz, RTHDRS_IN, NTHz,
&
NTR_BUFF_IN, RSPACEz(IX_WORK1), RSPACEz(IX_WORK2),
&
RSPACEz(IX_WORK3), TRACES_OUT, NVELS, NOUT,
&
RSPACEz(IX_VNMO), IOFFSETz, SAMPRATz, VSTART, VEND,
&
IH_VEL, RSPACEz(IX_VELSAVE), INA_STATz, NFFT, NORM,
&
RNOISE, MIN_FOLD, STRETCH )
CALL MEM_FREEBUFF( NTR_BUFF_IN*NUMSMPz, IX_WORK1, IERR )
C ..... Create the output headers
DO 100 J=1,NTR_BUFF_OUT
C ......... Just copy the last header
CALL VMOV( ITHDRS_IN(1,NTR_BUFF_IN), 1,
&
ITHDRS_OUT(1,J), 1, NTHz )
C ......... Make the offset zero
RTHDRS_OUT(IOFFSETz,J) = 0.0
C ......... Set the velocity and round off to nearest 10 for labeling neatness
RTHDRS_OUT(IH_VEL,J) = NINT( RSPACEz(IX_VELSAVE+J-1)
&
/ 10.0 ) * 10.0
C ......... Make the trace number null
ITHDRS_OUT(ITRACENOz,J) = INULLpz
C ......... Set the END_ENS flag
ITHDRS_OUT(IEND_ENSz,J) = NLASTpz
IF ( J .EQ. NTR_BUFF_OUT )
&
ITHDRS_OUT(IEND_ENSz,J) = LASTTRpz
100
CONTINUE
RETURN
END

&
&
&

&
&
&
&
&

SUBROUTINE SEMBLANCE_WORK( TRACES, NSAMPS, RTHDRS, NTH, NSTORED,


TRWORK, WORK2, WORK3, VELARR, NVELS, NOUT, VNMO,
IH_OFFSET, SAMPRATE, VSTART, VEND, IH_VEL, VELSAVE,
IH_NA_STAT, NFFT, NORM, RNOISE, MIN_FOLD, STRETCH)
IMPLICIT NONE
INTEGER NSAMPS, NTH, NSTORED, IH_OFFSET, I, J, K, NVELS, NSUMS,
IH_VEL, LENHALF, NFFT, NORM, MIN_FOLD, IH_NA_STAT, NOUT
REAL TRACES(NSAMPS,NSTORED), TRWORK(NSAMPS,NSTORED), STATIC,
VNMO(NSAMPS), VELARR(NSAMPS,NOUT), SAMPRATE, VSTART,
VEND, VINC, VEL, OFFSET, VELT, VELV, VELSAVE(NVELS),
STRETCH, RTHDRS(NTH,NSTORED), WORK2(NSAMPS), SUM, SUM2,
WORK3(NSAMPS), RMAX, RNOISE, RMAX_PANL

C ..... Initialize:
VINC = (VEND - VSTART) / FLOAT(NVELS-1)
C ..... AGC all of the data first (1000.0 ms or the trace length)
LENHALF = NINT( ( 1000.0 / SAMPRATE ) / 2.0 )
IF ( LENHALF .GT. NSAMPS/2 ) LENHALF = NSAMPS/2

Other Docs

Known Problems

semblance.f425

&
90

Developers Programming Guide

DO 90 J=1,NSTORED
CALL STAT_AGC_RUNAVG( TRACES(1,J), WORK2, NSAMPS,
LENHALF, 0 )
CONTINUE

C ..... Loop thru all of the velocities


DO 200 K=1,NVELS
C ......... Velocity increment based on delta-t
VELT = 1.0 /
&
( 1.0/VSTART - (1.0/VSTART-1.0/VEND) * FLOAT(K-1)
&
/ FLOAT(NVELS-1) )
C ......... Velocity increment based on delta-v
VELV = VSTART + FLOAT(K-1) * VINC
C ......... Use compromise between delta-t and delta-v
VEL = ( VELT + VELV ) / 2.0
C ......... Store the velocity in the trace header
RTHDRS(IH_VEL,K) = VEL
C ......... Save the velocity
VELSAVE(K) = VEL
C ......... Load the velocity array
DO 100 I=1,NSAMPS
VNMO(I) = VEL
100
CONTINUE
C ......... Loop thru all of the traces, applying NMO
DO 110 J=1,NSTORED
CALL VMOV( TRACES(1,J), 1, TRWORK(1,J), 1, NSAMPS )
OFFSET = ABS( RTHDRS(IH_OFFSET,J) )
STATIC = RTHDRS(IH_NA_STAT,J)
CALL NMO_APPLY( TRWORK(1,J), VNMO, WORK2, WORK3,
&
STRETCH, OFFSET, NSAMPS, SAMPRATE, STATIC, 2 )
110
CONTINUE
C ......... Calculate the semblance
DO 130 I=1,NSAMPS
SUM = 0.0
SUM2 = 0.0
NSUMS = 0
DO 120 J=1,NSTORED
IF ( TRWORK(I,J) .NE. 0.0 ) THEN
C ..................... Stack
SUM = SUM + TRWORK(I,J)
C ..................... Stack the squares
SUM2 = SUM2 + TRWORK(I,J)*TRWORK(I,J)
NSUMS = NSUMS + 1
ENDIF
120
CONTINUE
IF ( NSUMS .GT. MIN_FOLD ) THEN
C ................. signed semblance
C ............. try bias to force down the low fold times
VELARR(I,K) = (SUM*ABS(SUM)) / (FLOAT(NSUMS)*SUM2)
ELSE
VELARR(I,K) = 0.0
ENDIF
130
CONTINUE
C ......... compute envelope of signed semblance

Other Docs

Known Problems

semblance.f426

Developers Programming Guide

CALL VMOV( VELARR(1,K), 1, VNMO, 1, NSAMPS)


C ......... compute the 90 degree phase shifted version of the semb. trace
CALL PHASEFILTER( VNMO, NSAMPS, 90.0, NFFT, WORK2, WORK3)
C ......... compute the env of semblance
DO 135 I=1,NSAMPS
VELARR(I,K) = SQRT( VNMO(I)**2 + VELARR(I,K)**2 )
135
CONTINUE
C ......... Smooth in time fixed 3 samples - smooth remaining notches
LENHALF = 3 / 2
CALL STAT_AGC_RUNAVG( VELARR(1,K), WORK2, NSAMPS, LENHALF, 1
& )

200

CONTINUE

C ...... calculate power bar on side of plot


C ........ find max semblance
CALL MAXV( VELARR(1,1), 1, RMAX_PANL, J, NVELS*NSAMPS)
DO 210 I=1, NSAMPS
C ......... find max semblance across time slice
CALL MAXV( VELARR(I,1), NSAMPS, RMAX, J, NVELS)
C ......... scale each time slice
IF (RMAX_PANL .GT. 0.0) THEN
VELARR(I,NVELS+1) = 0.0
VELARR(I,NVELS+2) = RMAX/RMAX_PANL
VELARR(I,NVELS+3) = RMAX/RMAX_PANL
ENDIF
210
CONTINUE
C ...... Scale semblances if necessary
IF ( NORM .EQ. 1 ) THEN
DO 220 I=1, NSAMPS
C ............ find max semblance across time slice
CALL MAXV( VELARR(I,1), NSAMPS, RMAX, J, NVELS)
C ............ scale each time slice individually
IF (RMAX .GT. 0.0) THEN
RMAX = (1.0 + RNOISE) / (RMAX + RNOISE)
CALL VSMUL(VELARR(I,1), NSAMPS, RMAX, VELARR(I,1),
&
NSAMPS, NVELS - 2)
ENDIF
220
CONTINUE
ELSEIF ( NORM .EQ. 2) THEN
RMAX = RMAX_PANL
C ......... scale all semblance values
IF (RMAX .GT. 0.0) THEN
RMAX = (1.0 + RNOISE) / (RMAX + RNOISE)
CALL VSMUL(VELARR(1,1), 1, RMAX, VELARR(1,1),
&
1, NVELS*NSAMPS)
ENDIF
ENDIF
RETURN
END

Other Docs

Known Problems

interp_db.menu427

Developers Programming Guide

interp_db.menu
'(
name: INTERP_DB
label: "Double Buffer Trace Interpolation"
value_tab: 35
exec_data: ("INTERP_DB"
("GENERAL"
("dummy"
implicit: 1)
)
)
)

Other Docs

Known Problems

interp_db.c428

Developers Programming Guide

interp_db.c
/*--------------------------------------------------------------------------*/
/* interp_db
/* An example of a double buffer tool in C. The program collects an ensemble
/* of data traces then passes the ensemble on to the exec_ subroutine.
/* The program uses a change in Primary sort key value to detect that
/* there has been a change in the ensemble rather than by using the END_ENS
/* flag. This is done for demonstration of the nOverlap variable in
/* the flow routine. The output data traces are the original traces
/* plus a trace that is linearly interpolated between each input trace.
/* The output ensemble therefore has 2*N - 1 traces where
/* N is the number of input traces.
/*
/* The single buffer tool example called interp_sb.c is identical to
/* this example except that this is a double buffer tool and therefore
/* the data traces from the input buffer are mapped to the separate
/* output trace buffer.
/*-------------------------------------------------------------------------*/
/* include promax interface, globals, error codes, etc */
#include "cpromax.h"
#include "cglobal.h"
/* define saved parameters */
BEGINPARMS
int nInEnsemble; /* the number of traces passed to the exec subroutine */
int pKeyHdrIndx; /* index of the primary sort key trace header (FFID, CDP etc)
*/
ENDPARMS(parms)
/*-------------------------------------------------------------------*/
/*
/* description:
/*
initialization routine for interp_sb:
/*
/* output arguments:
/*
len_sav - length of the saved common block
/*
itooltype - type of tool
/*
/*-------------------------------------------------------------------*/
void init_interp_db_( len_sav, itooltype )
int *len_sav, *itooltype;
{
int max_to_buffer, nPadTraces, nPadSamples;
/* set the global pointers */
GlobalRuntime *gr = globalRuntime;
/* set the number of words that need to be saved */
*len_sav = NPARMS(parms);

Other Docs

Known Problems

interp_db.c429

/*
/*
/*
/*
/*
/*

Developers Programming Guide

Get the header array index for the primary sort key of the input data. */
Note that 1 is subracted from the value of globalRuntime->ipkey */
to obtain the index of the primary sort key that is appropriate for */
the C language. The global variable trace indicies are indexed for */
FORTRAN. This rule is true for globalRuntime->iskey as well as */
the standard headers. */
parms->pKeyHdrIndx = gr->ipkey - 1;

/*
/*
/*
/*
/*

Notify trace exec of maximum number of traces it will have to hold for */
this module. The ex_buff_parms_() routine must be called in the init */
subroutine of any buffered tool. NOTE that the routine is a FORTRAN */
routine that is being directly called by this C routine so the address of */
the variables are passed. */
max_to_buffer = 2*gr->maxdtr;
nPadTraces = 0;
nPadSamples = 0;
ex_buff_parms_( &max_to_buffer, &nPadTraces, &nPadSamples );

/* we are going to output more traces per ensemble than are input */
gr->maxdtr = (2*gr->maxdtr) - 1;
/* set the tool type */
*itooltype = IDBL_BUFF;
}

/*--------------------------------------------------------------------*/
/*
/* flow tool for interp_db
/*
/*
/*
/*--------------------------------------------------------------------*/
flow_interp_db_( float *traces, int *ithdrs, float *rthdrs,
int *nStored, int *ifound_eoj, int *nOutput, int *nOverlap )
{
GlobalRuntime *gr = globalRuntime;
float **rhdrs;

/*
/*
/*
/*
/*

if( *nStored == 1 ){
.. There is only one trace so we can't compare it to anything. This */
.. situtation should only occur on the first call to the routine unless */
.. the last trace input is a single-trace ensemble in which case more */
.. code would be needed to handle that special case. We leave out that */
.. extra code here as it would clutter the example. */
*nOutput = 0;
return;
}

/* put the trace headers into a 2d array that is easy to handle */


rhdrs = fVecTo2d( rthdrs, *nStored, gr->nth );
/* see if the primary key header value of most recent input trace has changed */

Other Docs

Known Problems

interp_db.c430

Developers Programming Guide

if( rhdrs[*nStored-2][parms->pKeyHdrIndx] != rhdrs[*nStored-1][parms>pKeyHdrIndx] ||


*ifound_eoj != 0 ){
/* .. we have found enough traces to process */
/* .. Set the number of traces to output from exec, a non-zero value tells */
/* .. the trace executive that it is time to pass the traces to */
/* .. exec_interp_sb_ */
*nOutput = 2*(*nStored-1) - 1;
/* .. set the number of traces that are being passed to the exec_ subroutine */
parms->nInEnsemble = *nStored - 1;
/* .. Let the last trace input on this call be the first trace input */
/* .. on the next call since it is part of the next ensemble that we */
/* .. will be collecting. */
*nOverlap = 1;
free( rhdrs );
}
else{
/* .. signal the trace executive that we aren't ready to pass traces exec_ */
*nOutput = 0;
}
}
/*-------------------------------------------------------------------*/
/*
/*
description:
/*
exectution routine for interp_db
/*
/*
input arguments:
/*
nStored - the amount of memory available (in traces) in the
/*
traces array. NOTE that the actual number of traces
/*
input was determined in the flow_interp_db routine and
/*
passed to exec_interp_db via the parms->nInEnsemble
/*
variable.
/*
/*
input/output arguments:
/*
traces_in - 2-d array of input traces
/*
ithdrs_in - 2-d array of input integer trace headers
/*
rthdrs_in - 2-d array of input float trace headers
/*
/*-------------------------------------------------------------------*/
void
exec_interp_db_( float
float
float
float

*traces_in, int *ithdrs_in,


*rthdrs_in, int *nTrBuffIn,
*traces_out, int *ithdrs_out,
*rthdrs_out, int *nTrBuffOut )

{
float **rhdrs_in, **tracs_in;
float **rhdrs_out, **tracs_out;
int i,j;

Other Docs

Known Problems

interp_db.c431

Developers Programming Guide

/* set the global pointers */


GlobalRuntime *gr = globalRuntime;
/* if cleaning up release memory, close files, in this case there is nothing to
do */
if( gr->cleanup){
return;
}
/* Arrange the trace and header arrays into 2d arrays that are easy to handle. */
tracs_in = fVecTo2d( traces_in, *nTrBuffIn, gr->numsmp );
rhdrs_in = fVecTo2d( rthdrs_in, *nTrBuffIn, gr->nth );
tracs_out = fVecTo2d( traces_out, *nTrBuffOut,
rhdrs_out = fVecTo2d( rthdrs_out, *nTrBuffOut,

gr->numsmp );
gr->nth );

/* Interpolate the sample values */


for( i = 0; i < gr->numsmp; i++ ){
for( j = parms->nInEnsemble-1; j > 0; j-- ){
tracs_out[2*j][i]
= tracs_in[j][i];
tracs_out[2*j-1][i] = (tracs_in[j][i] + tracs_in[j-1][i])/2.;
}
}
/* Take care of the headers too, interpolated traces will have a copy */
/* of the header just before them */
for( i = 0; i < gr->nth; i++ ){
for( j = parms->nInEnsemble-1; j > 0; j-- ){
rhdrs_out[2*j][i]
= rhdrs_in[j][i];
rhdrs_out[2*j-1][i] = rhdrs_in[j-1][i];
}
}
free(tracs_in);
free(rhdrs_in);
free(tracs_out);
free(rhdrs_out);

Other Docs

Known Problems

interp_db.c432

Other Docs

Developers Programming Guide

Known Problems

433

Developers Programming Guide

Appendix: Complex Tool Examples

This appendix provides an example of a complex tool. In this


example, the tool changes the trace length of the output traces
and the number of traces output per ensemble. The program
does not actually do anything useful except to demonstrate how
to use a complex tool.
The program gathers data traces until it has an entire ensemble
of M data traces, each of which is N data samples in length. The
program outputs N data traces, each of which is M samples
long, outputting the transpose of the 2-dimensional input
ensemble matrix.
The menu file is presented first, followed by the FORTRAN
version and then the C version. The menu file serves both the C
and FORTRAN versions.

Topics covered in this appendix:

Other Docs

transform.menu
transform.inc
transform.f
transform.c

Known Problems

transform.menu434

Developers Programming Guide

transform.menu
'(
name: TRANSFORM
label: "Transform"
value_tab: 35
exec_data: ("TRANSFORM"
("GENERAL"
("dummy" implicit: nil)
)
)
)

Other Docs

Known Problems

transform.inc435

Developers Programming Guide

transform.inc
C-----------------------------------------------------------------------------C
Include file for TRANSFORM
C-----------------------------------------------------------------------------IMPLICIT NONE
#include "global.inc"

&

&

COMMON /SAVED_PARMS/ SAVE1z, MAXDTRZ_OLD, NUMSMPZ_OLD, NSTORED,


NDUMPED, DUMPING, IX_TRACES, IX_THDRS
INTEGER LENSAVED, MAXDTRZ_OLD, NUMSMPZ_OLD, NSTORED,
NDUMPED, IX_TRACES, IX_THDRS
LOGICAL DUMPING

C
C
C
C

.....
.....
.....
.....

Specify the number of variables to save. This is set here (rather


than in the initialization routine) so that programmers don't forget
to change it when they are changing the contents of the common
block SAVED_PARMS.
DATA LENSAVED /8/

C
C
C
C
C
C
C

.....
.....
.....
.....
.....
.....
.....

MAXDTRZ_OLD - previous value of MAXDTRz


NUMSMPZ_OLD - previous value of NUMSMPz
NSTORED - current number of traces stored
NDUMPED - current number of traces dumped
DUMPING - logical flag for dumping mode
IX_TRACES - index of buffer of traces
IX_THDRS - index of buffer of trace headers

Other Docs

Known Problems

transform.f436

Developers Programming Guide

transform.f
SUBROUTINE INIT_TRANSFORM( LEN_SAV, ITOOLTYPE )
#include "transform.inc"
#include "header.inc"
INTEGER LEN_SAV, ITOOLTYPE, IOK_HDR
C ..... The trace number is no longer valid, and the geometry no longer matches
ITRNO_VALIDz = 0
IGEOM_MATCHz = 0
C ..... Reset the data type to transformed unstacked data
IDTYPz = IUS_TRANSpz
C ..... Reset the domain. We will have to make up something new, since
C ..... nothing appropriate exists
IDOMAINz = 100
C ..... Save the previous values of the trace length and maximum number
C ..... of traces per ensemble (we will need them in exec phase)
MAXDTRZ_OLD = MAXDTRz
NUMSMPZ_OLD = NUMSMPz
C ..... Reset the trace length and maximum number of traces per ensemble
MAXDTRz = NUMSMPZ_OLD
NUMSMPz = MAXDTRZ_OLD
C ..... Check the needed header entries
IF ( IOK_HDR(IEND_ENSz) .NE. 1 ) CALL EX_ERR_FATAL(
&
'ENS_ENS not found in header' )
IF ( IOK_HDR(ITRACENOz) .NE. 1 ) CALL EX_ERR_FATAL(
&
'TRACENO not found in header' )
IF ( IOK_HDR(ISEQNOz) .NE. 1 ) CALL EX_ERR_FATAL(
&
'SEQNO not found in header' )
C ..... Initialize for execution phase
NSTORED = 0
NDUMPED = 0
DUMPING = .FALSE.
C ..... Set the number of words that need to be saved and the tool type
LEN_SAV = LENSAVED
ITOOLTYPE = ICOMPLEXpz
RETURN
END

SUBROUTINE EXEC_TRANSFORM( TRACE, ITHDR, RTHDR )


#include "transform.inc"
#include "mem.inc"
#include "header.inc"
INTEGER ITHDR(NTHz), IND, IERR, IX_WORK
REAL TRACE(NUMSMPZ_OLD), RTHDR(NTHz)

Other Docs

Known Problems

transform.f437

Developers Programming Guide

C ..... No action needed for cleanup phase


IF ( CLEANUPz ) RETURN
IF ( .NOT. DUMPING ) THEN
C ......... Filling the buffer before the transform
C ......... Increment the number of traces stored
NSTORED = NSTORED + 1
IF ( NSTORED .EQ. 1 ) THEN
C ............. Get a buffer to fill
CALL MEM_RESBUFF( MAXDTRZ_OLD*NUMSMPZ_OLD, IX_TRACES,
&
IERR )
CALL MEM_RESBUFF( MAXDTRZ_OLD*NTHz, IX_THDRS, IERR )
ENDIF
C ......... Store the current trace and header
IND = IX_TRACES + (NSTORED-1)*NUMSMPZ_OLD
CALL VMOV( TRACE, 1, RSPACEz(IND), 1, NUMSMPZ_OLD )
IND = IX_THDRS + (NSTORED-1)*NTHz
CALL VMOV( ITHDR, 1, ISPACEz(IND), 1, NTHz )
C ......... If this is the end of the ensemble, time to process
IF ( ITHDR( IEND_ENSz ) .EQ. LASTTRpz ) THEN
C ............. Call the actual work routine
CALL MEM_RESBUFF(MAXDTRZ_OLD*NUMSMPZ_OLD, IX_WORK, IERR)
CALL TRANSFORM_WORK( RSPACEz(IX_TRACES),
&
RSPACEz(IX_WORK), NUMSMPZ_OLD, MAXDTRZ_OLD )
CALL MEM_FREEBUFF( MAXDTRZ_OLD*NUMSMPZ_OLD, IX_TRACES,
&
IERR )
IX_TRACES = IX_WORK
C ............. Time to start flushing the buffer
DUMPING = .TRUE.
ELSE
C ............. Otherwise, we are still in fill mode
CALL EX_FILLMODE
RETURN
ENDIF
ENDIF
C ..... If control reaches here, we are dumping the buffer
C ..... Increment the number of traces dumped
NDUMPED = NDUMPED + 1
C ..... Copy a header from storage (same one every time!!).
C ..... nasty problem
CALL VMOV( ISPACEz(IX_THDRS), 1, ITHDR, 1, NTHz )

This is a

C ..... Nullify the trace number


ITHDR(ITRACENOz) = INULLpz
C ..... Set the sequence-number-in-ensemble
ITHDR(ISEQNOz) = NDUMPED

Other Docs

Known Problems

transform.f438

Developers Programming Guide

C ..... Copy a "trace" from storage


IND = IX_TRACES + (NDUMPED-1)*NUMSMPz
CALL VMOV( RSPACEz(IND), 1, TRACE, 1, NUMSMPz )
IF ( NDUMPED .EQ. NUMSMPZ_OLD ) THEN
C ......... We are finished dumping
C ......... Reset related variables
DUMPING = .FALSE.
NDUMPED = 0
NSTORED = 0
C ......... Scratch the memory so that another process can use it
CALL MEM_FREEBUFF( MAXDTRZ_OLD*NUMSMPZ_OLD, IX_TRACES, IERR)
CALL MEM_FREEBUFF( MAXDTRZ_OLD*NTHz, IX_THDRS, IERR )
C ......... This is the last trace in the ensemble
ITHDR(IEND_ENSz) = LASTTRpz
C ......... We are in pipe mode momentarily
CALL EX_PIPEMODE
ELSE
C ......... We still have more traces to dump
ITHDR(IEND_ENSz) = NLASTpz
C ......... We are still in flush mode
CALL EX_FLUSHMODE
ENDIF
RETURN
END

100
110

&

SUBROUTINE TRANSFORM_WORK( TRACES_OLD, TRACES_NEW, NUMSMPZ_OLD,


MAXDTRZ_OLD )

&

IMPLICIT NONE
INTEGER NUMSMPZ_OLD, MAXDTRZ_OLD, I, J
REAL TRACES_OLD(NUMSMPZ_OLD,MAXDTRZ_OLD),
TRACES_NEW(MAXDTRZ_OLD,NUMSMPZ_OLD)
DO 110 J=1,MAXDTRZ_OLD
DO 100 I=1,NUMSMPZ_OLD
TRACES_NEW(J,I) = TRACES_OLD(I,J)
CONTINUE
CONTINUE
RETURN
END

Other Docs

Known Problems

transform.c439

Developers Programming Guide

transform.c
/* include ProMAX prototypes and globals */
#include "cpromax.h"
#include "cglobal.h"
#include "alloc.h"
#include "memalloc.h"
#include "agfc.h"
/* define saved parameters */
BEGINPARMS
/* saved parms related to sample interval and trace length */
int
maxdtr_old;
int
numsmp_old;
/* saved parms related to control of trace I/O */
int nstored;
int ndumped;
int dumping;
/* saved
float
float
float

parms related to trace and header storage */


**storedTrcs;
**storedHdrs;
**transTrcs;

ENDPARMS(parms)
void init_transform_(int *len_sav, int *itooltype);
void exec_transform_(float *trace, int *ithdr, float *rthdr);
float **transform_work( float**, int, int, int );
/*------------------------------------------------------------------Description:
Initialization routine for transform
output arguments:
len_save - number of 4-byte words to save for re-entrancy
itooltype - processing tool type
---------------------------------------------------------------------*/
void init_transform_(int *len_sav, int *itooltype)
{
/* local variabes */
GlobalRuntime *gr = globalRuntime;
/* The trace number is no longer valid, and the geometry no longer matches */
gr->itrno_valid = 0;
gr->igeom_match = 0;
/* Reset the data type to transformed unstacked data */
gr->idtyp = IUS_TRANS;

Other Docs

Known Problems

transform.c440

Developers Programming Guide

/* Reset the domain. We will have to make up something new, since */


/* nothing appropriate exists */
gr->idomain = 100;
/* Save the previous values of the trace length and maximum number */
/* of traces per ensemble (we will need them in exec phase) */
parms->maxdtr_old = gr->maxdtr;
parms->numsmp_old = gr->numsmp;
/* Reset the trace length and maximum number of traces per ensemble */
gr->maxdtr = parms->numsmp_old;
gr->numsmp = parms->maxdtr_old;
/* Make sure the needed header entries exist */
if( hdrExists( "END_ENS" ) != 1 ){
exErrFatal("END_ENS header not found in trace headers.");
}
if( hdrExists( "TRACENO" ) != 1 ){
exErrFatal("TRACENO header not found in trace headers.");
}
if( hdrExists( "SEQNO" ) != 1 ){
exErrFatal("SEQNO header not found in trace headers.");
}
/* Initialize for execution phase, TRUE and FALSE */
/* are #define'd in cpromax.h, TRUE = 1, FALSE = 0 */
parms->nstored = 0;
parms->ndumped = 0;
parms->dumping = FALSE;
/* Set the number of words that need to be saved for re-entrancy.
*len_sav = NPARMS (parms);

*/

/* set the tool type */


*itooltype = ICOMPLEX;
}

/*********************************************************************
*
*
Description:
*
Execution routine for transform
*
*
Input/output arguments:
*
trace - array of trace samples
*
ithdr - trace header (as integer)
*
rthdr - trace header (as floating [point)
*
**********************************************************************/

void exec_transform_(float *trace, int *ithdr, float *rthdr)


{
GlobalRuntime *gr = globalRuntime;
int indx;

Other Docs

Known Problems

transform.c441

Developers Programming Guide

/* No action needed for cleanup phase */


if( gr->cleanup ) return;
if( parms->dumping == FALSE ){
/* .. Filling the buffer before the transform */
/* .. Increment the number of traces stored */
parms->nstored++;
if ( parms->nstored == 1 ){
/* ..... Get buffers to store input traces and trace headers. */
/* ..... Note that error checking for null returned pointers is */
/* ..... done within ealloc2. */
parms->storedTrcs = _memAlloc2Float( parms->numsmp_old,
parms->maxdtr_old, "transform.c", 129 );
parms->storedHdrs = _memAlloc2Float( gr->nth, parms->maxdtr_old,
"transform.c", 132 );
}
/* .. Store the current trace and header */
indx = parms->nstored - 1;
vMov( trace, 1, parms->storedTrcs[indx], 1, parms->numsmp_old );
vMov( ithdr, 1, parms->storedHdrs[indx], 1, gr->nth );
/*... If this is the end of the ensemble it is time to process. */
if ( ithdr[ hdrIndex("END_ENS") ] == LASTTR ){
/* ...... Call the actual work routine that transforms traces */
parms->transTrcs = transform_work( parms->storedTrcs, parms->nstored,
gr->numsmp, parms->numsmp_old );
/* ...... free the memory that stored the original input traces */
_memFree2Float( parms->storedTrcs, "transform.c", 150 );
/* ...... Time to start flushing the buffer */
parms->dumping = TRUE;
}
else{
/* ...... We are still loading traces until we get an entire ensemble. */
/* ...... Set the mode to not output a trace on this call and get */
/* ...... another trace on the next call to exec_transform. */
exFillMode();
return;
}
}
/* If control reaches here, we are dumping the buffer */
/* Increment the number of traces dumped */
parms->ndumped++;
/* Copy a header from storage (same one every time for this exercise) */
vMov( parms->storedHdrs[0], 1, rthdr, 1, gr->nth );
/* Nullify the trace number */
ithdr[hdrIndex("TRACENO")] = INULL;

Other Docs

Known Problems

transform.c442

Developers Programming Guide

/* Set the sequence-number-in-ensemble */


ithdr[hdrIndex("SEQNO")] = parms->ndumped;
/* Copy a "trace" from storage */
indx = parms->ndumped - 1;
vMov( parms->transTrcs[indx], 1, trace, 1, gr->numsmp );
if( parms->ndumped == parms->numsmp_old){
/* .. We are finished dumping */
/* .. Reset related variables */
parms->dumping = FALSE;
parms->ndumped = 0;
parms->nstored = 0;
/* .. Free the memory so that another process can use it */
_memFree2Float( parms->transTrcs, "transform", 189 );
_memFree2Float( parms->storedHdrs, "transform,c", 190 );

/* .. This is the last trace in the ensemble */


ithdr[hdrIndex("END_ENS")] = LASTTR;
/* .. We are in pipe mode momentarily, output the current trace and */
/* .. tell the trace executive to give exec_tranform a new trace on the */
/* .. next call */
exPipeMode();
}
else{
/* .. We still have more traces to dump */
ithdr[hdrIndex("END_ENS")] = NLAST;
/* .. We are still in flush mode, give the current trace to the trace */
/* .. executive and exec_transform doesn't want a new trace on the next */
/* .. since it still has traces to output. */
exFlushMode();
}
}

float **transform_work( float **storedTrcs, int nstored,


int outTrcLen, int numOutTrcs )
/****************************************************************
/*
/* input:
/*
storedTrcs - the input traces
/*
nstored - number of stored traces == number out samples
/*
outTrcLen - the length in samples of the output trace
/*
nstored <= outTrcLen
/*
numOutTrcs - number of output traces
/*
/****************************************************************/
{

Other Docs

Known Problems

transform.c443

Developers Programming Guide

int i, j;
float **t;
/* allocate space for the transformed traces */
t = _memAlloc2Float( outTrcLen, numOutTrcs, "transform.c", 218 );

for( i = 0; i < nstored; i++ ){


for( j = 0; j < numOutTrcs; j++ ){
t[j][i] = storedTrcs[i][j];
}
}
return(t);

Other Docs

Known Problems

transform.c444

Other Docs

Developers Programming Guide

Known Problems

445

Developers Programming Guide

Appendix: Input Tool Examples

This appendix provides a template for new input tools. Most


input tools will look very much like this tool, except for the
code that actually gets data from tape, disk, or generates the
data internally.
The INIT_ subroutine in this example shows how the trace
headers are created and initialized. It also shows the global
parameters that must be set by the programmer, as well as those
global parameters that must not be set by the programmer. The
EXEC subroutine shows that input tools feed one trace at a time
into the processing flow. The EXEC routine also shows how the
tool tells the trace executive if it has a trace to input to the flow;
namely, through use of calls to EX_FLUSHMODE and
EX_QUITMODE in FORTRAN and exFlushMode and
exQuitMode in C.
The menu file is presented first, followed by the FORTRAN and
C examples.

Topics covered in this appendix:

Other Docs

sine_wave.menu
sine_wave.inc
sine_wave.f
sineWave.c

Known Problems

sine_wave.menu446

Developers Programming Guide

sine_wave.menu
'(
name: SINE_WAVE
label: "Sine Wave Generation"
value_tab: 45
parameter: PKEYNAM
text: "Primay key name"
type: circular:
type_desc: (
("Source" "SOURCE" "Generate synthetic shot gathers." )
("CDP
" "CDP"
"Generate synthetic CDP gathers."))
value: "SOURCE"
mouse_text: "Use B1 to toggle between SHOT or CDP gathers."
parameter: NENS
text: "Number of trace ensembles to generate"
type: typein:
type_desc: ( int: 5 1 nil )
value: 1
mouse_text: "How many ensembles do you wish to generate?"
parameter: NTRACES
text: "Number of traces per ensemble"
type: typein:
type_desc: ( int: 5 1 nil )
value: 60
mouse_text: "How many traces per ensemble do you wish to generate?"
parameter: SAMPRATE
text: "Sample interval for the synthetic traces"
type: typein:
type_desc: ( real: 7 1.0e-5 nil )
value: 2.0
mouse_text: "What is the desired sample interval (in milliseconds) for the
synthetic traces?"
parameter: TRACELEN
text: "Trace length for the synthetic traces"
type: typein:
type_desc: ( real: 7 1.0e-5 nil )
value: 2000.0
mouse_text: "What is the desired trace length (in milliseconds) for the synthetic
traces?"
parameter: FREQS
text: "List of frequencies"
type: edit:
type_desc: (31 80 5 " FORMAT: freq1 , freq2 , freq3 , ...
EXAMPLE: 60.0,125.0
HELP: EMACS Editor Widget (scroll with down/up arrow keys)
CURSOR MOVEMENT: Use the arrow keys:->,<-,etc.;Point the mouse cursor,click B1
CM: Ctrl-A Move the cursor to the BEGINNING of the current line
CM: Ctrl-E Move the cursor to the END of the current line
EDITING: All keyboard entry is in 'insert' mode
E: Backspace, Delete keysDelete one character to the LEFT of the cursor

Other Docs

Known Problems

sine_wave.menu447

Developers Programming Guide

E:
E:
E:

Ctrl-D Delete one character to the RIGHT of the cursor


Ctrl-K KILL to the end of the line (from the cursor)
Ctrl-Y YANK back the contents of the kill buffer; 'Cut and
paste'; (Can move the cursor first) " 3 )
value: "60.0,125.0"
mouse_text: "Use B1 to open up and edit field and enter the list of frequencies."
exec_data: ("SINE_WAVE"
("SPECIAL"
("TOOLTYPE"
implicit: "INPUT")
)
("GENERAL"
("PKEYNAM"
implicit: (value 'PKEYNAM))
("NENS"
implicit: (value 'NENS))
("NTRACES"
implicit: (value 'NTRACES))
("SAMPRATE" implicit: (value 'SAMPRATE))
("TRACELEN" implicit: (value 'TRACELEN))
("FREQS"
implicit: (value 'FREQS))
)
)
)

Other Docs

Known Problems

sine_wave.inc448

Developers Programming Guide

sine_wave.inc
C-----------------------------------------------------------------------------C
Include file for SINE_WAVE
C-----------------------------------------------------------------------------IMPLICIT NONE
#include "global.inc"

&

COMMON /SAVED_PARMS/ SAVE1z, NENS, NFREQS, IX_FREQS, IENS,


ITRACE_IN_ENS, FIRST_VISIT
INTEGER LENSAVED, NENS, NFREQS, IX_FREQS, IENS, ITRACE_IN_ENS
LOGICAL FIRST_VISIT

C
C
C
C

.....
.....
.....
.....

Specify the number of variables to save. This is set here (rather


than in the initialization routine) so that programmers don't forget
to change it when they are changing the contents of the common
block SAVED_PARMS.
DATA LENSAVED /7/

C
C
C
C
C
C

.....
.....
.....
.....
.....
.....

NTR_PER_ENS - input number of ensembles


NFREQS - number of frequencies to generate sine waves for
IX_FREQS - index of buffer of frequencies
IENS - current ensemble number
ITRACE_IN_ENS - current trace in ensemble
FIRST_VISIT - logical flag for first visit to exec phase

Other Docs

Known Problems

sine_wave.f449

Developers Programming Guide

sine_wave.f
C ..... This tool is a template for an input tool
cdd - short-hand header manipulation
cdd - no missing code
SUBROUTINE INIT_SINE_WAVE( LEN_SAV, ITOOLTYPE )
#include "sine_wave.inc"
#include "mem.inc"
#include "header.inc"
CHARACTER*8 CNAMES(4)
CHARACTER CPKEYNAM*8
INTEGER NCHARS, NTR_PER_ENS, NS, IERR, LEN_SAV,
&
ITOOLTYPE, IOK_HDR
REAL SAMPRATE, TRACELEN
C ..... Get the primary key name
CALL EX_CGETPARM( 'PKEYNAM ', 1, CPKEYNAM, NCHARS )
IF ( CPKEYNAM(1:6) .NE. 'SOURCE'
&
.AND. CPKEYNAM(1:3) .NE. 'CDP' ) CALL EX_ERR_FATAL(
&
'Only SOURCE or CDP can be primary keys' )
C ..... Get and decode the list for frequencies
CALL EX_CGETPARM( 'FREQS
', 1, CTEMPz, NCHARS )
IF ( NCHARS .LT. 1 ) CALL EX_ERR_FATAL(
&
'No frequencies were input' )
CALL FIX_SLASHES( CTEMPz, NCHARS, NS )
CALL FLOAT_DECODE( CTEMPz, NS, RTEMPz, NFREQS, .FALSE. )
IF ( NFREQS .LT. 1 ) CALL EX_ERR_FATAL(
&
'No frequencies were input' )
C ..... Get a buffer and save the frequencies
CALL MEM_RESBUFF( NFREQS, IX_FREQS, IERR )
CALL VMOV( RTEMPz, 1, RSPACEz(IX_FREQS), 1, NFREQS )
C ..... Get the number of traces per ensemble, the sample rate, the length of
C ..... the traces, and the number of ensembles
NTR_PER_ENS = 0
SAMPRATE = 0.0
TRACELEN = 0.0
NENS = 0
CALL EX_GETPARM( 'NTRACES ', 1, NTR_PER_ENS )
CALL EX_GETPARM( 'SAMPRATE', 1, SAMPRATE )
CALL EX_GETPARM( 'TRACELEN', 1, TRACELEN )
CALL EX_GETPARM( 'NENS
', 1, NENS )
C ..... Check and set the number of traces per ensemble
IF ( NTR_PER_ENS .LE. 0 ) THEN
CALL EX_ERR_FATAL(
&
'Number of traces per ensemble < 1' )
ELSE
MAXDTRz = NTR_PER_ENS
ENDIF

Other Docs

Known Problems

sine_wave.f450

Developers Programming Guide

C ..... Assign the sample interval


IF ( SAMPRATE .EQ. 0.0 ) THEN
CALL EX_ERR_FATAL( 'Sample interval must be > 0.0' )
ELSE
SAMPRATz = SAMPRATE
ENDIF
C ..... Check and set the trace length
IF ( TRACELEN .LE. 0.0 ) THEN
CALL EX_ERR_FATAL(
&
'Input trace length is not greater than zero' )
ELSE
NUMSMPz = NINT( TRACELEN / SAMPRATz ) + 1
ENDIF
C ..... Check the number of ensembles
IF ( NENS .LT. 1 ) CALL EX_ERR_FATAL(
&
'Number of ensembles < 1' )
C ..... Define the minimum standard header entries
CALL HDR_STD_MINIMUM
C ..... Set the primary sort flag depending on the primary key name
IF ( CPKEYNAM(1:3) .EQ. 'CDP' ) THEN
C ......... Add CDP, OFFSET, and AOFFSET to the header
CNAMES(1) = 'OFFSET '
CNAMES(2) = 'CDP
'
CNAMES(3) = 'AOFFSET '
CALL HDR_STD_ADD( CNAMES, 3 )
C ......... Set the primary sort FLAG to CDP
IPSORTz = ICDPpz
C ......... Set the primary sort INDEX to CDP
IPKEYz = ICDPz
C ......... Set the secondary sort index to OFFSET
ISKEYz = IOFFSETz
ELSEIF ( CPKEYNAM(1:6) .EQ. 'SOURCE' ) THEN
C ......... Add SIN, SOURCE, CHAN, and FFID to the header
CNAMES(1) = 'SIN
'
CNAMES(2) = 'SOURCE '
CNAMES(3) = 'CHAN
'
CNAMES(4) = 'FFID
'
CALL HDR_STD_ADD( CNAMES, 4 )
C ......... Set the primary sort FLAG to source
IPSORTz = ISINpz
C ......... Set the primary sort index to source
IPKEYz = ISOURCEz
C ......... Set the secondary sort index to channel
ISKEYz = ICHANz

Other Docs

Known Problems

sine_wave.f451

Developers Programming Guide

ENDIF
C ..... Set the domain to normal space-time
IDOMAINz = ITXpz
C ..... Check to be sure that SEQNO, TRACENO, and END_ENS exist
IF ( IOK_HDR(ISEQNOz) .NE. 1 ) CALL EX_ERR_FATAL(
&
'SEQNO not found in header' )
IF ( IOK_HDR(ITRACENOz) .NE. 1 ) CALL EX_ERR_FATAL(
&
'TRACENO not found in header' )
IF ( IOK_HDR(IEND_ENSz) .NE. 1 ) CALL EX_ERR_FATAL(
&
'END_ENS not found in header' )
C ..... It is impossible for the geometry to match or the trace number to be
C ..... valid (must be set by the program INIT_DATABASE)
IGEOM_MATCHz = 0
ITRNO_VALIDz = 0
C
C
C
C
C
C
C
C
C
C
C
C

.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....

HERE ARE RUNTIME GLOBAL VARIABLES THAT YOU DON'T SET:


NTHz
- the current number of 4-byte words in the trace header.
(incremented by HDR_ADD)
MODEz
- the run mode ( INTERpz, IBACKGpz, IBATCHpz )
IOUNITz - the I/O unit for output diagnostics
IDATEz
- the current date (seconds since 00:00:00 GMT, Jan. 1, 1970)
NPRIORFz - Number of prior processing flows
CLEANUPz - Flag indicating that the system is in cleanup mode (logical)
IERRORz - Flag indicating that the system is running under an error
condition (trying to cleanup) (logical)
INIT_ONLYz - Flag indicating that only initialization phase is
being executed (logical)

C ..... Initialize for exec phase


IENS = 1
ITRACE_IN_ENS = 1
FIRST_VISIT = .TRUE.
C ..... This is an input tool
ITOOLTYPE = INPUTpz
C ..... Set the saved buffer length
LEN_SAV = LENSAVED
RETURN
END

SUBROUTINE EXEC_SINE_WAVE( TRACE, ITHDR, RTHDR )


#include "sine_wave.inc"
#include "mem.inc"
REAL TRACE(NUMSMPz), RTHDR(NTHz)
INTEGER ITHDR(NTHz)
LOGICAL NO_DATA_FOUND
C ..... No action needed for cleanup phase
IF ( CLEANUPz ) RETURN

Other Docs

Known Problems

sine_wave.f452

Developers Programming Guide

C ..... Fill the trace


CALL SINE_WAVE_NEXT_TR( TRACE, ITHDR, RTHDR,
&
RSPACEz(IX_FREQS), NO_DATA_FOUND )
IF ( FIRST_VISIT ) THEN
C ......... We only want to do this once
FIRST_VISIT = .FALSE.
IF ( NO_DATA_FOUND ) THEN
CALL EX_ERR_FATAL( 'Unable to create any traces' )
ENDIF
ENDIF
IF ( NO_DATA_FOUND ) THEN
C ......... We have no data to output
CALL EX_QUITMODE
ELSE
C ......... We have a trace for next time
CALL EX_FLUSHMODE
ENDIF
RETURN
END

&

SUBROUTINE SINE_WAVE_NEXT_TR( TRACE, ITHDR, RTHDR, FREQS,


NO_DATA_FOUND )

#include "sine_wave.inc"
#include "header.inc"
INTEGER ITHDR(NTHz), I
REAL TRACE(NUMSMPz), FREQS(NFREQS), RTHDR(NTHz)
LOGICAL NO_DATA_FOUND
IF ( IENS .GT. NENS
C ......... We have no more
C ......... to read a trace
NO_DATA_FOUND =
RETURN
ELSE
NO_DATA_FOUND =
ENDIF

) THEN
data to output. This is equivalent to failing
from disk or tape
.TRUE.

.FALSE.

C ..... If control reaches here, we need to build a new trace


C ..... Initialize the trace with zeros
CALL VCLR( TRACE, 1, NUMSMPz )
C ..... Add the sine wave data to the traces
DO 100 I=1,NFREQS
CALL SINE_WAVE_ADD( FREQS, SAMPRATz, NUMSMPz, TRACE )
100
CONTINUE
C ..... Inititalize the values of the minimum standard header entries
CALL HDR_STD_INIT_VALS( ITHDR, RTHDR )
C ..... Take care of other header entries
IF ( IPSORTz .EQ. ISINpz ) THEN

Other Docs

Known Problems

sine_wave.f453

Developers Programming Guide

C ......... Inputting shots


C ......... The source index number should be null until geometry is assigned
ITHDR( ISINz ) = INULLpz
C ......... Set the live source number
ITHDR( ISOURCEz ) = IENS
C ......... Set the channel number
ITHDR( ICHANz ) = ITRACE_IN_ENS
C ......... Set the field file ID
ITHDR( IFFIDz ) = IENS
ELSEIF ( IPSORTz .EQ. ICDPpz ) THEN
C ......... Inputting CDPs
C ......... Set the CDP bin number
ITHDR( ICDPz ) = IENS
C ......... Set OFFSET and AOFFSET (doesn't make much sense)
RTHDR( IOFFSETz ) = FLOAT(ITRACE_IN_ENS)
RTHDR( IAOFFSETz ) = ABS( RTHDR(IOFFSETz) )
ENDIF
C ..... Set the sequence-number-in-ensemble
ITHDR( ISEQNOz ) = ITRACE_IN_ENS
C ..... Set the sequential trace number (null until geometry assignment)
ITHDR( ITRACENOz ) = INULLpz
IF ( ITRACE_IN_ENS .EQ. MAXDTRz ) THEN
C ......... This is the last trace in the ensemble
C ......... Since this is the last trace, set the last-trace-in-ensemble flag
ITHDR( IEND_ENSz ) = LASTTRpz
C ......... Reset the trace-in-ensemble counter to zero
ITRACE_IN_ENS = 0
C ......... Increment the ensemble number for next time
IENS = IENS + 1
ELSE
C ......... This is not the last trace in the ensemble, so set the flag as such
ITHDR( IEND_ENSz ) = NLASTpz
ENDIF
C ..... Increment the trace-in-ensemble number counter for next time
ITRACE_IN_ENS = ITRACE_IN_ENS + 1
RETURN
END

Other Docs

Known Problems

sine_wave.f454

Developers Programming Guide

SUBROUTINE SINE_WAVE_ADD( FREQ, SAMPRAT, NUMSMP, TRACE )


IMPLICIT NONE
INTEGER NUMSMP, I
REAL TRACE(NUMSMP), FREQ, SAMPRAT, TIME, ANGLE, TWO_PI
TWO_PI = ASIN(1.0) * 4.0

100

DO 100 I=1,NUMSMP
TIME = FLOAT(I-1) * SAMPRAT / 1000.0
ANGLE = FREQ * TIME * TWO_PI
TRACE(I) = TRACE(I) + SIN( ANGLE )
CONTINUE
RETURN
END

Other Docs

Known Problems

sineWave.c455

Developers Programming Guide

sineWave.c
/* this tool is a template for an input tool */
/* include ProMAX prototypes and globals */
#include "cpromax.h"
#include "cglobal.h"
/* define the saved parameters (user input, etc) */
BEGINPARMS
int
nens;
int
nfreqs;
float *freqs;
int
currEns;
int
currTrcInEns;
logical firstVisit;

/*
/*
/*
/*
/*
/*

number of trace ensembles to generate */


number of frequencies in output traces */
list of frequencies in output traces */
the current ensemble number */
current trace number in ensemble */
flag for first visit to exec */

ENDPARMS (parms)
/* functions defined and used internally */
static void sineWaveAdd( float, float, int, float* );
static int sineWaveNextTr( float*, int*, float*, float* );
/*-------------------------------------------------------------------*/
/* init_sine_wave
/*
/* initialization routine for ProMAX module sine_wave
/*
/*-------------------------------------------------------------------*/
void init_sine_wave_( int *len_sav, int *itooltype )
{

/* declare local variables */


char *pkeyName;
char *freqList;
int nChars;
int ntrPerEns;
int ns;
int iErr;
int okHdrOnly;
logical gatesFlag;
float sampRate;
float traceLen;
/* declare local versions of external parameters */
int nens;
int nfreqs;
float *freqs;
char *newList;
int lenFreqList;
int currEns;
int currTrcInEns;
logical firstVisit;

Other Docs

Known Problems

sineWave.c456

Developers Programming Guide

/* set a pointer to the global structures */


GlobalRuntime *gr = globalRuntime;
/* get the primary key name */
exParGetString( "PKEYNAM", &pkeyName );
if( strcmp( pkeyName, "SOURCE" ) != 0 && strcmp( pkeyName, "CDP" ) != 0
exErrFatal("Only SOURCE and CDP can be primary keys.");
}

){

/* get and decode the list of frequencies */


exParGetString("FREQS", &freqList );
if( strlen( freqList ) < 1 ){
exErrFatal("No frequencies were input!");
}
/* put freqList into a bigger array since decodePrep can */
/* require more space than is required by the input array */
lenFreqList = strlen( freqList );
newList = (char*)realloc( (void*)freqList, (2*(size_t)lenFreqList) );
nChars = decodePrep( newList, lenFreqList );
/* allocate enough space for the frequency list at max length */
freqs = (float*)malloc( nChars * sizeof(float));
gatesFlag = FALSE;
nfreqs = floatDecode( newList, nChars, freqs, gatesFlag );
/* free the newList space */
free( newList );
/* get the number of traces per ensemble, the sample rate the */
/* length of the traces, and the number of ensembles */
ntrPerEns = 0;
nens
= 0;
traceLen = 0.0;
sampRate

= 0.0;

exParGetInt( "NTRACES", &ntrPerEns );


exParGetInt( "NENS", &nens );
exParGetFloat( "TRACELEN", &traceLen );
exParGetFloat( "SAMPRATE", &sampRate );
/* check and set the number of traces per ensemble */
if( ntrPerEns <= 0 ){
exErrFatal("Number of traces per ensemble is < 1.");
}
else{
gr->maxdtr = ntrPerEns;
}
/* assign the sample interval */
if( sampRate <= 0.0 ){
exErrFatal("The sample interval cannot be 0.0 or less.");
}
else{
gr->samprat = sampRate;
}

Other Docs

Known Problems

sineWave.c457

Developers Programming Guide

/* assign the trace length, use the agfc.h NINT macro */


if( traceLen <= 0.0 ){
exErrFatal("The trace length cannot be 0.0 or less.");
}
else{
gr->numsmp = NINT( traceLen/sampRate ) + 1;
}
/* check the number of ensembles */
if( nens < 1 ){
exErrFatal("Number of ensembles is less than 1.");
}
/* define the minimum standard header entries */
defStdHdr();
/* set the primary sort flag depending on primary key name */
if( strncmp( pkeyName, "CDP", 3 ) == 0 ){
/* .. add CDP, OFFSET, and AOFFSET to headers */
hdrAddStd("CDP");
hdrAddStd("OFFSET");
hdrAddStd("AOFFSET");
/* .. set the primary sort flag to CDP */
gr->ipsort = ICDP;
/*
/*
/*
/*
/*
/*
/*

..
..
..
..
..
..
..

set the primary sort trace header index to cdp */


IMPORTANT NOTE, the standard header structure contains */
header index values that are appropriate for FORTRAN, a */
result of the trace executive being in FORTRAN. When you */
set gr->ipkey, use FORTRAN-appropriate values. When you */
need C header indicies, use the hdrIndex function or */
subtract 1 from the standard header value in stdHdr. */
gr->ipkey = stdHdr->icdp;

/* .. set the secondary key sort index to OFFSET */


gr->iskey = stdHdr->ioffset;
}
else{
/* .. add SIN, SOURCE, CHAN, and FFID to the header */
hdrAddStd("SIN");
hdrAddStd("SOURCE");
hdrAddStd("CHAN");
hdrAddStd("FFID");
/* .. set the primary sort flag to source */
gr->ipsort = ISIN;
/* .. set the primery sort index to source */
gr->ipkey = stdHdr->isource;
/* .. set the secondary sort index to channel */
gr->iskey = stdHdr->ichan;
}
/* set the domain to normal space-time */
gr->idomain = ITX;

Other Docs

Known Problems

sineWave.c458

Developers Programming Guide

/* it is impossible for the geometry to match or the trace number */


/* to be valid */
gr->igeom_match = FALSE;
gr->itrno_valid = FALSE;
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

here are the


gr->nth
gr->mode
gr->iounit
gr->idate
gr->npriorf
gr->cleanup
gr->ierror

globalRuntime variables that you do not set: */


- the number of 4-byte words in the trace header
- the run mode (INTER, IBACKG, IBATCH)
- the I/O unit for output diagnostics
- the current date (seconds since 00:00:00 GMT, Jan 1, 1970)
- number of prior processing flows
- flag indicating the system is in cleaup mode
- flag indicating the system is running under an error
condition and trying to cleanup
gr->init_only - flag indicating that only initialization phase is
being executed
*/

/* initialize some values for exec phase */


currEns = 1;
currTrcInEns = 1;
firstVisit = TRUE;
/* set the number of words that need to be saved for re-entrancy */
*len_sav = NPARMS(parms);
/* set the tool type to simple, (one trace in one trace out). */
*itooltype = INPUT;
/* set the external parameters */
parms->nens
= nens
parms->nfreqs
= nfreqs
parms->freqs
= freqs
parms->currEns
= currEns
parms->currTrcInEns = currTrcInEns
parms->firstVisit
= firstVisit

;
;
;
;
;
;

}
/*-------------------------------------------------------------------*/
/* exec_sine_wave
/*
/* execution routine for ProMAX module sine_wave
/*
/*
/*-------------------------------------------------------------------*/
void exec_sine_wave_( float* trace, float* rthdr, int* ithdr )
{
/* declare
int
int
float
int
int
logical

local versions
nens
=
nfreqs
=
*freqs
=
currEns
=
currTrcInEns =
firstVisit
=

Other Docs

of external variables */
parms->nens
;
parms->nfreqs
;
parms->freqs
;
parms->currEns
;
parms->currTrcInEns ;
parms->firstVisit
;

Known Problems

sineWave.c459

Developers Programming Guide

/* declare local variables */


logical noDataFound;
int iErr;
/* set a pointer to the globalRuntime structure */
GlobalRuntime *gr = globalRuntime;
/* see if we are in cleanup phase */
if( gr->cleanup ){
free( parms->freqs );
return;
}
/* fill the current trace and header buffers */
noDataFound = sineWaveNextTr( trace, ithdr, rthdr, freqs );
if( parms->firstVisit == TRUE ){
/* .. we only want to do this once */
parms->firstVisit = FALSE;
if( noDataFound == TRUE ){
exErrFatal("Unable to create any traces.");
}
}
if( noDataFound == TRUE ){
/* .. we have no data to output, this is analogous to hitting the end */
/* .. of a disk file or the end of a tape */
exQuitMode();
}
else{
/* .. we have a trace to give to the executive */
exFlushMode();
}
}
/*-------------------------------------------------------------------*/
/* sineWaveNextTr
/*
/* subroutine to overlay sine waves on a trace
/* input:
/*
freqs - array of frequencies to add to the sine wave
/*
/* output:
/*
trace - the trace on which sine waves are written
/*
ithdr - integer trace header array
/*
rthdr - float trace header array
/*
returns a logical (int) flag TRUE if trace could not be written to
/*
FALSE if normal completion
/*
/*-------------------------------------------------------------------*/
static int sineWaveNextTr( float *trace, int *ithdr, float *rthdr,
float *freqs )
{
/* local variables */

Other Docs

Known Problems

sineWave.c460

Developers Programming Guide

int i;
int iErr;
float offset;
/* global variables */
GlobalRuntime *gr = globalRuntime;
if( parms->currEns > parms->nens ){
/* .. we have no more data to output, this is equivalent to */
/* .. failing to read a trace from tape or disk */
return(TRUE);
}
/* if control reaches here we need to build a trace */
/* clear the input data trace */
vClr( trace, 1, gr->numsmp );
/* add the sine_wave data to the trace */
for( i = 0; i < parms->nfreqs; i++ ){
sineWaveAdd( freqs[i], gr->samprat, gr->numsmp, trace );
}
/* initialize the values of the minimum standard header values */
initStdHdr( ithdr, rthdr );
/* take care of other header entries */
if( gr->ipsort == ISIN ){
/* .. inputting shots */
/* .. the source index number should be null until geom is assigned */
ithdr[ hdrIndex("SIN") ] = INULL;
/* .. set the live source number */
ithdr[ hdrIndex("SOURCE") ] = parms->currEns;
/* .. set the channel number */
ithdr[ hdrIndex("CHAN") ] = parms->currTrcInEns;
/* .. set the field file id number, FFID */
ithdr[ hdrIndex("FFID") ] = parms->currEns;
}
else{
/* .. inputting CDPs */
/* .. set the CDP bin number */
ithdr[ hdrIndex("CDP") ] = parms->currEns;
/* .. set the offset and aoffset, these values don't make much sense */
offset = (float)(parms->currTrcInEns);
rthdr[ hdrIndex("OFFSET") ] = offset;
rthdr[ hdrIndex("OFFSET") ] = (float)fabs( (double)offset );
}
/* set the sequence number in the ensemble */
ithdr[ hdrIndex("SEQNO") ] = parms->currTrcInEns;
/* set the sequential trace number (null until geometry is assigned) */

Other Docs

Known Problems

sineWave.c461

Developers Programming Guide

ithdr[ hdrIndex("TRACENO")] = INULL;


if( parms->currTrcInEns == gr->maxdtr ){
/* .. this is the last trace in the ensemble, set end of ens flag */
ithdr[ hdrIndex("END_ENS") ] = LASTTR;
/* .. reset the trace-in-ensemble counter, it gets incremented below */
parms->currTrcInEns = 0;
/* .. increment the ensemble number for next time */
parms->currEns += 1;
}
else{
/* .. this is not the last trace in the ensembel */
ithdr[ hdrIndex("END_ENS") ] = NLAST;
}
/* increment the trace in ensemble counter for the next trace */
parms->currTrcInEns += 1;
return( FALSE );
}

/*-------------------------------------------------------------------*/
/* sineWaveAdd
/*
/* subroutine to add a sine wave to a trace
/* input:
/*
freq - frequency of sine wave to add
/*
sampInt - float sample interval of trace in ms
/*
numsmp - number of samples in trace
/* output:
/*
trace - the trace
/*
/*-------------------------------------------------------------------*/
static void sineWaveAdd( float freq, float sampInt, int numsmp,
float *trace )
{
/* local variables */
int i;
double angle, twoPi, time;
twoPi = asin(1.0)*4.0;
for( i = 0; i < numsmp; i++ ){
time = (float)i * sampInt/1000.;
angle = freq*time*twoPi;
trace[i] += (float)sin( angle );
}
}

Other Docs

Known Problems

sineWave.c462

Other Docs

Developers Programming Guide

Known Problems

463

Developers Programming Guide

Appendix: Disk Iteration Examples

The appendix demonstrates the use of the disk iteration


capabilities of ProMAX tools. The following examples present
a prototype for a surface-consistent amplitude correction
program. A FORTRAN example is presented first, followed by
a C example.
The critical subroutine in this disk iteration program is
EX_SET_DISKITER() in FORTRAN and ex_set_diskiter_() in
C. Note that in C, the program is simply calling the FORTRAN
code directly. Since there is only one calling argument, this is
not difficult to do.

Topics covered in this chapter:

Other Docs

sc_amp.menu
sc_amp.inc
sc_amp.f
disk_iter.menu
disk_iter.c

Known Problems

sc_amp.menu464

Developers Programming Guide

sc_amp.menu
'(
name: SC_AMP
label: "Sc Amp"
value_tab: 35
exec_data: ("SC_AMP"
("GENERAL"
("dummy" implicit: nil)
)
)
)

Other Docs

Known Problems

sc_amp.inc465

Developers Programming Guide

sc_amp.inc
C-----------------------------------------------------------------------------C
Include file for SC_AMP
C-----------------------------------------------------------------------------IMPLICIT NONE
#include "global.inc"

&

&

COMMON /SAVED_PARMS/ SAVE1z, NSHOTS, NRECS, IX_SHOT_SUM,


IX_SHOT_NORM, IX_REC_SUM, IX_REC_NORM, IX_TR, PROCESSING
INTEGER LENSAVED, NSHOTS, NRECS, IX_SHOT_SUM, IX_SHOT_NORM,
IX_REC_SUM, IX_REC_NORM, IX_TR
LOGICAL PROCESSING
DATA LENSAVED /9/

Other Docs

Known Problems

sc_amp.f466

Developers Programming Guide

sc_amp.f
C ..... This is a working model for a surface consistent gain module.
C ..... makes no attempt for true separation of source and receiver.

It

SUBROUTINE INIT_SC_AMP( LEN_SAV, ITOOLTYPE )


#include "sc_amp.inc"
#include "header.inc"
INTEGER LEN_SAV, ITOOLTYPE, IERR, IOK_HDR
C ..... Ask for two iterations through the data, one the analyze the data
C ..... and one to process the data
CALL EX_SET_DISKITER( 2 )
C ..... Make sure that the needed geometry parameters are valid
IF ( MAXSINz .EQ. INULLpz .OR. MINSINz .EQ. INULLpz
&
.OR. INCSINz .EQ. INULLpz .OR. MAXSLOCz .EQ. INULLpz
&
.OR. MINSLOCz .EQ. INULLpz .OR. INCSLOCz .EQ. INULLpz )
&
CALL EX_ERR_FATAL( 'Geometry parameters are null' )
C ..... Reserve a buffer to store the sum and normalization factor for every
C ..... shot and receiver
NSHOTS = (MAXSINz-MINSINz) / INCSINz + 1
NRECS = (MAXSLOCz-MINSLOCz) / INCSLOCz + 1
CALL MEM_RESBUFF( NSHOTS, IX_SHOT_SUM, IERR )
CALL MEM_RESBUFF( NSHOTS, IX_SHOT_NORM, IERR )
CALL MEM_RESBUFF( NRECS, IX_REC_SUM, IERR )
CALL MEM_RESBUFF( NRECS, IX_REC_NORM, IERR )
C ..... Get a work buffer to hold one trace
CALL MEM_RESBUFF( NUMSMPz, IX_TR, IERR )
C ..... Check for needed header entries
IF ( IOK_HDR(ISINz) .NE. 1 .OR. IOK_HDR(IREC_SLOCz) .NE. 1 )
&
CALL EX_ERR_FATAL( 'SIN or REC_SLOC not found in header' )
IF ( IOK_HDR(IDISKITERz) .NE. 1 ) CALL EX_ERR_FATAL(
&
'DISKITER not found in header (not using Disk Data Input?)' )
C ..... Initialize for execution phase
PROCESSING = .FALSE.
C ..... Set the number of words for re-entrancy and the tool type
LEN_SAV = LENSAVED
ITOOLTYPE = ICOMPLEXpz
RETURN
END

SUBROUTINE EXEC_SC_AMP( TRACE, ITHDR, RTHDR )


#include "sc_amp.inc"
#include "header.inc"

Other Docs

Known Problems

sc_amp.f467

Developers Programming Guide

#include "mem.inc"
INTEGER ITHDR(NTHz), ISHOT, IREC
REAL TRACE(NUMSMPz), RTHDR(NTHz), SCALAR
C ..... No action required in cleanup phase
IF ( CLEANUPz ) RETURN
IF ( ITHDR(ISINz) .GE. MINSINz
&
.AND. ITHDR(ISINz) .LE. MAXSINz
&
.AND. ITHDR(IREC_SLOCz) .GE. MINSLOCz
&
.AND. ITHDR(IREC_SLOCz) .LE. MAXSLOCz ) THEN
C ......... This is a valid trace
C ......... Compute the sequential shot and receiver mem offset
ISHOT = (ITHDR(ISINz)-MINSINz) / INCSINz + 1
IREC = (ITHDR(IREC_SLOCz)-MINSLOCz) / INCSLOCz + 1
IF ( ITHDR(IDISKITERz) .EQ. 1 ) THEN
C ............. Still analyzing the data
C ............. Call the routine to accumulate the statistics
CALL SC_AMP_ACCUM( ISHOT, IREC, TRACE, RSPACEz(IX_TR),
&
NUMSMPz, RSPACEz(IX_SHOT_SUM),
&
RSPACEz(IX_SHOT_NORM), RSPACEz(IX_REC_SUM),
&
RSPACEz(IX_REC_NORM) )
ELSE
C ............. Processing the data
IF ( .NOT. PROCESSING ) THEN
C ................. Just started processing
PROCESSING = .TRUE.
C ................. Normalize the values
CALL SC_AMP_NORM( NSHOTS, NRECS,
&
RSPACEz(IX_SHOT_SUM), RSPACEz(IX_SHOT_NORM),
&
RSPACEz(IX_REC_SUM), RSPACEz(IX_REC_NORM) )
ENDIF
C ............. Apply the scalar to this trace
SCALAR = ( RSPACEz(IX_SHOT_SUM+ISHOT-1)
&
+ RSPACEz(IX_REC_SUM+IREC-1) ) / 2.0
CALL VSDIV( TRACE, 1, SCALAR, TRACE, 1, NUMSMPz )
ENDIF
ENDIF
IF ( ITHDR(IDISKITERz) .EQ. 1 ) THEN
C ......... Still analyzing the data, so act as a black hole
CALL EX_FILLMODE
ELSE
CALL EX_PIPEMODE
ENDIF
RETURN
END

&

SUBROUTINE SC_AMP_ACCUM( ISHOT, IREC, TRACE, TR_WORK,


NUMSMP, SHOT_SUM, SHOT_NORM, REC_SUM, REC_NORM )

C ..... Routine to accumulate the statistics

Other Docs

Known Problems

sc_amp.f468

&

Developers Programming Guide

IMPLICIT NONE
INTEGER ISHOT, IREC, NUMSMP
REAL TRACE(NUMSMP), TR_WORK(NUMSMP), SHOT_SUM(*), SHOT_NORM(*),
REC_SUM(*), REC_NORM(*), SUM, AVEAMP

C ..... Convert the trace to absolute values


CALL VABS( TRACE, 1, TR_WORK, 1, NUMSMP )
C ..... Take the sum
CALL SVE( TR_WORK, 1, SUM, NUMSMP )
C ..... Normalize to the number of samples (ignore hard zeros)
AVEAMP = SUM / FLOAT(NUMSMP)
C ..... Add this value to the respective shot and receiver
SHOT_SUM(ISHOT) = SHOT_SUM(ISHOT) + AVEAMP
SHOT_NORM(ISHOT) = SHOT_NORM(ISHOT) + 1.0
REC_SUM(IREC) = REC_SUM(IREC) + AVEAMP
REC_NORM(IREC) = REC_NORM(IREC) + 1.0
RETURN
END

&

SUBROUTINE SC_AMP_NORM( NSHOTS, NRECS, SHOT_SUM, SHOT_NORM,


REC_SUM, REC_NORM )

C ..... Routine to normalize the values

&

100

110

IMPLICIT NONE
INTEGER NSHOTS, NRECS, I
REAL SHOT_SUM(NSHOTS), SHOT_NORM(NSHOTS), REC_SUM(NRECS),
REC_NORM(NRECS)
DO 100 I=1,NSHOTS
IF ( SHOT_NORM(I) .GT. 0.0 ) THEN
SHOT_SUM(I) = SHOT_SUM(I) / SHOT_NORM(I)
ELSE
SHOT_SUM(I) = 1.0
ENDIF
CONTINUE
DO 110 I=1,NRECS
IF ( REC_NORM(I) .GT. 0.0 ) THEN
REC_SUM(I) = REC_SUM(I) / REC_NORM(I)
ELSE
REC_SUM(I) = 1.0
ENDIF
CONTINUE
RETURN
END

Other Docs

Known Problems

disk_iter.menu469

Developers Programming Guide

disk_iter.menu
'(
name: DISK_ITER
label: "Disk Iteration Demo"
value_tab: 50
exec_data: ("DISK_ITER"
("GENERAL"
("DUMMY"

implicit: 0)

)
)
)

Other Docs

Known Problems

disk_iter.c470

Developers Programming Guide

disk_iter.c
/*--------------------------------------------------------------------*/
/* disk_iter
/* A demo program for iterating over a dataset and scaling the
/* shot records by the power of the shot record.
/*
/*--------------------------------------------------------------------*/
/* include promax interface, globals, error codes, etc */
#include "cpromax.h"
#include "cglobal.h"
/* define saved parameters */
BEGINPARMS
float *scalVals; /* scalar values */
int
hdrIndexSIN;
ENDPARMS(parms)
/*-------------------------------------------------------------------*/
/*
/* description:
/*
initialization routine for disk_iter
/*
/* output arguments:
/*
len_sav - length of the saved common block
/*
itooltype - type of tool
/*
/*
/*-------------------------------------------------------------------*/
void init_disk_iter_( int *len_sav, int *itooltype )
{
int nShots, numIters, i;
/* set the global pointers */
GlobalRuntime *gr = globalRuntime;
GlobalGeom
*gg = globalGeom;
/* make sure the data are sorted by source */
if( gr->ipsort != ISIN ){
exErrFatal("Data must be sorted by SIN for this program to operate.");
}
/* allocate and initialize enough memory to store shot scalar values */
nShots = gg->maxsin - gg->minsin + 1;
if( nShots <= 0 ){
exErrFatal("Number of shots must be greater than 0. Have you "
"assigned geometry yet?");
}
parms->scalVals = (float*)malloc( nShots * sizeof(float));
if( parms->scalVals == NULL ){

Other Docs

Known Problems

disk_iter.c471

Developers Programming Guide

exErrFatal("Memory allocation error, %d bytes requested.",


nShots * sizeof(float));
}
for( i = 0; i < nShots; i++ ){
parms->scalVals[i] = 0.0;
}
/* set the number of disk iterations, note that this is a call to a
/* FORTRAN routine so the address of numIters has to be passed. */
numIters = 2;
ex_set_diskiter_( &numIters );

*/

/* get the trace header index of SIN */


if( hdrExists("SIN") ){
parms->hdrIndexSIN = hdrIndex("SIN");
}
else{
exErrFatal("The header SIN does not exist in the dataset."
"Assign geometry to the data.");
}
/* set the number of words that need to be saved */
*len_sav = NPARMS(parms);
/* set the tool type */
*itooltype = ICOMPLEX;
}

/*-------------------------------------------------------------------*/
/*
/*
description:
/*
exectution routine for disk_iter
/*
/*
input/output arguments:
/*
trace - data trace
/*
ithdr - int header array
/*
rthdr - float header array
/*
/*-------------------------------------------------------------------*/
void exec_disk_iter_( float *trace, int *ithdr, float *rthdr)
{
int i;
float val;
/* set the global pointers */
GlobalRuntime *gr = globalRuntime;
GlobalGeom
*gg = globalGeom;
if( ithdr[ hdrIndex("DISKITER") ] == 1 ){
/* .. this is the first pass of the data */
/* .. sum the amplitudes */
if( ithdr[ parms->hdrIndexSIN ] < gg->maxsin ){
for( i = 0; i < gr->numsmp; i++ ){

Other Docs

Known Problems

disk_iter.c472

Developers Programming Guide

parms->scalVals[parms->hdrIndexSIN] += trace[i]*trace[i];
}
}
/* .. we are in just getting info from traces, not passing them on yet */
exFillMode();
}
else{
/* .. this is the second pass of the data */
/* .. scale the trace */
if( val = parms->scalVals[parms->hdrIndexSIN] != 0.0 ){
for( i = 0; i < gr->numsmp; i++ ){
trace[i] /= val;
}
}
/* .. put this trace back into the flow and receive one on the next call */
exPipeMode();
}
}

Other Docs

Known Problems

473

Developers Programming Guide

Appendix: Stand-alone Tool


Examples

This appendix provides examples of stand-alone programs. The


first group of programs shows how to read data from a ProMAX
disk dataset. It includes two FORTRAN examples (prestack.f
and poststack.f) and one C example (poststack.c). Note that the
FORTRAN routines require a C program, or wrapper, to allow
the program to pass command line arguments. The C program
does not require a wrapper, since command line arguments can
be passed directly to the program.
The next program (vel_io.f) demonstrates how to input and
output velocities to the ProMAX database.

Topics covered in this appendix:

Other Docs

prestack_menu
prestack.f
Makefile_prestack
poststack.f
Makefile_poststack
poststack.c
vel_io.f

Known Problems

prestack.menu474

Developers Programming Guide

prestack.menu
'(
name: DOMAIN_READ
label: "Domain Read*"
value_tab: 47
parameter: LABEL
text: "Select trace data file"
type: function:
type_desc: (dataset_list datasets)
value: "no entry"
selected_item: "* No Datasets Found *"
mouse_text: "Use Mouse Button 1 to select a trace data file description from the
datasets menu."
parameter: DOMAIN
text: "Domain of the data"
type: pop_choose:
type_desc: (
("CDP" 1 "CDP domain." )
("SIN" 2 "Source domain.")
("SRF" 3 "Surface location domain." )
)
mouse_text: "Use B1 to pop up a menu to select the domain."
exec_data: ("DOMAIN_READ"
("SPECIAL"
("TOOLTYPE"
implicit: "STAND_ALONE")
("PATHNAME"
implicit:
"/home/dave/exer/stand_alone/prestack.exe")
)
("GENERAL"
("LABEL"
("DOMAIN"
)

implicit: (value 'LABEL))


implicit: (value 'DOMAIN))

)
)

Other Docs

Known Problems

prestack.f475

Developers Programming Guide

prestack.f
C
C
C
C
C
C
C
C
C
C
C
C
C
C

This is the C "wrapper" that passes command line args to the FORTRAN
stand alone program. This produces the main executable file that is
referenced in the menu under the "special" parameter section.
void main( argc, argv )
int argc;
char **argv;
{
prestack_( &argc, argv[1] );
}
.....
.....
.....
.....

This is a sample program that shows how a stand-alone program can


use the database to grab traces without searching. Traces are
selected from disk in any order by accessing the trace file using
the orginal trace number.
SUBROUTINE PRESTACK( NARGS, CINPUT )

IMPLICIT NONE
#include "global.inc"
#include "mem.inc"
INTEGER NARGS, ID_PACKET, IERR, NCHARS, ID_DATASET, IREAD_ONLY,
&
NDFILES, ISWAPENDS, ITRTOTAL, NUMSMP, NTH, MAXDTR, MAXATR,
&
IPSORT, IPKEY, ISKEY, IDTYP, IDOMAIN, NTRACES, IGEOM_MATCH,
&
ITRNO_VALID, NPRIORF, IFORMAT, LENGTH, IH_PKEY,
&
IX_TRACE, IX_THDR, MAXFOLD, NENS,
&
INPUT_DOMAIN
REAL SAMPRAT, SOFTRLP, GEORLSP
CHARACTER CINPUT(*), CAREA(16), CLINE(16)
CHARACTER CPACKET_FILE*128, CLABEL*8, CDESC*32, CHDRNAM*8,
&
CENS_FLAG*3
IF ( NARGS .LT. 2 ) THEN
C ......... Nothing was entered on the command line
CALL U_ERR_FATAL( 'Packet file must be specified' )
ENDIF
C ..... Load the character ARRAY into a character STRING.
C ..... understand the difference.
CALL U_CARR2STR( CINPUT, CPACKET_FILE, 128 )
C ..... Open
CALL
&
IF (
&
C
C
C
C

.....
.....
.....
.....

Be sure that you

the parameter packet file, get back the ID, area, and line
PKT_OPEN_LOAD( CPACKET_FILE, 'DOMAIN_READ
', ID_PACKET,
CAREA, CLINE )
ID_PACKET .EQ. 0 ) CALL U_ERR_FATAL(
'Unable to open packet file' )

Initialize the database for this area and line. Note that CAREA
and CLINE are character arrays, not character strings. This call
set globals geom. from LIN OPF and directory path for database
routines.
CALL DB_INIT_LINE( CAREA, CLINE, IERR )
IF ( IERR .NE. 0 ) THEN
CALL REPORT_DB_ERR( IERR )
CALL U_ERR_FATAL( 'Unable to initialize the database' )

Other Docs

Known Problems

prestack.f476

Developers Programming Guide

ENDIF
C ..... Get the label for the dataset from the packet file. Parameters
C
are input using standalone version of EX_GET_PARM
CALL U_CGETPARM( ID_PACKET, 'LABEL
', 1, CLABEL, NCHARS )
C ..... Get the requested domain: 1=CDP, 2=SIN, 3=SRF
CALL U_GETPARM( ID_PACKET, 'DOMAIN ', 1, INPUT_DOMAIN )
IF ( INPUT_DOMAIN .EQ. 1 ) THEN
CENS_FLAG = 'CDP'
ELSEIF ( INPUT_DOMAIN .EQ. 2 ) THEN
CENS_FLAG = 'SIN'
ELSEIF ( INPUT_DOMAIN .EQ. 3 ) THEN
CENS_FLAG = 'SRF'
ENDIF
C ..... Open the dataset (status=readonly)
IREAD_ONLY = 1
CALL DISKIO_OPEN( CLABEL, IREAD_ONLY, ID_DATASET, IERR )
IF ( IERR .NE. 0 ) THEN
CALL U_ERR_FATAL(
&
'Unable to open the trace dataset ' // CLABEL )
ENDIF
C ..... Get misc. info on the dataset. This is where runtime globals
C ..... are set.
CALL DISKIO_INFO( ID_DATASET, NDFILES, ISWAPENDS,
&
ITRTOTAL, SAMPRAT, NUMSMP, NTH, MAXDTR,
&
MAXATR, IPSORT, IPKEY, ISKEY, IDTYP, IDOMAIN,
&
NTRACES, IGEOM_MATCH, ITRNO_VALID, NPRIORF, SOFTRLP,
&
GEORLSP )
C
C
C
C
C

.....
.....
.....
.....
.....

Set up the trace headers (this will cause a bunch of calls to


HDR_ADD, creating all of the header entries that were found in
the dataset). Complete header description info (list of names,
format, length, etc) is now available using the same in-line
executive header subroutines.
CALL DISKIO_THDR_SETUP( ID_DATASET, IERR )

C ..... Now we can get header information. We are after the index of
C ..... the primary key in question.
IF ( CENS_FLAG .EQ. 'CDP' ) THEN
CHDRNAM = 'CDP
'
ELSEIF ( CENS_FLAG .EQ. 'SIN' ) THEN
CHDRNAM = 'SIN
'
ELSEIF ( CENS_FLAG .EQ. 'SRF' ) THEN
CHDRNAM = 'REC_SLOC'
ENDIF
CALL HDR_NAMINFO( CHDRNAM, CDESC, LENGTH, IFORMAT,
&
IH_PKEY, IERR )
IF ( IERR .NE. 0 ) CALL U_ERR_FATAL(
&
'Primary key not found in header' )
C ..... Allocate buffers for a trace and a trace header.
C ..... of memory routines as in executive.
CALL MEM_RESBUFF( NUMSMP, IX_TRACE, IERR )
CALL MEM_RESBUFF( NTH, IX_THDR, IERR )

Same use

C ..... Determine the actual number of ensembles and the maximum fold.

Other Docs

Known Problems

prestack.f477

Developers Programming Guide

C ..... Note that all of these variables were set by DB_INIT_LINE. You
C ..... should check to see if they are null (geometry not loaded).
IF ( CENS_FLAG .EQ. 'CDP' ) THEN
NENS = ( MAXCDPz - MINCDPz ) / INCCDPz + 1
MAXFOLD = NTRCDPz
ELSEIF ( CENS_FLAG .EQ. 'SIN' ) THEN
NENS = ( MAXSINz - MINSINz ) / INCSINz + 1
MAXFOLD = MAXCPSz
ELSEIF ( CENS_FLAG .EQ. 'SRF' ) THEN
NENS = ( MAXSLOCz - MINSLOCz ) / INCSLOCz + 1
MAXFOLD = MAXTPRz
ENDIF

&
&

IF ( NENS .LT. 1 ) CALL U_ERR_FATAL(


'Less than 1 ensemble exists' )
IF ( MAXFOLD .LT. 1 ) CALL U_ERR_FATAL(
'Maximum fold is less than 1' )

C ..... Call
CALL
&
&

the routine that does the actual work.


STAND_ALONE_WORK( ISPACEz(IX_TRACE), ISPACEz(IX_THDR),
ISPACEz(IX_THDR), NUMSMP, NTH, NENS, IH_PKEY,
ID_DATASET, CENS_FLAG )

C ..... Close the packet file


CALL PKT_FILCLOSE( ID_PACKET, IERR )
C ..... Close the dataset
CALL DISKIO_CLOSE( ID_DATASET )
C ..... Report normal completion
CALL U_COMP_NORMAL
END

&

SUBROUTINE STAND_ALONE_WORK( TRACE, ITHDR, RTHDR, NUMSMP, NTH,


NENS, IH_PKEY, ID_DATASET, CENS_FLAG )
IMPLICIT NONE

#include "global.inc"

&
&

INTEGER NUMSMP, NTH, NENS, IFOUND_VAL, ITRACENO, ITHDR(NTH),


IFOLD, IERR, J, I, IH_PKEY, ITOKEN1, ID_DATASET, IENS,
ITOKEN2
REAL RTHDR(NTH), TRACE(NUMSMP)
CHARACTER CENS_FLAG*3, CS_DOMAIN*8, CPKEYNAM*8

C ..... Assign the secondary key domain (not called 'FOLD' in SIN domain)
C ..... Also assign the primary key name
IF ( CENS_FLAG .EQ. 'CDP' ) THEN
CS_DOMAIN = 'FOLD
'
CPKEYNAM = 'CDP
'
ELSEIF ( CENS_FLAG .EQ. 'SRF' ) THEN
CS_DOMAIN = 'FOLD
'
CPKEYNAM = 'SRF
'
ELSEIF ( CENS_FLAG .EQ. 'SIN' ) THEN

Other Docs

Known Problems

prestack.f478

Developers Programming Guide

CS_DOMAIN = 'NCHANS '


CPKEYNAM = 'SIN
'
ENDIF
C ..... Loop over the ensembles
DO 110 J=1,NENS
C ......... Determine which ensemble this is
IF ( CENS_FLAG .EQ. 'CDP' ) THEN
IENS = MINCDPz + (J-1) * INCCDPz
ELSEIF ( CENS_FLAG .EQ. 'SIN' ) THEN
IENS = MINSINz + (J-1) * INCSINz
ELSEIF ( CENS_FLAG .EQ. 'SRF' ) THEN
IENS = MINSLOCz + (J-1) * INCSLOCz
ENDIF
C ......... Get the fold for this ensemble. Use the ensemble number to examine
C ......... the appropriate ordered parameter file and retrieve the fold.
CALL DB_ENSEMBLE_MAP( ITOKEN1, CPKEYNAM, CPKEYNAM,
&
CS_DOMAIN, IENS, IFOLD, IFOUND_VAL, IERR )
C ......... Note that in some situations this might not be a fatal error.
IF ( IFOUND_VAL .NE. 1 .OR. IERR .NE. 0 ) THEN
WRITE (*,*) CPKEYNAM, J, IFOUND_VAL, IERR
CALL U_ERR_FATAL( 'Error getting FOLD' )
ENDIF
WRITE (*,*)
C ......... Read every trace in the ensemble.
C ......... the fold for this ensemble.
DO 100 I=1,IFOLD

Note that we are looping over

C ............. Given the primary key and sequence number within ensemble,
C ............. get the trace number. Again the order parameter files are
C ............. the vehicle for extracting the all important original trace #
CALL DB_TRACE_MAP( ITOKEN2, CPKEYNAM, 'sequence',
&
'traceno ', IENS, I, ITRACENO, IFOUND_VAL, IERR )
C ............. Note that in some situations this might not be a fatal error
IF ( IFOUND_VAL .NE. 1 .OR. IERR .NE. 0 ) THEN
WRITE (*,*) CPKEYNAM, I, IFOUND_VAL, IERR
CALL U_ERR_FATAL( 'Error getting TRACENO' )
ENDIF
C
C
C
C

.............
.............
.............
.............
&

This reads in a trace and headers given the original trace


number. ITRACENO can be replaced with a negative integer to
simply access the traces by sequential order (ie -143 ->
gets the 143rd trace).
CALL DISKIO_GET_TR( ID_DATASET, ITRACENO,
ITHDR, TRACE, IERR )

C ............. These had BETTER be the same


IF ( IENS .NE. ITHDR(IH_PKEY) ) THEN
WRITE (*,*) I, J, IENS, ITHDR(IH_PKEY)
CALL U_ERR_FATAL( 'IENS != ITHDR(IH_PKEY)' )
ENDIF

&

Other Docs

WRITE (*,*) 'IENS= ', IENS, '


ITHDR(IH_PKEY)

ITHDR= ',

Known Problems

prestack.f479

100
110

Developers Programming Guide

CONTINUE
CONTINUE
RETURN
END

Other Docs

Known Problems

Makefile_prestack480

Developers Programming Guide

Makefile_prestack
##############################################################################
# Makefile for ProMAX standalone program
##############################################################################
# Program name
name = prestack
# Object files - preface any product-specific files with "$(product)/"
objs = prestack_main.o prestack.o
# Libraries - to be searched before and after the standard ProMAX libraries
libsbefore =
libsafter =
# Standard rules to make ProMAX programs
include maxprog.make
# be quiet
.SILENT:

Other Docs

Known Problems

poststack.f481

Developers Programming Guide

poststack.f
C
C
C
C
C
C
C
C
C
C

This is the C "wrapper" that passes command line args to the FORTRAN
stand alone program. This produces the main executable file that is
referenced in the menu under the "special" parameter section.
void main( argc, argv )
int argc;
char **argv;
{
poststack_( &argc, argv[1] );
}

C ..... This is a sample program that shows how a stand-alone program can
C ..... read post-stack traces (or otherwise access data without using
C ..... TRACENO as a key)
SUBROUTINE POSTSTACK( NARGS, CINPUT )
IMPLICIT NONE
#include "global.inc"
#include "mem.inc"
INTEGER NARGS, ID_PACKET, IERR, NCHARS, ID_DATASET, IREAD_ONLY,
&
NDFILES, ISWAPENDS, ITRTOTAL, NUMSMP, NTH, MAXDTR, MAXATR,
&
IPSORT, IPKEY, ISKEY, IDTYP, IDOMAIN, NTRACES, IGEOM_MATCH,
&
ITRNO_VALID, NPRIORF, IFORMAT, LENGTH, IH_CDP,
&
IX_TRACE, IX_THDR
REAL SAMPRAT, SOFTRLP, GEORLSP
CHARACTER CINPUT(*), CAREA(16), CLINE(16)
CHARACTER CPACKET_FILE*128, CLABEL*8, CDESC*32
IF ( NARGS .LT. 2 ) THEN
C ......... Nothing was entered on the command line
CALL U_ERR_FATAL( 'Packet file must be specified' )
ENDIF
C ..... Load the character ARRAY into a character STRING.
C ..... understand the difference.
CALL U_CARR2STR( CINPUT, CPACKET_FILE, 128 )

Be sure that you

C ..... Open the parameter packet file, get back the ID, area, and line
C ..... STAND_ALONE was the name specified in the menu file.
CALL PKT_OPEN_LOAD( CPACKET_FILE, 'POSTSTACK_READ ', ID_PACKET,
&
CAREA, CLINE )
IF ( ID_PACKET .EQ. 0 ) CALL U_ERR_FATAL(
&
'Unable to open packet file' )
C ..... Initialize the database for this area and line. Note that CAREA
C ..... and CLINE are character arrays, not character strings.
CALL DB_INIT_LINE( CAREA, CLINE, IERR )
IF ( IERR .NE. 0 ) THEN
CALL REPORT_DB_ERR( IERR )
CALL U_ERR_FATAL( 'Unable to initialize the database' )
ENDIF
C ..... Get the label for the dataset from the packet file.
C ..... the packet ID is an input arg.

Other Docs

Note that the

Known Problems

poststack.f482

CALL U_CGETPARM( ID_PACKET, 'LABEL

Developers Programming Guide

', 1, CLABEL, NCHARS )

C ..... Open the dataset, status=readonly


IREAD_ONLY = 1
CALL DISKIO_OPEN( CLABEL, IREAD_ONLY, ID_DATASET, IERR )
IF ( IERR .NE. 0 ) THEN
CALL U_ERR_FATAL(
&
'Unable to open the trace dataset ' // CLABEL )
ENDIF
C ..... Get misc. info on the dataset.
CALL DISKIO_INFO( ID_DATASET, NDFILES, ISWAPENDS,
&
ITRTOTAL, SAMPRAT, NUMSMP, NTH, MAXDTR,
&
MAXATR, IPSORT, IPKEY, ISKEY, IDTYP, IDOMAIN,
&
NTRACES, IGEOM_MATCH, ITRNO_VALID, NPRIORF, SOFTRLP,
&
GEORLSP )
C
C
C
C
C

.....
.....
.....
.....
.....

Set up the trace headers (this will cause a bunch of calls to


HDR_ADD, creating all of the header entries that were found in
the dataset). Complete header description info (list of names,
format, length, etc) is now available using the same in-line
executive header subroutines.
CALL DISKIO_THDR_SETUP( ID_DATASET, IERR )

C ..... Get the index of CDP


CALL HDR_NAMINFO( 'CDP
', CDESC, LENGTH, IFORMAT,
&
IH_CDP, IERR )
IF ( IERR .NE. 0 ) CALL U_ERR_FATAL(
&
'Primary key not found in header' )
C ..... Allocate buffers for a trace and a trace header
CALL MEM_RESBUFF( NUMSMP, IX_TRACE, IERR )
CALL MEM_RESBUFF( NTH, IX_THDR, IERR )
C ..... Call the routine that does the actual work.
CALL STAND_ALONE_WORK( ISPACEz(IX_TRACE), ISPACEz(IX_THDR),
&
IH_CDP, ID_DATASET, ITRTOTAL )
C ..... Close the packet file
CALL PKT_FILCLOSE( ID_PACKET, IERR )
C ..... Close the dataset
CALL DISKIO_CLOSE( ID_DATASET )
C ..... Report normal completion
CALL U_COMP_NORMAL
END

&

SUBROUTINE STAND_ALONE_WORK( TRACE, ITHDR, IH_CDP, ID_DATASET,


ITRTOTAL )

IMPLICIT NONE
#include "global.inc"
INTEGER ITHDR(*)
INTEGER IERR, J, IH_CDP, ID_DATASET, ITRTOTAL

Other Docs

Known Problems

poststack.f483

Developers Programming Guide

REAL TRACE(*)
DO 100 J=1,ITRTOTAL
C ......... This reads in a trace, given the relative position within the
C ......... file.
CALL DISKIO_GET_TR( ID_DATASET, -J, ITHDR, TRACE, IERR )
IF ( IERR .NE. 0 ) THEN
WRITE (*,*) '*** ERROR *** ', J, IERR
ELSE
WRITE (*,*) 'CDP= ', ITHDR(IH_CDP)
ENDIF
100

CONTINUE
RETURN
END

Other Docs

Known Problems

Makefile_poststack484

Developers Programming Guide

Makefile_poststack
##############################################################################
# Makefile for ProMAX standalone program
##############################################################################
# Program name
name = poststack
# Object files - preface any product-specific files with "$(product)/"
# The following line is for the FORTRAN above
objs = poststack_main.o poststack.o
# The following line is for the C code example below
#objs = poststack.o
# Libraries - to be searched before and after the standard ProMAX libraries
libsbefore =
libsafter =
# Standard rules to make ProMAX programs
include maxprog.make
# be quiet
.SILENT:

Other Docs

Known Problems

poststack.c485

Developers Programming Guide

poststack.c
/*
/*
/*
/*
/*
/*

----------------------------------------------------------------*/
poststack()
This is a stand-alone ProMAX module for demonstration of a
stand alone program that reads in data traces and headers.
----------------------------------------------------------------*/

#include "cglobal.h"
#include "cpromax.h"
#include <stdio.h>

void main( int argc, char **argv )


{
/* declare local variables */
void *tblPntr;
char
char
int
int
int

cpacket_file[129], carea[17], cline[17];


*dsetLabel;
read_only;
id_dataset, errCode, ih_cdp;
i_128 = 128;

/* variables realated to the dataset */


int ndfiles, iswapends;
int trtotal, numsmp, nth, maxdtr;
int maxatr, ipsort, ipkey, iskey, idtyp, idomain;
int ntraces, igeom_match, itrno_valid, npriorf;
float samprat, softrlp, georlsp;
/* pointers to memory to hold a data trace and its header */
float *trace;
int *ihdr;
/* function used in the main program */
void stand_alone_work( float *trace, int *ithdr, int ih_cdp,
int id_dataset, int itrtotal );
/* set the global pointers */
GlobalRuntime *gr = globalRuntime;
GlobalGeom
*gg = globalGeom;
GlobalMisc
*gm = globalMisc;
/* Put argv[1] into a string called cpacket_file, this is a FORTRAN call */
u_carr2str_( argv[1], cpacket_file, &i_128, strlen(argv[1]) );
/* null terminate the string at the end */
cpacket_file[128] = '\0';
/* Open the parameter packet file and initialize the database */
/* This gives access to opf files, not actually used in this program.
/* Note that the character string must be padded to 16 characters. */

Other Docs

*/

Known Problems

poststack.c486

Developers Programming Guide

/* The character string "STAND_ALONE


" matches the tool name in the menu. */
initStandAlone(argc, argv, "STAND_ALONE
");

/* Get the 8-character label for the dataset from the packet file. */
uParGetString( "LABEL", &dsetLabel );
/* Open the dataset, status=readonly, note we are calling a FORTRAN routine
read_only = 1;
diskio_open_( dsetLabel, &read_only, &id_dataset, &errCode );

*/

if( errCode != 0 ){
uErrFatal("Unable to open the trace dataset %s", id_dataset );
}
/* Get misc. info about the dataset */
diskio_info_( &id_dataset, &ndfiles, &iswapends,
&trtotal, &samprat, &numsmp, &nth, &maxdtr,
&maxatr, &ipsort, &ipkey, &iskey, &idtyp, &idomain,
&ntraces, &igeom_match, &itrno_valid, &npriorf, &softrlp,
&georlsp );

/*
/*
/*
/*
/*

Set up the trace headers (this will cause a bunch of calls to


HDR_ADD, creating all of the header entries that were found in
the dataset). Complete header description info (list of names,
format, length, etc) is now available using the same in-line
executive header subroutines.
diskio_thdr_setup_( &id_dataset, &errCode );
if( errCode != 0 ){
uErrFatal("Error setting up trace headers for dataset.");
}

*/
*/
*/
*/
*/

/* Get the index of CDP */


if( hdrExists("CDP") ){
ih_cdp = hdrIndex("CDP");
}
else{
uErrFatal("Primary key header CDP does not exist in the data .");
}
/* Allocate buffers for a trace and a trace header */
trace = (float*)malloc( numsmp * sizeof(float));
ihdr
= (int*)malloc( nth * sizeof(float));
if( trace == NULL || ihdr == NULL ){
uErrFatal("Error allocating memory for trace and header.");
}
/* Call the routine that does the actual work */
stand_alone_work( trace, ihdr, ih_cdp, id_dataset, trtotal );
/* Close the dataset */
diskio_close_( &id_dataset );
/* notify the system of a normal completion */
u_comp_normal_();
}

Other Docs

Known Problems

poststack.c487

Developers Programming Guide

void stand_alone_work( float *trace, int *ithdr, int ih_cdp,


int id_dataset, int itrtotal )
{
/* local variables */
int errCode, j, trNum;
/* loop over the dataset trace numbers, they range from 1 to itrtotal. */
for( j = 1; j <= itrtotal; j++ ){
/* .. Read each trace using its relative position within the file by inputting */
/* .. a negative value for the trace number. See docs on diskio_get_tr. */
trNum = -j;
diskio_get_tr_( &id_dataset, &trNum, ithdr, trace, &errCode );
if ( errCode != 0 ){
printf("*** ERROR *** %d %d", j, errCode );
}
else{
printf("CDP= %d\n", ithdr[ih_cdp] );
}
}
}

Other Docs

Known Problems

vel_io.f488

Developers Programming Guide

vel_io.f
C ..... This is a stand alone program that shows examples on inputting and
C ..... outputting velocities to the ProMAX database
PROGRAM VEL_IO

&
&

IMPLICIT NONE
CHARACTER CX_DESC*8, CY_DESC*8, CZ_DESC*8, CTABLE_DESC*128,
CLABEL*8, CREPLY*1, CDESC*128
INTEGER MODE, IHANDLE, NFUNCTIONS, J, IERR, IRETURN, I,
LX_NAM, LX_DSC, NTABLES, ISELECT, NUMSMP, IDUMB
REAL X, SAMPRAT, RCDP, TIMEIN
LOGICAL WRITE_TABLE
CHARACTER CAREA(16), CLINE(16), CTBLTYPE(3)

C ..... Normally you would not want these to be hard-dimensioned arrays


INTEGER ICDP(100), NPAIRS(100), IMOD_TIMES(25)
REAL TIME(100,100), VEL(100,100), VELARR(5000)
CHARACTER COWNERS(32,25), CTBLNAMES(144,25)
C ..... See what the user wants to do
WRITE (*,*)
WRITE (*,*) 'Read (1) or write (2) velocities'
READ (*,'(A1)') CREPLY
IF ( CREPLY .EQ. '1' ) THEN
WRITE_TABLE = .FALSE.
ELSE
WRITE_TABLE = .TRUE.
ENDIF
C ..... Call a crude function to let the user select an area and line.
C ..... Normally you would get this info from the packet file.
CALL DB_CHOOSE_AL( CAREA, CLINE, IRETURN )
C ..... If return status is not 0, act accordingly
IF ( IRETURN .EQ. 1 ) THEN
WRITE (*,*) 'No areas exist'
STOP
ELSEIF ( IRETURN .EQ. 2 ) THEN
C ......... User wants to quit
STOP
ENDIF
C ..... Initialize the area and line
CALL DB_INIT_LINE( CAREA, CLINE, IERR )
IF ( .NOT. WRITE_TABLE ) THEN
C ......... User wants to read a table.
C ......... Get a list of the tables. Normal applications don't have to
C ......... go fishing for this type of info, it is selected from the
C ......... menus (these routines don't appear in your manual).
C ......... First count the number of tables in the database
CALL U_STR2CARR( 'VEL', CTBLTYPE, 3 )

Other Docs

Known Problems

vel_io.f489

&
&

Developers Programming Guide

CALL DB_TBL_COUNT( CAREA, CLINE, CTBLTYPE, NTABLES,


LX_NAM, LX_DSC, IERR )
IF ( IERR .NE. 0 ) CALL U_ERR_FATAL(
'Error counting tables' )

C ......... Get the list of tables


CALL DB_TBL_LIST( CAREA, CLINE, CTBLTYPE, CTBLNAMES,
&
NTABLES, LX_NAM, LX_DSC, IMOD_TIMES, COWNERS, IERR )
C ......... Allow the user to select one
WRITE (*,*)
DO 90 J=1,NTABLES
CALL U_CARR2STR( CTBLNAMES(1,J), CLABEL, 8 )
CALL U_CARR2STR( CTBLNAMES(LX_NAM+1,J), CDESC, 128 )
WRITE (*,'(I2,1X,A8,1X,A60)') J, CLABEL, CDESC(1:60)
90
CONTINUE
WRITE (*,*)
WRITE (*,*) 'Please select one'
READ (*,'(I2)') ISELECT
CALL U_CARR2STR( CTBLNAMES(1,ISELECT), CLABEL, 8 )
ENDIF
IF ( WRITE_TABLE ) THEN
C ......... This is a totally new table
MODE = 1
C ......... Set the descriptions
CX_DESC = 'CDP
'
CY_DESC = 'TIME
'
CZ_DESC = 'VELOCITY'
CTABLE_DESC = 'Test input to velocity table'
C ......... Make a new table in memory
CALL TBL_INIT( MODE, CX_DESC, CY_DESC, CZ_DESC,
&
CTABLE_DESC, IHANDLE )
C ......... Hard-code some input velocities
NFUNCTIONS = 3
ICDP(1) = 511
ICDP(2) = 204
ICDP(3) = 562
NPAIRS(1) = 3
NPAIRS(2) = 5
NPAIRS(3) = 2
TIME(1,1) = 50.0
VEL(1,1) = 50.0
TIME(2,1) = 1000.0
VEL(2,1) = 1000.0
TIME(3,1) = 1950.0
VEL(3,1) = 1950.0
TIME(1,2) = 75.0
VEL(1,2) = 75.0

Other Docs

Known Problems

vel_io.f490

Developers Programming Guide

TIME(2,2) = 480.0
VEL(2,2) = 480.0
TIME(3,2) = 950.0
VEL(3,2) = 950.0
TIME(4,2) = 1510.0
VEL(4,2) = 1510.0
TIME(5,2) = 1975.0
VEL(5,2) = 1975.0
TIME(1,3) = 100.0
VEL(1,3) = 100.0
TIME(2,3) = 2000.0
VEL(2,3) = 2000.0
C ......... Loop over the functions, inputting them. You could also input
C ......... each time-velocity pair independently (NUMY=1 in TBL_ADD)
DO 100 J=1,NFUNCTIONS
C ............. X is the CDP in this case
X = FLOAT( ICDP(J) )
C ............. Add the data to the table
CALL TBL_ADD( IHANDLE, X, TIME(1,J), NPAIRS(J),
&
VEL(1,J), 1 )
100

CONTINUE

C ......... Close the table in memory (compress the buffers, etc.)


CALL TBL_END( IHANDLE )
C ......... Put the table into the database
CLABEL = 'VELTEST '
CALL DB_TBL_PUT( 'VEL', CLABEL, IHANDLE, IERR )
IF ( IERR .NE. 0 ) THEN
WRITE (*,*) 'IERR= ', IERR
CALL U_ERR_FATAL(
&
'Error putting velocity table into database' )
ENDIF

ELSEIF ( .NOT. WRITE_TABLE ) THEN


C ......... Get the chosen table from the database. Note that it goes
C ......... straight into a table structure.
CALL DB_TBL_GET( 'VEL', CLABEL, IHANDLE, IERR )
IF ( IERR .NE. 0 ) CALL U_ERR_FATAL(
&
'Error getting velocity table from database' )
C ......... Get some info on the table. We are after the number of functions
CALL TBL_U_INFO( IHANDLE, CX_DESC, CY_DESC, CZ_DESC,
&
CTABLE_DESC, NFUNCTIONS )
C ......... Loop over the functions
DO 120 J=1,NFUNCTIONS
C ............. Pull
C ............. also
CALL
&

Other Docs

the time-velocity pairs out of the table. You could


pull each time-velocity pair independently.
TBL_IX_GET( IHANDLE, J, 100, 1, X, TIME(1,J),
NPAIRS(J), VEL(1,J), IERR )

Known Problems

vel_io.f491

Developers Programming Guide

IF ( IERR .NE. 0 .OR. NPAIRS(J) .LT. 1 )


CALL U_ERR_FATAL(
'Error getting info from velocity table' )

&
&

C ............. Show the user what was in the table


WRITE (*,*)
WRITE (*,*) 'CDP= ', X
DO 110 I=1,NPAIRS(J)
WRITE (*,*) J, TIME(I,J), VEL(I,J)
110
CONTINUE
120

CONTINUE

C ......... Here is an example of interpolating a velocity function


WRITE (*,*)
WRITE (*,*)
&
'Do you want to interpolate a velocity function (y/n)?'
READ (*,'(A1)') CREPLY
IF ( CREPLY .EQ. 'Y' .OR. CREPLY .EQ. 'y' ) THEN
WRITE (*,*)
WRITE (*,*) 'Enter the CDP'
READ (*,'(F10.0)') RCDP
WRITE (*,*) 'Enter the sample rate (ms)'
READ (*,'(F10.0)') SAMPRAT
WRITE (*,*) 'Enter the number of samples'
READ (*,'(I10)') NUMSMP
CALL INT_VEC( IHANDLE, 0, 0, RCDP, 0.0, SAMPRAT, NUMSMP,
VELARR, IDUMB )

&

C ............. Increment by 10 or we will be here all day


DO 130 I=1,NUMSMP,10
WRITE (*,*) I, VELARR(I)
130
CONTINUE
ENDIF
C ......... Here is an example of interpolating at a particular time
WRITE (*,*)
WRITE (*,*)
&
'Do you want to interpolate at a particular time (y/n)?'
READ (*,'(A1)') CREPLY
IF ( CREPLY .EQ. 'Y' .OR. CREPLY .EQ. 'y' ) THEN
WRITE (*,*)
WRITE (*,*) 'Enter
READ (*,'(F10.0)')
WRITE (*,*) 'Enter
READ (*,'(F10.0)')

the CDP'
RCDP
the time (ms)'
TIMEIN

CALL INT_GET( IHANDLE, 0, 0, RCDP, TIMEIN, VELARR(1),


IDUMB )

&

WRITE (*,*) VELARR(1)


ENDIF

Other Docs

Known Problems

vel_io.f492

Developers Programming Guide

ENDIF
END

Other Docs

Known Problems

vel_io.f493

Other Docs

Developers Programming Guide

Known Problems

vel_io.f494

Other Docs

Developers Programming Guide

Known Problems

495

Developers Programming Guide

Appendix: IPC Tool Examples

This appendix describes IPC (interprocess communication)


tools.

Topics covered in this appendix:

Other Docs

IPC Menu Code


IPC C Code
IPC FORTRAN Code
amp_ratio Menu Code
ampRatio C Code
amp_ratio FORTRAN Code

Known Problems

IPC Menu Code496

Developers Programming Guide

IPC Menu Code


;

This is a comment

Sample menu for executing a IPC tool

'(
name: stand_alone
label: "Test IPC tool"
value_tab: 55
;These are normal menu parameters.....
parameter: program
text: "Program executable name"
type: edit:
type_desc: (30 100 2 " Example: /usr/stof/promax/sa/my_prog )
value: "/usr/stof/exe/test_sa.exe"
mouse_text: "Type path name of program executible. If the path
doesn't start with a /, the main ProMAX executable directory is used."
parameter: max_freq
text: "Maximum frequency"
type: typein:
type_desc: ( real: 7 1.0e-5 nil )
value: 100.0
mouse_text: "Enter maximum frequency in the data."
parameter: DEBUG
text: "Debug mode?"
type: boolean:
value: nil
mouse_text: "To debug program, enter YES.
debug the program yourself"

You will have to

exec_data: ("SOCKET_TOOL"
("GENERAL"
; The program parameter is the executible name of your IPC tool.
; You can hard code by specifying:
;
("program" implicit: "/home/stof/exe/mySocketTool.exe" )
("program"
implicit: (value 'program))
("DEBUG"
implicit: ( if (value 'debug) 3 0) )
; Put your other program parameters below here
("max_freq"
implicit: (value 'max_freq ))
)
)
rules: (
; put your normal rules in
)
)

Other Docs

Known Problems

IPC C Code497

Developers Programming Guide

IPC C Code
#include
#include
#include
#include
#include

<stdio.h>
<math.h>
"cglobal.h"
"cpromax.h"
"cSocketTool.h"

main(int ac,char **av)


{
int i,nt,nth,nx,iMyHeader ;
float dt;
int *ihead;
float *rhead, *trace;
int ivalue;
float value, value2;
char *mfile;
/*
Open the packet file, get area & line, open database */
initStandAlone(ac,av, "SOCKET_TOOL");
/****
Establish connection with server module in the processing flow
All the global parameters are transferred in from the Executive.
They are accessible through the normal C global structures
(i.e. globalRuntime) or the normal FORTRAN common blocks (i.e.
GLOBAL_RUNTIME)
***/
stConnectToServer();
/*

Start initialization portion of program

*/

stSetToolName("Simple test program for ProMAX IPC tool");


/* This name is stored and printed out before messages printed
with stErrMessage(). This helps the user determine where
mesages in the printout are coming from.
*/

/* Access packet file, using standalone parameter subroutines */


exParGetFloat("max_frequency", &value);
/* read global variables
dt=globalRuntime->samprat;
nt= globalRuntime->numsmp;
nx= globalRuntime->maxdtr;
nth= globalRuntime->nth;

see cglobal.h */
/* Sample rate */
/* Number of samples per trace */
/* Number of traces per ensemble */
/* Length of trace header in
words */

/* allocate necessary space in program */


trace= (float *) malloc( nt*sizeof(float));
ihead= (int *)(rhead= (float *) malloc( nth*sizeof(float)) );
/* Manipulate headers */
if (!stHdrExists("MY_header") ) {
/* Does this header exist
/* Add Header with arbitrary char string */
iMyHeader=stHdrAdd("MY_header","Description of what
MY_header is",1,HDRINT);

Other Docs

*/

Known Problems

IPC C Code498

Developers Programming Guide

} else { /* Header exists. Get the index. */


/* What is the location of the header */
iMyHeader=stHdrIndex("MY_header");
}
/*
In future releases you will also be able to use the more standard
routines: hdrExists(), hdrAdd(), hdrIndex(), etc. */
/*

Print the location of headers in the trace header array */


stErrMessage("Header locations: IEOJ=%d IEND_ENS=%d,
MY_header: %d",
STDHDR(ieoj),STDHDR(iend_ens), iMyHeader);
/* STDHDR(ieoj) lets you access commonly used headers through a
global structure. */
/* Change global parameters if we wish
globalRuntime->samprat*= 1.1 ;
globalRuntime->numsmp/= 2;
*/
/**
Up until now, we have been communicating with a master
init_stand_alone_module() in the ProMAX Executive. By calling
stEndInitialization(), this sends the possibly altered globalRuntime
parameters back to the Executive, allows the init_stand_alone module
to return, and begins the exec_stand_alone_module() which passes and
receives the traces from this stand alone program.
We can no longer
make calls to stHdrIndex(), sHdrAdd(), etc., nor can we change the
globalRuntime structure.
**/
stEndInitialization();
/* Read in a trace. Traces are transferred from
the proper location in the ProMAX flow. Ensembles of traces are
read in with stGetEnsemble().
*/
while (stGetTrace(trace,ihead) ) {
/*

access header information */


stErrMessage("CDP: %d, offset: %g", ihead[STDHDR(icdp)],
rhead[STDHDR(ioffset)] );
do_work_on_trace(trace,ihead);

/* Write out a trace back to the ProMAX flow.


Traces are transferred back to the proper location in the ProMAX flow.
Ensembles of traces are written with stPutEnsemble().
Note that stGetTrace() can be called in any order with stPutTrace().
*/
stPutTrace(trace,ihead);
}

/*

end while( stGetTrace() loop

*/

/* Perform cleanup operations here */


stCloseSocketLink();
}
do_work_on_trace()
{
}

Other Docs

Known Problems

IPC FORTRAN Code499

Developers Programming Guide

IPC FORTRAN Code


C
C
C
C
C
C
C
C
C

/* this is the C "wrapper" that passes command


line args to FORTRAN */
void main( argc, argv )
int argc;
char **argv;
{
socket_tool_( &argc, argv[1] );
}

SUBROUTINE SOCKET_TOOL( NARGS, CINPUT )


IMPLICIT NONE
INTEGER NARGS
CHARACTER CINPUT*128, CPACKET_FILE*128, CAREA*16, CLINE*16
INTEGER ID_PACKET
C ..... Include ProMAX global declarations
#include "global.inc"
#include "header.inc"
C ..... Include the file that allows use of the "space array" and memory
C ..... management routines.
#include "mem.inc"
C ...

#include "socket_tool.inc"

C ..... Include file with error definitions


#include "hdr_err.inc"
#include "db_err.inc"
INTEGER IERR, LENGTH, IFORMAT, NCHARS, EOF_REACHED,
&
NT, NTH, NX, MY_HEADER
CHARACTER CDESC_HDR*32, CDESC_DB*80, CGATENAME*8, CPRIM_KEY*8,
&
CSCND_KEY*8, CTABLE_DESC*128, CZ_DESC*8, CMFILE*80
INTEGER IX_HEADER, IX_TRACE, IVALUE, IH_MY_HEADER, IDUM
REAL VALUE, VALUE2
INTEGER ITHDR(1000), LOC_TRC, ISAVE, IMIN_SAMP, IMAX_SAMP
REAL TRACE(10000), RTHDR(1000), DT,
&
PKEYVAL, SKEYVAL, TGATE(2)
EQUIVALENCE (ITHDR,RTHDR)
C ....

These first few lines are typical of a stand alone program

IF ( NARGS .LT. 2 ) THEN


C ......... Nothing was entered on the command line
CALL U_ERR_FATAL( 'Packet file must be specified' )
ENDIF
C ..... Load the character ARRAY into a character STRING.
C
Be sure that you understand the difference.
CALL U_CARR2STR( CINPUT, CPACKET_FILE, 128 )

Other Docs

Known Problems

IPC FORTRAN Code500

C ..... Open
CALL
&
IF (
&
C
C
C
C

.....
.....
.....
.....

C
C
C
C

.....
.....
.....
.....

Developers Programming Guide

the parameter packet file, get back the ID, area, and line
PKT_OPEN_LOAD( CPACKET_FILE, 'SOCKET_TOOL
', ID_PACKET,
CAREA, CLINE )
ID_PACKET .EQ. 0 ) CALL U_ERR_FATAL(
'Unable to open packet file' )

Initialize the database for this area and line. Note that CAREA
and CLINE are character arrays, not character strings. This
must be called in order for access to parameter files in the
database.
CALL DB_INIT_LINE( CAREA, CLINE, IERR )
IF ( IERR .NE. 0 ) THEN
CALL REPORT_DB_ERR( IERR )
CALL ST_ERR_FATAL( 'Unable to initialize the database' )
ENDIF

Establish connection with server module in the processing flow


All the global parameters are transferred in from the Executive.
They are accessible through the GLOBAL_RUNTIME common
block members
CALL ST_CONNECT_TO_SERVER(ID_PACKET)

C ..... Give IPC tool a name


CALL ST_SET_TOOL_NAME('FORTRAN IPC tool example')
C ..... This name is stored and printed out before messages printed
C ..... with stErrMessage(). This helps the user determine where
C ..... mesages in the printout are coming from.
C ..... Use standard Executive parameter input routines
CALL EX_GETPARM( 'max_freq', 1, VALUE )

C ..... Access global parameters as you would normally


DT = SAMPRATz
NT= NUMSMPz
NX= MAXDTRz
NTH= NTHz
C ....
C ....

Create headers using functions similar to that in the Executive


Note the name change with the "ST_" prefix
CDESC_HDR = 'Description of what MY_header is'
CALL ST_HDR_ADD( 'MY_header', CDESC_HDR, 1, INT4pz,
&
IH_MY_HEADER, IERR )
IF ( IERR .NE. 0 ) THEN
IF ( IERR .EQ. IERR_HDR_EXSTpz ) THEN
C ................. Error routines start with ST_
CALL ST_ERR_WARN(
&
'RATIOMAX already exists in header' )
CALL ST_HDR_NAMINFO( 'MY_header ', CDESC_HDR, LENGTH, IFORMAT,
&
IH_MY_HEADER, IERR )
ELSE
CALL ST_ERR_FATAL( 'Error adding header entry' )
ENDIF
ENDIF

&

CALL ST_HDR_NAMINFO( 'CDP


IDUM, IERR )

Other Docs

', CDESC_HDR, LENGTH, IFORMAT,

Known Problems

IPC FORTRAN Code501

Developers Programming Guide

IF ( IERR .NE. 0 ) THEN


CALL ST_ERR_FATAL( 'Header CDP does not exist.')
ENDIF
C ....
C

In future releases you will also be able to use the


more standard routines HDR_ADD etc
WRITE(*,*) 'EOJ header pos: ', IEOJz,
'END_ENS header pos: ',IEND_ENSz,
'MY_HEADER pos:', IH_MY_HEADER

&
&
C
C
C
C
C

.....
.....
.....
....

Reserve a buffers for the trace and headers


note how the memory is passed to the subroutine
DO_WORK_ON_TRACE().
We could just as well have used the static memory
buffer "TRACE()"
CALL MEM_RESBUFF( NT, IX_TRACE, IERR )
CALL MEM_RESBUFF( NTH, IX_Header, IERR )

C ..... Possibly change the global parameters


SAMPRATz= SAMPRATz*1.1
NUMSMPz= NUMSMPz/2
C ....
C

End initialization phase. this subroutine send back the


possibly altered global parameters back to the Executive
CALL ST_END_INIT()

C ....

loop over traces

C ..... prime the loop


CALL ST_GET_TRACE(RSPACEz(IX_TRACE), RSPACEz(IX_HEADER),
&
RSPACEz(IX_HEADER), EOF_REACHED)
DO WHILE ( EOF_REACHED .EQ. 0 )

C ..... Pass the buffers off to a routine where the real work is done
CALL DO_WORK_ON_TRACE( RSPACEz(IX_TRACE), RSPACEz(IX_HEADER) ,
& RSPACEz(IX_HEADER) )
C ....

send the trace back to the Executive


CALL ST_PUT_TRACE(RSPACEz(IX_TRACE), RSPACEz(IX_HEADER))

C ..... Get the next trace


CALL ST_GET_TRACE(RSPACEz(IX_TRACE), RSPACEz(IX_HEADER),
&
RSPACEz(IX_HEADER), EOF_REACHED)
C ....

end while loop over traces


ENDDO

C ..... This is where the normal clean up phase goes


C ...... Close stand alone program in the normal fasion
C ..... This routine also closes the packet file and calls U_COMP_NORMAL
CALL ST_CLOSE_SOCKET_LINK()
END

Other Docs

Known Problems

IPC FORTRAN Code502

Developers Programming Guide

SUBROUTINE DO_WORK_ON_TRACE( TRACE, IHEADER , RHEADER)


IMPLICIT NONE
#include "header.inc"
INTEGER TRACE(1), IHEADER(1)
REAL RHEADER(1)
C ....
&

Write certain header locations


WRITE(*, * ) 'CDP: ', IHEADER(ICDPz),
'Offset: ', RHEADER(IOFFSETz)
END

Other Docs

Known Problems

amp_ratio Menu Code503

Developers Programming Guide

amp_ratio Menu Code


This is a more involved example that accesses tables and the database.
'(
name: AMP_RATIO
label: "Test FORTRAN amplitude Ratio"
value_tab: 35
parameter: GATELEN
text: "Amplitude gate length"
type: typein:
type_desc: ( real: 7 1.0e-5 nil )
value: 100.0
mouse_text: "Enter the sliding gate length used to compute amplitude
ratios."
parameter: time_gate_opt
text: "Confine the maximum?"
type: boolean:
value: nil
mouse_text: "Select 'Yes' if you wish to use a gate to constrain the
search for the maximum in the amp ratio."
parameter: GATENAME
text: " Select gate parameter file"
type: function:
type_desc: ((parm_list "GAT") parms)
value: "INVALID"
selected_item: "** No Parameter File Selected **"
mouse_text: "Use Mouse Button 1 to select a gate parameter file from
the parameter file menu."
parameter: LOAD_HDR
text: "Load the results into the header?"
type: boolean:
value: t
mouse_text: "Select 'Yes' if you wish to load the maximum of the amp
ratio and its time into the trace header."
parameter: LOAD_DB
text: "Load the results into the database?"
type: boolean:
value: t
mouse_text: "Select 'Yes' if you wish to load the maximum of the amp
ratio and its time into the database."
parameter: DEBUG
text: "Do you want to execute the program from dbx?"
type: boolean:
value: t
mouse_text: "If 'Yes', you must execute this program yourself from
dbx."
exec_data:
("SOCKET_TOOL"

Other Docs

Known Problems

amp_ratio Menu Code504

;
;

Developers Programming Guide

("GENERAL"
The following four variables are needed by init_stand_alone() to
run the stand alone program. They are described below.
("program"
implicit: "/home/mark/amp_ratio.exe" )
("machine"
implicit: "" )
("DEBUG"
implicit: ( if (value 'DEBUG) 3 1) )
variables after here are user parameters
("GATELEN"
implicit: (value 'GATELEN))
("GATENAME" implicit: ( if (value 'time_gate_opt)
(value 'GATENAME) "NO__GATE" ))
("LOAD_HDR" implicit: ( if (value 'LOAD_HDR) 1 0 ) )
("LOAD_DB"
implicit: ( if (value 'LOAD_DB) 1 0 ) )
)
)

rules: (
(rule1 ( value 'time_gate_opt )
(do_show 'GATENAME) (do_not_show 'GATENAME))
)
)

Other Docs

Known Problems

ampRatio C Code505

Developers Programming Guide

ampRatio C Code
/* include ProMAX prototypes and globals */
#include "cpromax.h"
#include "cglobal.h"
#include "cSocketTool.h"
void
amp_ratio_work (float *trace, float *scratch, int nsams, int ngate,
int imin_samp, int imax_samp, float samprate, float *ratio_max, float
*ratio_time);
main (int ac, char **av)
{
int
ngate, ih_ratio_max, ih_ratio_time, load_hdr, load_opf, id_max,
id_time, ih_traceno, use_gate, itbl_handle, ih_pkey, ih_skey, iformat_pkey,
iformat_skey;
float
*scratch;
void
*gate_tbl;
void
*opf_trc, *opfPtr1, *opfPtr2;
float
char

gatelen;
*cgatename;

float
int
float

*trace;
*ithdr;
*rthdr;

initStandAlone (ac, av, "SOCKET_TOOL");


stConnectToServer ();
stSetToolName ("Amplitude Ratio");
/* get the gate length */
gatelen = -1.0;
uParGetFloat ("GATELEN", &gatelen);
/* convert the gate length from time to samples */
ngate = (int) (gatelen / globalRuntime->samprat + 0.5);
/* check for reasonable input */
if (ngate < 1 || ngate * 2 + 1 > globalRuntime->numsmp)
stErrFatal ("Gate length is illegal");
/* See if the user wants to confine the maximum to fall within a gate */
use_gate = FALSE;
uParGetString ("GATENAME", &cgatename);
if (strcmp (cgatename, "") != 0 && strcmp (cgatename, "NO_GATE") != 0
&& strcmp (cgatename, "NO__GATE") != 0) {
use_gate = TRUE;
/* Get the gate from the database */
gate_tbl = tblFromDatabase ("GAT", cgatename);
if (gate_tbl == NULL)

Other Docs

Known Problems

ampRatio C Code506

Developers Programming Guide

stErrFatal ("Cannot open time gate %s !!", cgatename);


if (tblCountZ(gate_tbl) != 2)
stErrFatal ("invalid gate (Gate must have an upper and lower gate!)");
/* We will need the index of the primary and secondary key

*/

ih_pkey = stHdrIndex (tblDescX(gate_tbl) );


if (!ih_pkey)
stErrFatal ("The primary key of the time gate (%s) is not in the
header!", tblDescX(gate_tbl) );
ih_skey = stHdrIndex (tblDescY(gate_tbl) );
if (!ih_skey)
stErrFatal ("The secondary key of the time gate is (%s) is not in the
header!", tblDescY(gate_tbl) );
}
/* See if the user wants to load the results into the trace header
load_hdr = 0;
uParGetInt ("LOAD_HDR", &load_hdr);
if (load_hdr) {
/* Add new trace header entries

*/

*/

if (stHdrExists ("RATIOMAX")) {
if (stHdrFormat ("RATIOMAX") == HDRFLOAT)
stErrWarn ("RATIOMAX header already exists!");
else
stErrFatal ("RATIOMAX header already exists but is of wrong type!");
}
else {
ih_ratio_max = stHdrAdd ("RATIOMAX", "Time of amp ratio maximum", 1,
HDRFLOAT);
if (ih_ratio_max < 0) {
/* This should virtually never happen. */
stErrFatal ("Error adding header RATIOMAX");
}
}
if (stHdrExists ("RATIOTIM")) {
if (stHdrFormat ("RATIOTIM") == HDRFLOAT)
stErrWarn ("RATIOTIM header already exists!");
else
stErrFatal ("RATIOTIM header already exists but is of wrong type!");
}
else {
ih_ratio_time = stHdrAdd ("RATIOTIM", "Time of amp ratio maximum", 1,
HDRFLOAT);
if (ih_ratio_time < 0) {
/* This should virtually never happen. */
stErrFatal ("Error adding header RATIOTIM");
}
}
}
/* See if the user wants to load the results into the database */
load_opf = 0;

Other Docs

Known Problems

ampRatio C Code507

Developers Programming Guide

uParGetInt ("LOAD_DB", &load_opf);


if (load_opf) {
ierr;
/* Open the database to store the amp ratio information against trace */
if (globalRuntime->itrno_valid)
stErrFatal ("Cannot load data into the TRC order without valid trace
numbers (geom assigned?)");
int

if (!stHdrExists ("TRACENO")) {
stErrFatal ("TRACENO not found in header");
}
/* Lock the TRC order since we will be writing to it

*/

if (!opfExists ("TRC"))
stErrFatal ("TRC database does not exist.");
opf_trc = opfLock ("TRC");
if (opf_trc==NULL )
stErrFatal ("Could not lock TRC database order.");
/* Create the new entries in the database
*/
if (!opfParmExists (opf_trc, "F_B_PICK", "RATIOMAX")) {
ierr = opfParmCreate (opf_trc, "F_B_PICK",
"RATIOMAX", "Maximuma value of amp ratio", 1, PARFLOAT);
if (ierr != 0)
stErrFatal ("Error creating database entry");
}
if (!opfParmExists (opf_trc, "F_B_PICK", "RATIOTIM")) {
ierr = opfParmCreate (opf_trc, "F_B_PICK", "RATIOTIM",
"Time of amp ration maximum", 1, PARFLOAT);
if (ierr != 0)
stErrFatal ("Error creating database entry");
}
/* Initialize the token for buffered database I/O

*/

opfPtr1 = opfInitBufPut (opf_trc, "F_B_PICK", "RATIOMAX");


opfPtr2 = opfInitBufPut (opf_trc, "F_B_PICK", "RATIOTIM");
}
/* reserve memory */
trace = (float *) malloc (globalRuntime->numsmp * sizeof (float));
ithdr = (int *) malloc (globalRuntime->nth * sizeof (int));
rthdr = (float *) ithdr;
/* Reserve a scratch buffer that we will need in exec phase */
scratch = (float *) malloc (globalRuntime->numsmp * sizeof (float));
stEndInitialization ();
/* Loop while traces still exist */
while (stGetTrace (trace, ithdr)) {
int
loc_trc, ierr, isave, imin_samp, imax_samp;
float
ratio_max, ratio_time, pkeyval, skeyval, tgate[2];

if (use_gate) {
/* Interpolate the gate times from the table */

Other Docs

Known Problems

ampRatio C Code508

Developers Programming Guide

if (tblInterpXY (gate_tbl, rthdr[ih_pkey],


rthdr[ih_skey], tgate)) {
stErrFatal ("Error interpolating time gate");
}
}
else {
/* use entire trace */
tgate[0] = 0.0;
tgate[1] = (globalRuntime->numsmp - 1) * globalRuntime->samprat;
}
/* Convert the time gate values to samples */
imin_samp = tgate[0] / globalRuntime->samprat + 0.5;
imax_samp = tgate[1] / globalRuntime->samprat + 0.5;
/* Convert the time gate values to samples */
imin_samp = MAX (imin_samp, 0);
imin_samp = MIN (imin_samp, globalRuntime->numsmp - 1);
imax_samp = MAX (imax_samp, 0);
imax_samp = MIN (imax_samp, globalRuntime->numsmp - 1);
if (imin_samp > imax_samp) {
int
isave;
/* assume that they were menat to be reversed */
isave = imin_samp;
imin_samp = imax_samp;
imax_samp = isave;
}
/* Pass the buffers off to a routine where the real work is done */
amp_ratio_work (trace, scratch, globalRuntime->numsmp,
ngate, imin_samp, imax_samp, globalRuntime->samprat,
&ratio_max, &ratio_time);
if (load_hdr == 1) {
/* Load the values into the header */
rthdr[ih_ratio_max] = ratio_max;
rthdr[ih_ratio_time] = ratio_time;
}
if (load_opf) {
/* Load the values into the database

*/

loc_trc = ithdr[STDHDR (itraceno)];


if (loc_trc != INULL) {
opfBufPutFloat (opfPtr1, loc_trc, ratio_max);
opfBufPutFloat (opfPtr2, loc_trc, ratio_time);
}
}
stPutTrace (trace, ithdr);
}
/* End loop over traces. */

if (load_opf) {
/* Flush the buffers for buffered database I/O Note that errors ony give
rise to warnings in cleanup phase. Also note that the "location" is now
0.
*/

Other Docs

Known Problems

ampRatio C Code509

Developers Programming Guide

if (opfCloseBufPut (opfPtr1) != 0)
stErrWarn ("Error loading data
}
if (opfCloseBufPut (opfPtr2) != 0)
stErrWarn ("Error loading data
}
opfClose (opf_trc);

{
into database.");
{
into database.");

}
stCloseSocketLink ();
}
/**
C--------------------------------------------------------------------C
C Actual work routine
C
C--------------------------------------------------------------------**/
void
amp_ratio_work (float *trace, float *scratch, int nsamps, int ngate,
int imin_samp, int imax_samp, float samprate, float
*ratio_max, float *ratio_time)
{
int
i, istart, iend, ind_max;
float
sum_above, sum_below, rabove, rbelow;
/* Set the starting and end of the zone of interest
istart = 0 - ngate;
iend = nsamps + ngate;
/* Sum the first two gates
sum_above = 0.0;
rabove = 0.0;

*/

*/

sum_below = 0.0;
rbelow = 0.0;
for (i = istart + ngate; i < istart + ngate * 2; i++)
if (i >= 0 && i < nsamps && trace[i] != 0.0) {
sum_below = sum_below + fabs (trace[i]);
rbelow = rbelow + 1.0;
}
for (i = istart + ngate; i < iend - ngate; i++) {
/* Compute the ratio */
if (sum_above > 0.0 && rabove > 0.0 && rbelow > 0.0) {
scratch[i] = (sum_below / rbelow) / (sum_above / rabove);
}
else {
scratch[i] = 0.0;
}
/* Drop a sample from each gate and add the next one
if (i - ngate >= 0) {

Other Docs

*/

Known Problems

ampRatio C Code510

Developers Programming Guide

sum_above = sum_above - fabs (trace[i - ngate]) + fabs (trace[i]);


}
else if (trace[i] != 0.0) {
sum_above = sum_above + fabs (trace[i]);
rabove = rabove + 1.0;
}
if (i + ngate + 1 < nsamps) {
sum_below = sum_below - fabs (trace[i + 1])
+ fabs (trace[i + ngate + 1]);
}
else if (i + 1 < nsamps && trace[i + 1] != 0.0) {
sum_below = sum_below - fabs (trace[i + 1]);
rbelow = rbelow - 1.0;
}
}
/* Put the final results in place. Note that we have not handled the edge
problem, we have simply made the function undefined */
for (i = 0; i < nsamps; i++) {
trace[i] = scratch[i];
}
/* Find the maximum of the ratio function */
*ratio_max = trace[imin_samp];
ind_max = imin_samp;
for (i = imin_samp; i < imax_samp; i++) {
if (trace[i] > *ratio_max) {
ind_max = i;
*ratio_max = trace[i];
}
}
/* Covert the index of the maximum to time */
*ratio_time = (float) (ind_max) * samprate;
}

Other Docs

Known Problems

amp_ratio FORTRAN Code511

Developers Programming Guide

amp_ratio FORTRAN Code


C
C
C
C
C
C
C
C
C

/* this is the C "wrapper" that passes command


line args to FORTRAN */
void main( argc, argv )
int argc;
char **argv;
{
socket_tool_( &argc, argv[1] );
}

SUBROUTINE SOCKET_TOOL( NARGS, CINPUT )


IMPLICIT NONE
INTEGER NARGS
CHARACTER CINPUT*128, CPACKET_FILE*128, CAREA*16, CLINE*16
INTEGER ID_PACKET
#include "global.inc"
C ..... Include file with error definitions
#include "hdr_err.inc"
#include "db_err.inc"
C ..... Include the file that allows use of the "space array" and memory
C ..... management routines.
#include "mem.inc"

&

&

&
&
&
&
&

CHARACTER CDESC_HDR*32, CDESC_DB*80, CGATENAME*8, CPRIM_KEY*8,


CSCND_KEY*8, CTABLE_DESC*128, CZ_DESC*8
REAL TRACE(10000), RTHDR(1000), RATIO_MAX, RATIO_TIME,
PKEYVAL, SKEYVAL, TGATE(2), GATELEN, RDUMMY(6)
EQUIVALENCE (ITHDR,RTHDR)
INTEGER NGATE, IX_SCRATCH, LENSAVED, IH_RATIO_MAX,
IH_RATIO_TIME, LOAD_HDR, LOAD_DB, ID_MAX, ID_TIME,
IH_TRACENO, IKEY_TRC, ITBL_HANDLE, IH_PKEY, IH_SKEY,
IFORMAT_PKEY, IFORMAT_SKEY, IERR, LENGTH, IFORMAT,
NCHARS, EOF_REACHED, IDUMMY(3), NTIMES,
ITHDR(1000), LOC_TRC, ISAVE, IMIN_SAMP, IMAX_SAMP

LOGICAL USE_GATE
IF ( NARGS .LT. 2 ) THEN
C ......... Nothing was entered on the command line
CALL ST_ERR_FATAL( 'Packet file must be specified' )
ENDIF
C ..... Load the character ARRAY into a character STRING.
C
Be sure that you understand the difference.
CALL U_CARR2STR( CINPUT, CPACKET_FILE, 128 )
C ..... Open the parameter packet file, get back the ID, area, and line

Other Docs

Known Problems

amp_ratio FORTRAN Code512

&
&
C
C
C
C

.....
.....
.....
.....

Developers Programming Guide

CALL PKT_OPEN_LOAD( CPACKET_FILE,'SOCKET_TOOL


CAREA, CLINE )
IF ( ID_PACKET .EQ. 0 ) CALL ST_ERR_FATAL(
'Unable to open packet file' )

',ID_PACKET,

Initialize the database for this area and line. Note that CAREA
and CLINE are character arrays, not character strings. This
must be called in order for access to parameter files in the
database.
CALL DB_INIT_LINE( CAREA, CLINE, IERR )
IF ( IERR .NE. 0 ) THEN
CALL REPORT_DB_ERR( IERR )
CALL ST_ERR_FATAL( 'Unable to initialize the database' )
ENDIF

C ..... Open connect to Executive


CALL ST_CONNECT_TO_SERVER(ID_PACKET)
C ..... Give IPC tool a name
CALL ST_SET_TOOL_NAME('FORTRAN amplitude ratio')
C ..... Set a default that is illegal (in case there is a menu problem)
GATELEN = -1.0
C
C
C
C

.....
.....
.....
.....

Call for the input parameter by name. Note the padding


in the character constant. It is the programmers
responsibility to provide the correct type of
return argument. Same as Executive!!
CALL EX_GETPARM( 'GATELEN ', 1, GATELEN )

C ..... Convert the gate length to samples.


NGATE = NINT( GATELEN / SAMPRATz )

Globals are available.

C ..... Check for reasonable input


IF ( NGATE .LT. 1 .OR. NGATE*2+1 .GT. NUMSMPz ) THEN
CALL ST_ERR_FATAL( 'Gate length is illegal' )
ENDIF
C ..... See if the user wants to confine the maximum to fall within a gate
USE_GATE = .FALSE.
CGATENAME = '
'
CALL EX_CGETPARM( 'GATENAME', 1, CGATENAME, NCHARS )
IF ( CGATENAME .NE. '
'
&
.AND. CGATENAME .NE. 'NO__GATE' ) THEN
C ......... Something was specified
USE_GATE = .TRUE.
C ......... Get the gate from the database
CALL DB_TBL_GET( 'GAT', CGATENAME, ITBL_HANDLE, IERR )
IF ( IERR .NE. 0 ) THEN
CALL REPORT_DB_ERR( IERR )
CALL ST_ERR_FATAL(
&
'Cannot open time gate ' //CGATENAME )
ENDIF
C ......... Get info on the gate table
CALL TBL_INFO( .TRUE., ITBL_HANDLE, CPRIM_KEY, CSCND_KEY,
&
CZ_DESC, CTABLE_DESC, IDUMMY(1), IDUMMY(2), IDUMMY(3),

Other Docs

Known Problems

amp_ratio FORTRAN Code513

&
&

Developers Programming Guide

NTIMES, RDUMMY(1), RDUMMY(2), RDUMMY(3), RDUMMY(4),


RDUMMY(5), RDUMMY(6) )

C ......... There had better be two time values (upper and lower gate)
IF ( NTIMES .NE. 2 ) CALL ST_ERR_FATAL(
&
'Invalid gate (must have an upper and lower gate)' )
C ......... We will need the index of the primary and secondary key
C ......... Note: ST_ appended to header calls
CALL ST_HDR_NAMINFO( CPRIM_KEY, CDESC_DB, LENGTH,
&
IFORMAT_PKEY,
&
IH_PKEY, IERR )
IF ( IERR .NE. 0 ) CALL ST_ERR_FATAL(
&
'The primary key of the time gate (' //CPRIM_KEY
&
//') is not in the header' )

&
&
&
&

CALL ST_HDR_NAMINFO( CSCND_KEY, CDESC_DB, LENGTH,


IFORMAT_SKEY,
IH_SKEY, IERR )
IF ( IERR .NE. 0 ) CALL ST_ERR_FATAL(
'The secondary key of the time gate (' //CSCND_KEY
//') is not in the header' )
ENDIF

C ..... See if the user wants to load the results into the trace header
LOAD_HDR = 0
CALL EX_GETPARM( 'LOAD_HDR', 1, LOAD_HDR )
IF ( LOAD_HDR .EQ. 1 ) THEN
C ......... Add new trace header entries
CDESC_HDR = 'Maximum value of amp ratio'
CALL ST_HDR_ADD( 'RATIOMAX', CDESC_HDR, 1, IREAL4pz,
&
IH_RATIO_MAX, IERR )
IF ( IERR .NE. 0 ) THEN
IF ( IERR .EQ. IERR_HDR_EXSTpz ) THEN
C ................. That's OK, but somewhat unexpected
CALL ST_ERR_WARN(
&
'RATIOMAX already exists in header' )
ELSE
C ................. This will virtually never happen, but just in case
CALL ST_ERR_FATAL( 'Error adding header entry' )
ENDIF
ENDIF
CDESC_HDR = 'Time of amp ratio maximum'
CALL ST_HDR_ADD( 'RATIOTIM', CDESC_HDR, 1, IREAL4pz,
&
IH_RATIO_TIME, IERR )
IF ( IERR .NE. 0 ) THEN
IF ( IERR .EQ. IERR_HDR_EXSTpz ) THEN
C ................. That's OK, but somewhat unexpected
CALL ST_ERR_WARN(
&
'RATIOTIM already exists in header' )
ELSE
C ................. This will virtually never happen, but just in case
CALL ST_ERR_FATAL( 'Error adding header entry' )
ENDIF
ENDIF

Other Docs

Known Problems

amp_ratio FORTRAN Code514

Developers Programming Guide

ENDIF
C ..... See if the user wants to load the results into the database
LOAD_DB = 0
CALL EX_GETPARM( 'LOAD_DB ', 1, LOAD_DB )
IF ( LOAD_DB .EQ. 1 ) THEN
C ......... Open the database to store the amp ratio information
C
against trace
C ......... Note: ST_ instead of EX_ERR_FATAL
IF ( ITRNO_VALIDz .NE. 1 ) THEN
CALL ST_ERR_FATAL( 'Cannot load data into the TRC order'
&
//' without valid trace numbers (geom assigned)' )
ENDIF
C ......... We will need the index of the trace number
CALL ST_HDR_NAMINFO( 'TRACENO ', CDESC_HDR, LENGTH, IFORMAT,
&
IH_TRACENO, IERR )
IF ( IERR .NE. 0 ) CALL ST_ERR_FATAL(
&
'TRACENO not found in header' )
C ......... Lock the TRC order since we will be writing to it
C ......... Note: normal database calls
CALL DB_ORDLOCK( 'TRC', IKEY_TRC, IERR )
IF ( IERR .NE. 0 ) THEN
CALL REPORT_DB_ERR( IERR )
CALL ST_ERR_FATAL( 'Error locking TRC database' )
ENDIF
C ......... Create the new entries in the database
CDESC_DB = 'Maximum value of amp ratio'
CALL DB_PARMCRE( IKEY_TRC, '
', 'F_B_PICK', 'RATIOMAX',
&
CDESC_DB, 1, IREAL4pz, RNULLpz, IERR )
IF ( IERR .NE. 0 .AND. IERR .NE. IERR_DB_PEXSpz ) THEN
CALL REPORT_DB_ERR( IERR )
CALL ST_ERR_FATAL( 'Error creating database entry' )
ENDIF

&

CDESC_DB = 'Time of amp ratio maximum'


CALL DB_PARMCRE( IKEY_TRC, '
', 'F_B_PICK', 'RATIOTIM',
CDESC_DB, 1, IREAL4pz, RNULLpz, IERR )
IF ( IERR .NE. 0 .AND. IERR .NE. IERR_DB_PEXSpz ) THEN
CALL REPORT_DB_ERR( IERR )
CALL ST_ERR_FATAL( 'Error creating database entry' )
ENDIF

C ......... Initialize the token for buffered database I/O


ID_MAX = 0
ID_TIME = 0
ENDIF
C ..... Reserve a scratch buffer that we will need in exec phase
CALL MEM_RESBUFF( NUMSMPz, IX_SCRATCH, IERR )
C ....

End initialization phase


CALL ST_END_INIT()

Other Docs

Known Problems

amp_ratio FORTRAN Code515

C ....

Developers Programming Guide

loop over traces


CALL ST_GET_TRACE(TRACE, ITHDR, RTHDR, EOF_REACHED)
DO WHILE ( EOF_REACHED .NE. 1 )

IF ( USE_GATE ) THEN
C ..... Interpolate the gate times from the table
IF (IFORMAT_PKEY .EQ. IREAL4pz ) PKEYVAL= RTHDR(IH_PKEY)
IF (IFORMAT_PKEY .EQ. INT4pz ) PKEYVAL= ITHDR(IH_PKEY)
IF (IFORMAT_SKEY .EQ. IREAL4pz ) SKEYVAL= RTHDR(IH_SKEY)
IF (IFORMAT_SKEY .EQ. INT4pz ) SKEYVAL= ITHDR(IH_SKEY)
CALL INT_GET( ITBL_HANDLE, 0, 0, PKEYVAL, SKEYVAL,
&
TGATE, IERR )
IF ( IERR .NE. 0 ) CALL ST_ERR_FATAL(
&
'Error interpolating time gate' )
ELSE
C ......... Use the entire trace
TGATE(1) = 0.0
TGATE(2) = FLOAT(NUMSMPz-1) * SAMPRATz
ENDIF
C ..... Convert the time gate values to samples
IMIN_SAMP = NINT( TGATE(1) / SAMPRATz ) + 1
IMAX_SAMP = NINT( TGATE(2) / SAMPRATz ) + 1
C ..... Don't let them go out of bounds
IMIN_SAMP = MAX0( IMIN_SAMP, 1 )
IMIN_SAMP = MIN0( IMIN_SAMP, NUMSMPz )
IMAX_SAMP = MAX0( IMAX_SAMP, 1 )
IMAX_SAMP = MIN0( IMAX_SAMP, NUMSMPz )
IF ( IMIN_SAMP .GT. IMAX_SAMP ) THEN
C ......... Let's assume that they were meant to be reversed
ISAVE = IMIN_SAMP
IMIN_SAMP = IMAX_SAMP
IMAX_SAMP = ISAVE
ENDIF
C ..... Pass
CALL
&
&

the buffers off to a routine where the real work is done


AMP_RATIO_WORK( TRACE, RSPACEz(IX_SCRATCH), NUMSMPz,
NGATE, IMIN_SAMP, IMAX_SAMP, SAMPRATz, RATIO_MAX,
RATIO_TIME )

IF ( LOAD_HDR .EQ. 1 ) THEN


C ......... Load the values into the header
RTHDR(IH_RATIO_MAX) = RATIO_MAX
RTHDR(IH_RATIO_TIME) = RATIO_TIME
ENDIF
IF ( LOAD_DB .EQ. 1 ) THEN
C ......... Load the values into the database
LOC_TRC = ITHDR( IH_TRACENO )
IF ( LOC_TRC .NE. INULLpz ) THEN

&

Other Docs

CALL DB_BUFFRDPUT( ID_MAX, IKEY_TRC, 'F_B_PICK',


'RATIOMAX', LOC_TRC, RATIO_MAX, .FALSE., IERR )
IF ( IERR .NE. 0 ) THEN
CALL REPORT_DB_ERR( IERR )
CALL ST_ERR_FATAL(

Known Problems

amp_ratio FORTRAN Code516

&

Developers Programming Guide

'Error loading data into database' )


ENDIF
CALL DB_BUFFRDPUT( ID_TIME, IKEY_TRC, 'F_B_PICK',
'RATIOTIM', LOC_TRC, RATIO_TIME, .FALSE., IERR )
IF ( IERR .NE. 0 ) THEN
CALL REPORT_DB_ERR( IERR )
CALL ST_ERR_FATAL(
'Error loading data into database' )
ENDIF

&

&

ENDIF
ENDIF
C ....

Send the trace back to the Executive


CALL ST_PUT_TRACE(TRACE, ITHDR)

C ....

get the next trace


CALL ST_GET_TRACE(TRACE, ITHDR, RTHDR, EOF_REACHED)
C .... end while loop over traces
ENDDO
IF ( LOAD_DB .EQ. 1 ) THEN
C ............. Flush the buffers for buffered database I/O
C ............. Note that errors only give rise to
C
warnings in cleanup phase.
C ............. Also note that the "location" is now 0.
CALL DB_BUFFRDPUT( ID_MAX, IKEY_TRC, 'F_B_PICK',
&
'RATIOMAX', 0, 0.0, .TRUE., IERR )
IF ( IERR .NE. 0 ) THEN
CALL REPORT_DB_ERR( IERR )
CALL ST_ERR_WARN(
&
'Error loading data into database' )
ENDIF
CALL DB_BUFFRDPUT( ID_TIME, IKEY_TRC, 'F_B_PICK',
&
'RATIOTIM', 0, 0.0, .TRUE., IERR )
IF ( IERR .NE. 0 ) THEN
CALL REPORT_DB_ERR( IERR )
CALL ST_ERR_WARN(
&
'Error loading data into database' )
ENDIF
ENDIF
C ..... Close the packet file
CALL PKT_FILCLOSE( ID_PACKET, IERR )
C ..... Report normal completion
CALL ST_CLOSE_SOCKET_LINK
END

C-----------------------------------------------------------------------------C
C
Actual work routine
C
C------------------------------------------------------------------------------

Other Docs

Known Problems

amp_ratio FORTRAN Code517

&

&
&

Developers Programming Guide

SUBROUTINE AMP_RATIO_WORK( TRACE, SCRATCH, NSAMPS, NGATE,


IMIN_SAMP, IMAX_SAMP, SAMPRATE, RATIO_MAX, RATIO_TIME )
IMPLICIT NONE
INTEGER NSAMPS, NGATE, I, ISTART, IEND, IND_MAX, IMIN_SAMP,
IMAX_SAMP
REAL TRACE(NSAMPS), SCRATCH(NSAMPS), SUM_ABOVE, SUM_BELOW,
RATIO_MAX, RATIO_TIME, SAMPRATE, RABOVE, RBELOW

C ..... Set the starting and end of the zone of interest


ISTART = 1 - NGATE
IEND = NSAMPS + NGATE
C ..... Sum the first two gates
SUM_ABOVE = 0.0
RABOVE = 0.0
SUM_BELOW = 0.0
RBELOW = 0.0
DO 110 I=ISTART+NGATE+1,ISTART+NGATE*2
IF ( I .GE. 1 .AND. I .LE. NSAMPS ) THEN
SUM_BELOW = SUM_BELOW + ABS( TRACE(I) )
RBELOW = RBELOW + 1.0
ENDIF
CONTINUE

110

C ..... Now move down the trace


DO 120 I=ISTART+NGATE,IEND-NGATE
C ......... Compute the ratio
IF ( SUM_ABOVE .GT. 0.0 .AND. RABOVE .GT. 0.0
&
.AND. RBELOW .GT. 0.0 ) THEN
SCRATCH(I) = (SUM_BELOW/RBELOW) / (SUM_ABOVE/RABOVE)
ELSE
SCRATCH(I) = 0.0
ENDIF
C ......... Drop a sample from each gate and add the next one
IF ( I-NGATE .GE. 1 ) THEN
SUM_ABOVE = SUM_ABOVE - ABS( TRACE(I-NGATE) )
&
+ ABS( TRACE(I) )
ELSE
SUM_ABOVE = SUM_ABOVE + ABS( TRACE(I) )
RABOVE = RABOVE + 1.0
ENDIF

&

120

IF ( I+NGATE+1 .LE. NSAMPS ) THEN


SUM_BELOW = SUM_BELOW - ABS( TRACE(I+1) )
+ ABS( TRACE(I+NGATE+1) )
ELSE
IF ( I+1 .LE. NSAMPS ) THEN
SUM_BELOW = SUM_BELOW - ABS( TRACE(I+1) )
RBELOW = RBELOW - 1.0
ENDIF
ENDIF
CONTINUE

C ..... Put the final results in place.

Other Docs

Known Problems

amp_ratio FORTRAN Code518

Developers Programming Guide

C
Note that we have not handled the
C ..... edge problem, we have simply made the function undefined.
DO 130 I=1,NSAMPS
IF ( I .LE. ISTART+NGATE-1 ) THEN
TRACE(I) = 0.0
ELSEIF ( I .GE. IEND-NGATE+1 ) THEN
TRACE(I) = 0.0
ELSE
TRACE(I) = SCRATCH(I)
ENDIF
130
CONTINUE
C ..... Find the maximum of the ratio function
RATIO_MAX = TRACE(IMIN_SAMP)
IND_MAX = IMIN_SAMP
DO 140 I=IMIN_SAMP,IMAX_SAMP
IF ( TRACE(I) .GT. RATIO_MAX ) THEN
IND_MAX = I
RATIO_MAX = TRACE(I)
ENDIF
140
CONTINUE
C ..... Convert the index of the maximum to time
RATIO_TIME = FLOAT( IND_MAX - 1 ) * SAMPRATE
RETURN
END

Other Docs

Known Problems

519

Developers Programming Guide

Appendix: Global Include File


Examples

This appendix provides examples of ProMAX global include


files.

Topics covered in this appendix:

global.inc
global.h

Other Docs

Known Problems

global.inc520

Developers Programming Guide

global.inc
C-----------------------------------------------------------------------------C
C
This is the global common block for inter-tool communication of
C
processing modules that are linked into the Executive. Note that
C
all global variables end in lower case 'z', and all global parameters
C
end in lower case 'pz'.
C
C-----------------------------------------------------------------------------C ..... These are global character parameters. The common is padded to
C ..... 128 chars to facilitate addition of new parameters.
COMMON /GLOBAL_CHARcz/ CPROJz, CLINEz, CAREAz, CFLOWz,
&
CPAD_GLOBAL_CHAR
CHARACTER CPROJz*16, CLINEz*16, CAREAz*16, CFLOWz*16,
&
CPAD_GLOBAL_CHAR*64
C ..... CPROJz
- the current project name (C*16)
C ..... CLINEz
- the current line name (C*16)
C ..... CAREAz
- the current area name (C*16)
C ..... CFLOWz
- the current flow name (C*16)
C-----------------------------------------------------------------------------C ..... These are miscellaneous global parameters. The common is padded to
C ..... 16 words to facilitate addition of new parameters.
COMMON /GLOBAL_MISCcz/ EXDATUMz, VXDATUMz, IUNITSz, I3Dz,
&
IMULTCz, NTRACEz, ICDPASNz, IGEOASNz, IPAD_GLOBAL_MISC
INTEGER IUNITSz, I3Dz, IMULTCz, NTRACEz, ICDPASNz, IGEOASNz,
&
IPAD_GLOBAL_MISC(8)
REAL EXDATUMz, VXDATUMz
C ..... EXDATUMz
- Final processing datum elevation (if not variable)
C ..... VXDATUMz
- Final datum replacment velocity (if not variable)
C ..... IUNITSz
- Type of units (choices are IENGLISHpz, ISECARCpz
C .....
or IMETRICpz )
C ..... I3Dz
- 3-D flag (I3Dz=1 if data is 3-D, otherwise I3Dz=0)
C ..... IMULTCz
- Multi-component flag (=1 if data is multi-component)
C ..... NTRACEz
- Maximum sequential trace number of unstacked traces
C .....
(this is number of traces that were in the dataset
C .....
that was used to initialize the database)
C ..... ICDPASNz
- CDP bin assigned flag (=1 if CDP bins are assigned)
C ..... IGEOASNz
- Geometry-assigned flag (=1 if the geometry is assigned)
C-----------------------------------------------------------------------------C ..... These are the possible types of units:
#define IENGLISHpz 1 /* flag indicating english units */
#define IMETRICpz 3
/* flag indicating metric units */
C-----------------------------------------------------------------------------C ..... These are the global run-time parameters. The common is padded to
C ..... 32 words to facilitate addition of new parameters.
COMMON /GLOBAL_RUNTIMEcz/ SAMPRATz, NUMSMPz, IPSORTz, MAXDTRz,
&
IDTYPz, NTHz, MODEz, IOUNITz, IPKEYz, ISKEYz, IDATEz,
&
IDOMAINz, CLEANUPz, IERRORz, IGEOM_MATCHz, ITRNO_VALIDz,
&
INIT_ONLYz, IPAD_GLOBAL_RUNTIME

Other Docs

Known Problems

global.inc521

&
&

C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C

.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....

Developers Programming Guide

INTEGER NUMSMPz, IPSORTz, MAXDTRz, IDTYPz, NTHz, MODEz, IOUNITz,


IPKEYz, ISKEYz, IDATEz, IDOMAINz, IGEOM_MATCHz,
ITRNO_VALIDz, IPAD_GLOBAL_RUNTIME(15)
REAL SAMPRATz
LOGICAL CLEANUPz, IERRORz, INIT_ONLYz
SAMPRATz - trace sample rate in milliseconds
NUMSMPz - number of samples per trace. All traces are assumed to
begin at time 0.
IPSORTz - physical primary sort flag (see choices below)
MAXDTRz - the maximum number of data traces per ensemble
IDTYPz
- primary data type (see choices below)
NTHz
- the current number of 4-byte words in the trace header.
Note that the number of trace header entries may
be less than NTHz (some header entries may be more
than 4 bytes long).
MODEz
- the mode ( INTERpz, IBACKGpz, IBATCHpz )
IOUNITz - the I/O unit for output diagnostics
IPKEYz
- index in the trace header of the primary sort key
ISKEYz
- index in the trace header of the secondary sort key
IDATEz
- the current date (seconds since 00:00:00 GMT, Jan. 1, 1970)
IDOMAINz - The domain (see choices below)
INIT_ONLYz - Flag indicating that only initialization phase is
being executed (logical)
CLEANUPz - Flag indicating that the system is in cleanup mode (logical)
IERRORz - Flag indicating that the system is running under an error
condition (trying to cleanup) (logical)
IGEOM_MATCHz - Geometry loaded in the trace headers matches the
geometry that is stored in the database (=1 if true)
ITRNO_VALIDz - Trace number is valid flag, i.e. the trace number
found in the trace header can be used to reference
the database (=1 if true)

C-----------------------------------------------------------------------------C .....
#define
#define
#define
#define
#define
#define

These are the choices for IPSORTz, the physical primary sort flag
ICDPpz 1
/* CDP bin */
ISINpz 2
/* source index number */
IRECSLOCpz 3 /* receiver surface location */
IOFFSETpz 4 /* offset */
ICHANpz 5
/* channel number */
IUNKNOWNpz 6 /* none of the above */

C-----------------------------------------------------------------------------C .....
#define
#define
#define
#define
#define
#define
#define
#define
#define

These are the choices for IDTYPz, the primary data type:
INORMALpz 0
/* normal unstacked data */
IUP_HOLESpz 1 /* uphole data */
IUS_TRANSpz 2 /* transformed unstacked (e.g., frequency dom.) data */
IST_TRANSpz 3 /* transformed stacked (e.g., frequency domain) data */
ISTACKEDpz 7
/* normal stacked data */
ISNAPSHOTSpz 8 /* movie snapshots from finite difference modeling */
IFIELDpz 9 /* tape types should NOT overlap with primary data types */
IARCHIVEpz 10
IOTHER_TAPEpz 11

C-----------------------------------------------------------------------------C ..... These are the executive mode types:


#define INTERpz 1 /* interactive */

Other Docs

Known Problems

global.inc522

Developers Programming Guide

#define IBACKGpz 2 /* background */


#define IBATCHpz 3 /* batch */
C-----------------------------------------------------------------------------C .....
#define
#define
#define
#define
#define
#define
#define
#define

These are the


ITXpz 0
/*
IFXpz 1
/*
IFTpz 2
/*
IFKpz 3
/*
ITAUPpz 4 /*
ISEMBpz 5 /*
IMBTpz 6
/*
IDEPTHpz 7 /*

choices for IDOMAINz, the domain type:


normal time-space domain */
frequency-space domain */
frequency-time domain */
frequency-wavenumber domain */
tau-p domain */
semblance domain */
model-based transform */
depth-space domain */

C-----------------------------------------------------------------------------C ..... These are the critical global parameters related to geometry.
C ..... The common is padded to 64 words to facilitate addition of new
C ..... parameters.
COMMON /GLOBAL_GEOMcz/
&
MINSLOCz, MAXSLOCz, INCSLOCz, NRCVRSz, MAXTPRz,
&
MINCDPz, MAXCDPz, INCCDPz, NUMCDPz, NTRCDPz,
&
MINSINz, MAXSINz, INCSINz, NSINSz,
MAXCPSz, NSHOTSz,
&
MINOFBz, MAXOFBz, INCOFBz, NOFBINSz, OFFBINCz, OFFMAXz,
&
MINCHNz, MAXCHNz, INCCHNz, NSLOCSz, X3DORIGz, Y3DORIGz,
&
NILINESz, MINILINz, MAXILINz, XILNENDz, YILNENDz, DCDPILNz,
&
NXLINESz, MINXLINz, MAXXLINz, XXLNENDz, YXLNENDz, DCDPXLNz,
&
IPAD_GLOBAL_GEOM

C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C

INTEGERMINSLOCz, MAXSLOCz, INCSLOCz, NRCVRSz, MAXTPRz,


&
MINCDPz, MAXCDPz, INCCDPz, NUMCDPz, NTRCDPz,
&
MINSINz, MAXSINz, INCSINz, NSINSz, MAXCPSz, NSHOTSz,
&
MINOFBz, MAXOFBz, INCOFBz, NOFBINSz, MINCHNz, MAXCHNz,
&
INCCHNz, NSLOCSz, NILINESz, MINILINz, MAXILINz,
&
NXLINESz, MINXLINz, MAXXLINz, IPAD_GLOBAL_GEOM(24)
REAL OFFMAXz, OFFBINCz, XILNENDz, YILNENDz, DCDPILNz,
&
XXLNENDz, YXLNENDz, DCDPXLNz, X3DORIGz, Y3DORIGz
..... MINSLOCz - Minimum surface location number
..... MAXSLOCz - Maximum surface location number
..... INCSLOCz - Surface location number increment (always 1)
..... NRCVRSz - Total number of live groups
..... NSLOCSz - Total number of surface locations of all types
..... MAXTPRz - Maximum traces per receiver ensemble
..... MINCDPz - Minimum CDP number
..... MAXCDPz - Maximum CDP number
..... INCCDPz - CDP number increment (always 1)
..... NUMCDPz - Total number of CDPs
..... NTRCDPz - Maximum CDP fold
..... MINSINz - Minimum SIN (source index) number
..... MAXSINz - Maximum SIN (source index) number
..... INCSINz - SIN (source index) number increment (always 1)
..... NSINSz
- Total number of SINs (records of all types)
..... MAXCPSz - Maximum channels per source
..... NSHOTSz - Total number of live sources (excluding test records, etc.)
..... MINOFBz - Minimum offset bin number
..... MAXOFBz - Maximum offset bin number
..... INCOFBz - Offset bin number increment (always 1)
..... NOFBINSz - Number of offset bins

Other Docs

Known Problems

global.inc523

C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C

.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....

OFFBINCz
OFFMAXz
MINCHNz
MAXCHNz
INCCHNz
X3DORIGz

Developers Programming Guide

Y3DORIGz NILINESz
MINILINz
MAXILINz
XILNENDz
YILNENDz
DCDPILNz

NXLINESz
MINXLINz
MAXXLINz
XXLNENDz
YXLNENDz
DCDPXLNz

Offset increment between bins


Longest offset of line
Minimum channel number
Maximum channel number
Increment between channel numbers (always 1)
X coordinate of origin of 3D grid (first inline and first
crossline) (relative to XREFz)
Y coordinate of origin of 3D grid (first inline and first
crossline) (relative to YREFz)
Number of inlines
Minimum inline number
Maximum inline number
X coordinate of far end of first inline
Y coordinate of far end of first inline
Distance between CDPs in the inline direction (same as the
distance between crosslines) for 3D; mean distance between
CDPs for 2d
Number of crosslines
Minimum crossline number
Maximum crossline number
X coordinate of far end of first crossline
Y coordinate of far end of first crossline
Distance between CDPs in the crossline direction (same as
the distance between inlines)

C-----------------------------------------------------------------------------C ..... These are the global parameters related to coordinates. The common
C ..... is padded to 8 words to facilitate addition of new parameters.
COMMON /GLOBAL_COORDcz/ AZIMX1z, SLOC1Xz, SLOC1Yz,
&
IPAD_GLOBAL_COORD
C ..... These are the global double precision reference coordinates. The
C ..... common is padded to 8 words to facilitate addition of new parameters.
COMMON /GLOBAL_XYcz / XREFz, YREFz, IPAD_GLOBAL_XY
REAL AZIMX1z, SLOC1Xz, SLOC1Yz
REAL*8 XREFz, YREFz
INTEGER IPAD_GLOBAL_COORD(5), IPAD_GLOBAL_XY(4)
C
C
C
C
C

.....
.....
.....
.....
.....

AZIMX1z
SLOC1Xz
SLOC1Yz
XREFz
YREFz

Azimuth towards increasing SURFLOC number


X coordinate of first surface location
Y coordinate of first surface location
(R*8) - X reference point for the line
(R*8) - Y reference point for the line

C-----------------------------------------------------------------------------C ..... These are the global parameters related to acquisition. The common
C ..... is padded to 32 words to facilitate addition of new parameters.
COMMON /GLOBAL_AQUIScz/ ISRCTYPz, IDATRECz, IGAINXz, PREXAMPz,
&
EARLYGz, AAXFILTz, AAXSLOPz, FREQXNz, FXNSLOPz, FREQXLz,
&
FREQXHz, FXLSLOPz, FXHSLOPz, NSRECDz, ORIGDTz, IXFORMz,
&
MANFACTz, ISERIALz, NXAUXSz, RCCONSTz, IPAD_GLOBAL_AQUIS
INTEGER ISRCTYPz, IDATRECz, IGAINXz, NSRECDz, IXFORMz, MANFACTz,
&
ISERIALz, NXAUXSz, IPAD_GLOBAL_AQUIS(12)
REAL PREXAMPz, EARLYGz, AAXFILTz, AAXSLOPz, FREQXNz, FXNSLOPz,
&
FREQXLz, FREQXHz, FXLSLOPz, FXHSLOPz, ORIGDTz, RCCONSTz
C ..... ISRCTYPz - Source type
C ..... IDATRECz - Date recorded
C ..... IGAINXz - Gain mode of field intruments

Other Docs

Known Problems

global.inc524

C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C

.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....
.....

PREXAMPz
EARLYGz
AAXFILTz
AAXSLOPz
FREQXNz
FXNSLOPz
FREQXLz
FREQXHz
FXLSLOPz
FXHSLOPz
NSRECDz
ORIGDTz
IXFORMz
MANFACTz
ISERIALz
NXAUXSz
RCCONSTz

Developers Programming Guide

Instrument preamp gain constant


Instrument early or initial gain
Instrument antialias filter frequency
Instrument antialias filter slope
Instrument notch filter frequency
Instrument notch filter slope
Instrument low cut filter frequency
Instrument high cut filter frequency
Instrument low cut filter slope
Instrument high cut filter slope
Number of samples per trace on field data
Sample rate on field data
Recording system format code
Recording system manufacturing code
Recording system serial number
Number of aux channels on field records
Recording system "dial in" constant

C-----------------------------------------------------------------------------C ..... Include the system-wide null values


INTEGER INULLpz
PARAMETER ( INULLpz = 2139081118 )
REAL RNULLpz
PARAMETER ( RNULLpz = 3.3999999521443642E38 )
CHARACTER CNULLpz*1
PARAMETER ( CNULLpz = '\0' )
C-----------------------------------------------------------------------------C ..... This is done for re-entrancy, to ensure that all of the
C ..... common blocks are the same size:
REAL SAVE_ARz(1000), SAVE1z
EQUIVALENCE ( SAVE_ARz, SAVE1z )
C-----------------------------------------------------------------------------C ..... These are the possible values for the last-trace-in-ensemble flag:
#define LASTTRpz 1 /* last trace in the ensemble */
#define NLASTpz 0
/* NOT last trace in the ensemble */
C-----------------------------------------------------------------------------C .....
C .....
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

These are the choices for trace type (as defined in the trace header
entry TRC_TYPE):
IAUXpz 0
/* general auxiliary trace */
ILIVEpz 1
/* live data trace */
IDEADpz 2
/* dead trace */
IDUMMYpz 3 /* dummy trace */
ITBREAKpz 4 /* time-break trace */
IUPHOLEpz 5 /* uphole trace */
ISWEEPpz 6 /* sweep trace */
ITIMINGpz 7 /* timing trace */
IWBREAKpz 8 /* water break trace */
IOTHERpz 9 /* any other trace */
IWLOGpz 10 /* well log trace */

Other Docs

Known Problems

global.inc525

Developers Programming Guide

C-----------------------------------------------------------------------------C .....
#define
#define
#define
#define
#define
#define
#define
#define
#define

These are the tool types:


ISIMPLEpz 1
/* simple (trace in, trace out) tool */
IENSEMBLEpz 2 /* ensemble tool */
ICOMPLEXpz 3
/* complex tool */
IFLOWpz 4
/* flow control tool (not valid for user tools)
INPUTpz 6
/* input tool (implies complex tool) */
IROLLGATEpz 7 /* rolling gate tool */
IPANELpz 8
/* panel tool */
ISNL_BUFFpz 9 /* one-buffer tool */
IDBL_BUFFpz 10 /* two-buffer tool */

*/

C-----------------------------------------------------------------------------C ..... Include the system formats


INTEGER INT4pz, IREAL4pz, IREAL8pz, INTCHARpz, ICHARpz,
&
ICHARRpz, ILOGICpz
PARAMETER ( INT4pz
= 1 )
PARAMETER ( IREAL4pz = 2 )
PARAMETER ( IREAL8pz = 3 )
PARAMETER ( INTCHARpz = 4 )
PARAMETER ( ICHARpz
= 5 )
PARAMETER ( ICHARRpz = 6 )
PARAMETER ( ILOGICpz = 7 )
C ..... INT4pz
- format is INTEGER*4
C ..... IREAL4pz - format is REAL*4
C ..... IREAL8pz - format is REAL*8
C ..... INTCHARpz - format is character stored as integer
C ..... ICHARpz
- format is character string
C ..... ICHARRpz - format is character array
C ..... ILOGICpz - format is logical
C-----------------------------------------------------------------------------C ..... Include the resource type definitions
#include "resource.inc"
C-----------------------------------------------------------------------------C ..... This is the software release number and geometry release number.
#define SOFTRLpz 4.2 /* software */
#define GEORLSpz 4.2 /* geometry */
C-----------------------------------------------------------------------------C
C

Source file:
/promax/1998.6/port/include/global.inc

Other Docs

Known Problems

cglobal.h526

Developers Programming Guide

cglobal.h
/* C globals for ProMAX - equivalent to global.inc */
#ifndef CGLOBAL_H
#define CGLOBAL_H
/* define logical variables as integers */
typedef int logical;
/* character globals */
typedef struct globalCharStruct {
char cproj[16]; /* current project name */
char cline[16]; /* current line name */
char carea[16]; /* current area name */
char cflow[16]; /* current flow name */
char cpad[64]; /* pad to 128 */
} GlobalChar;
#ifdef DEFINE_CGLOBALS
#if defined (CRAY)
GlobalChar GLOBAL_CHARCZ;
GlobalChar *globalChar = &GLOBAL_CHARCZ;
#elif defined (CONVEX)
extern GlobalChar _global_charcz_;
GlobalChar *globalChar = &_global_charcz_;
#elif defined SOLARIS
extern GlobalChar global_charcz_;
GlobalChar *globalChar = &global_charcz_;
#else
extern GlobalChar global_charcz_;
GlobalChar *globalChar = &global_charcz_;
#endif
#else
#if defined (CRAY)
extern GlobalChar GLOBAL_CHARCZ, *globalChar;
#elif defined (CONVEX)
extern GlobalChar _global_charcz_, *globalChar;
#else
extern GlobalChar global_charcz_, *globalChar;
#endif
#endif /* DEFINE_CGLOBALS */
/* miscellaneous globals */
typedef struct globalMiscStruct {
float exdatum; /* final processing datum elevation (if not variable) */
float vxdatum; /* final datum replacement velocity (if not variable) */
int iunits; /* type of units (see choices below) */
logical i3d; /* true if data is 3-D */
logical imultc; /* true if data is multi-component */
int ntrace; /* number of traces used to initialize database */
logical icdpasn; /* true if CDP bins have been assigned */
logical igeoasn; /* true if geometry has been assigned */

Other Docs

Known Problems

cglobal.h527

Developers Programming Guide

logical imarine; /* true if data is marine */


logical inoexit; /* SAJ true if executive is no exiting */
int ipad[6]; /* padding to 16 words */
} GlobalMisc;
#ifdef DEFINE_CGLOBALS
#if defined (CRAY)
GlobalMisc GLOBAL_MISCCZ;
GlobalMisc *globalMisc = &GLOBAL_MISCCZ;
#elif defined (CONVEX)
extern GlobalMisc _global_misccz_;
GlobalMisc *globalMisc = &_global_misccz_;
#elif defined SOLARIS
extern GlobalMisc global_misccz_;
GlobalMisc *globalMisc = &global_misccz_;
#else
extern GlobalMisc global_misccz_;
GlobalMisc *globalMisc = &global_misccz_;
#endif
#else
#if defined (CRAY)
extern GlobalMisc GLOBAL_MISCCZ, *globalMisc;
#elif defined (CONVEX)
extern GlobalMisc _global_misccz_, *globalMisc;
#else
extern GlobalMisc global_misccz_, *globalMisc;
#endif
#endif /* DEFINE_CGLOBALS */
/* choices for globalMisc->iunits - type of units */
#define IENGLISH 1
#define IMETRIC 3
/* shorthand for easier typing and reading of code */
#define IUNITSz(globalMisc->iunits)
/* runtime globals */
typedef struct globalRuntimeStruct {
float samprat; /* time sampling interval in milliseconds */
int numsmp; /* number of samples per trace */
int ipsort; /* physical primary sort flag (see choices below) */
int maxdtr; /* maximum number of data traces per ensemble */
int idtyp; /* primary data type (see choices below) */
int nth; /* number of 4-byte words in trace header */
int mode; /* processing executive mode (see choices below) */
int iounit; /* Fortran I/O unit for output diagnostics */
int ipkey; /* trace header index of primary sort key */
int iskey; /* trace header index of secondary sort key */
int idate; /* current date (seconds since 00:00:00 GMT, 1/1/70 */
int idomain; /* domain type (see choices below) */
logical cleanup; /* true if system is in cleanup mode */
logical ierror; /* true if system in error mode (trying to cleanup) */
logical igeom_match; /* true if header geometry matches database */
logical itrno_valid; /* true if trace number can index database */
logical init_only; /* true if initialization phase only */
int ipad[15]; /* padding to 32 words */

Other Docs

Known Problems

cglobal.h528

Developers Programming Guide

} GlobalRuntime;
#ifdef DEFINE_CGLOBALS
#if defined (CRAY)
GlobalRuntime GLOBAL_RUNTIMECZ;
GlobalRuntime *globalRuntime = &GLOBAL_RUNTIMECZ;
#elif defined (CONVEX)
extern GlobalRuntime _global_runtimecz_;
GlobalRuntime *globalRuntime = &_global_runtimecz_;
#elif defined SOLARIS
extern GlobalRuntime global_runtimecz_;
GlobalRuntime *globalRuntime = &global_runtimecz_;
#else
extern GlobalRuntime global_runtimecz_;
GlobalRuntime *globalRuntime = &global_runtimecz_;
#endif
#else
#if defined (CRAY)
extern GlobalRuntime GLOBAL_RUNTIMECZ, *globalRuntime;
#elif defined (CONVEX)
extern GlobalRuntime _global_runtimecz_, *globalRuntime;
#else
extern GlobalRuntime global_runtimecz_, *globalRuntime;
#endif
#endif /* DEFINE_CGLOBALS */
/* shorthand for easier typing and reading of code */
#define NUMSMPz(globalRuntime->numsmp)
#define SAMPRATz(globalRuntime->samprat)
#define NTHz(globalRuntime->nth)
#define MAXDTRz(globalRuntime->maxdtr)
/* choices for globalRuntime->ipsort - physical primary sort key */
#define ICDP 1 /* cdp bin */
#define ISIN 2 /* source index number */
#define IRECSLOC 3 /* receiver surface location */
#define IOFFSET 4 /* offset */
#define ICHAN 5 /* channel number */
#define IUNKNOWN 6 /* none of the above */
#define IILINE 7 /* 3D inline number */
#define IXLINE 8 /* 3D cross line number */
/* choices for globalRuntime->idtyp - primary data type */
#define INORMAL 0 /* normal unstacked data */
#define IUP_HOLES 1 /* uphole data */
#define IUS_TRANS 2 /* transformed unstacked (e.g., frequency domain) data */
#define IST_TRANS 3 /* transformed stacked (e.g., frequency domain) data */
#define ISTACKED 7 /* normal stacked data */
#define ISNAPSHOTS 8 /* Movie Snap shots from finite difference modeling */
/* tape types (should NOT overlap with primary data types) */
#define IFIELD 9
#define IARCHIVE 10
#define IOTHER_TAPE 11
/* globalRuntime->mode - processing executive mode */

Other Docs

Known Problems

cglobal.h529

Developers Programming Guide

#define FROM_SHELL 1 /* job run from the command line */


#define FROM_UI 2 /* job run from the ProMAX user interface */
#define FROM_QUEUE 3 /* job run from a queue */
/* for historic reasons (avoid) */
#define INTER 1 /* interactive */
#define IBACKG 2 /* background */
#define IBATCH 3 /* batch */
/* globalRuntime->idomain - domain type */
#define ITX 0 /* normal time-space domain */
#define IFX 1 /* frequency-space domain */
#define IFT 2 /* frequency-time domain */
#define IFK 3 /* frequency-wavenumber domain */
#define ITAUP 4 /* tau-p domain */
#define ISEMB 5 /* semblance domain */
#define IMBT 6 /* model-based transform */
#define IDEPTH 7 /* depth-space domain */
#define TSLICE 8 /* time-slice domain */
#define FLEXED 9 /* flex bin data after trace duplication */
/* geometry globals */
typedef struct globalGeomStruct {
int minsloc; /* minimum surface location number */
int maxsloc; /* maximum surface location number */
int incsloc; /* surface location number increment (always 1) */
int nrcvrs; /* total number of live groups */
int maxtpr; /* maximum traces per receiver ensemble */
int mincdp; /* minimum cdp number */
int maxcdp; /* maximum cdp number */
int inccdp; /* cdp number increment (always 1) */
int numcdp; /* total number of cdps */
int ntrcdp; /* maximum cdp fold */
int minsin; /* minimum source index number */
int maxsin; /* maximum source index number */
int incsin; /* source index number increment (always 1) */
int nsins; /* total number of SINs (records of all types) */
int maxcps; /* maximum channels per source */
int nshots; /* total number of live sources */
int minofb; /* minimum offset bin number */
int maxofb; /* maximum offset bin number */
int incofb; /* offset bin number increment (always 1) */
int nofbins; /* number of offset bins */
float offbinc; /* offset increment between bins */
float offmax; /* longest offset of line */
int minchn; /* minimum channel number */
int maxchn; /* maximum channel number */
int incchn; /* increment between channel numbers (always 1) */
int nslocs; /* total number of surface locations of all types */
float x3dorig; /* x coordinate of origin of 3D grid (rel. to xref) */
float y3dorig; /* y coordinate of origin of 3D grid (rel. to yref) */
int nilines; /* number of inlines */
int minilin; /* minimum inline number */
int maxilin; /* maximum inline number */
float xilnend; /* x coordinate of far end of first inline */
float yilnend; /* y coordinate of far end of first inline */
float dcdpiln; /* distance between CDPs in the inline direction for
* 3D; mean distance between CDPs for 2D */
int nxlines; /* number of crosslines */
int minxlin; /* minimum crossline number */

Other Docs

Known Problems

cglobal.h530

Developers Programming Guide

int maxxlin; /* maximum crossline number */


float xxlnend; /* x coordinate of far end of first crossline */
float yxlnend; /* y coordinate of far end of first crossline */
float dcdpxln; /* distance between CDPs in the crossline direction */
int ipad[24]; /* padding to 64 words */
} GlobalGeom;
#ifdef DEFINE_CGLOBALS
#if defined (CRAY)
GlobalGeom GLOBAL_GEOMCZ;
GlobalGeom *globalGeom = &GLOBAL_GEOMCZ;
#elif defined (CONVEX)
extern GlobalGeom _global_geomcz_;
GlobalGeom *globalGeom = &_global_geomcz_;
#elif defined SOLARIS
extern GlobalGeom global_geomcz_;
GlobalGeom *globalGeom = &global_geomcz_;
#else
extern GlobalGeom global_geomcz_;
GlobalGeom *globalGeom = &global_geomcz_;
#endif
#else
#if defined (CRAY)
extern GlobalGeom GLOBAL_GEOMCZ, *globalGeom;
#elif defined (CONVEX)
extern GlobalGeom _global_geomcz_, *globalGeom;
#else
extern GlobalGeom global_geomcz_, *globalGeom;
#endif
#endif /* DEFINE_CGLOBALS */
/* ***** ADD 3D STUFF HERE WHEN IT IS READY ***** */
/* coordinates globals */
typedef struct globalCoordStruct {
float azimx1; /* azimuth towards increasing SURFLOC number */
float sloc1x; /* X coordinate of first surface location */
float sloc1y; /* Y coordinate of first surface location */
int ipad[5]; /* pad to 8 words */
} GlobalCoord;
#ifdef DEFINE_CGLOBALS
#if defined (CRAY)
GlobalCoord GLOBAL_COORDCZ;
GlobalCoord *globalCoord = &GLOBAL_COORDCZ;
#elif defined (CONVEX)
extern GlobalCoord _global_coordcz_;
GlobalCoord *globalCoord = &_global_coordcz_;
#elif defined SOLARIS
extern GlobalCoord global_coordcz_;
GlobalCoord *globalCoord = &global_coordcz_;
#else
extern GlobalCoord global_coordcz_;
GlobalCoord *globalCoord = &global_coordcz_;

Other Docs

Known Problems

cglobal.h531

Developers Programming Guide

#endif
#else
#if defined (CRAY)
extern GlobalCoord GLOBAL_COORDCZ, *globalCoord;
#elif defined (CONVEX)
extern GlobalCoord _global_coordcz_, *globalCoord;
#else
extern GlobalCoord global_coordcz_, *globalCoord;
#endif
#endif
typedef struct globalXYStruct {
double xref; /* X reference point for the line */
double yref; /* Y reference point for the line */
int ipad[4]; /* pad to 8 words */
} GlobalXY;
#ifdef DEFINE_CGLOBALS
#if defined (CRAY)
GlobalXY GLOBAL_XYCZ;
GlobalXY *globalXY = &GLOBAL_XYCZ;
#elif defined (CONVEX)
extern GlobalXY _global_xycz_;
GlobalXY *globalXY = &_global_xycz_;
#elif defined SOLARIS
extern GlobalXY global_xycz_;
GlobalXY *globalXY = &global_xycz_;
#else
extern GlobalXY global_xycz_;
GlobalXY *globalXY = &global_xycz_;
#endif
#else
#if defined (CRAY)
extern GlobalXY GLOBAL_XYCZ, *globalXY;
#elif defined (CONVEX)
extern GlobalXY _global_xycz_, *globalXY;
#else
extern GlobalXY global_xycz_, *globalXY;
#endif
#endif /* DEFINE_CGLOBALS */
/* acquisition globals */
typedef struct globalAcquisStruct {
int isrctyp; /* source type */
int idatrec; /* date recorded */
int igainx; /* gain mode of field instruments */
float prexamp; /* instrument preamp gain constant */
float earlyg; /* instrument early or initial gain */
float aaxfilt; /* instrument anti-alias filter frequency */
float aaxslop; /* instrument anti-alias filter slope */
float freqxn; /* instrument notch filter frequency */
float fxnslop; /* instrument notch filter slope */
float freqxl; /* instrument low-cut filter frequency */

Other Docs

Known Problems

cglobal.h532

Developers Programming Guide

float freqxh; /* instrument high-cut filter frequency */


float fxlslop; /* instrument low-cut filter slope */
float fxhslop; /* instrument high-cut filter slope */
int nsrecd; /* number of samples per trace on field data */
float origdt; /* sample rate on field data */
int ixform; /* recording system format code */
int manfact; /* recording system manufacturing code */
int iserial; /* recording system serial number */
int nxauxs; /* number of aux channels on field records */
float rcconst; /* recording system "dial in" constant */
int ipad[12]; /* pad to 32 words */
} GlobalAcquis;
#ifdef DEFINE_CGLOBALS
#if defined (CRAY)
GlobalAcquis GLOBAL_AQUISCZ;
GlobalAcquis *globalAcquis = &GLOBAL_AQUISCZ;
#elif defined (CONVEX)
extern GlobalAcquis _global_aquiscz_;
GlobalAcquis *globalAcquis = &_global_aquiscz_;
#elif defined SOLARIS
extern GlobalAcquis global_aquiscz_;
GlobalAcquis *globalAcquis = &global_aquiscz_;
#else
extern GlobalAcquis global_aquiscz_;
GlobalAcquis *globalAcquis = &global_aquiscz_;
#endif
#else
#if defined (CONVEX)
extern GlobalAcquis GLOBAL_AQUISCZ, *globalAcquis;
#elif defined (CONVEX)
extern GlobalAcquis _global_aquiscz_, *globalAcquis;
#else
extern GlobalAcquis global_aquiscz_, *globalAcquis;
#endif
#endif /* DEFINE_CGLOBALS */
/* ****************************************************************************
IF YOU CHANGE THIS struct, DON'T FORGET TO CHANGE header.inc,
OR YOU WILL BE TRANSFERRED TO THE SUPPORT DEPARTMENT
**************************************************************************** */
/* Standard header entries */
typedef struct stdHdrStruct {
int
isource, icdp, irec_sloc, ioffset,
ichan, ifb_pick, iaoffset, iseqno,
iffid, isin, isou_sloc, isou_x,
isou_y, isou_elev, inchans, irec_x,
irec_y, irec_elev, irec_nfld, icdp_sloc,
icdp_x, icdp_y, icdp_elev, icdp_nfld,
itot_stat, ina_stat, iskewstat, irec_stat,
isou_stat, iend_ens, ieoj, itraceno,
itrc_type, itlive_s, itfull_s, itfull_e,
itlive_e, ilen_surg, iamp_norm, itr_fold,

Other Docs

Known Problems

cglobal.h533

Developers Programming Guide

idepth, iuphole, isr_azim, ipad_trc,


igeo_comp, ircdp, irec_h2od, isou_h2od,
inmo_stat, ifnl_stat, iseq_disk, irepeat,
ifk_waven, ifk_wavel, ift_freq, ics_stat,
icr_stat, ips_stat, ipr_stat, itrimstat,
ilseg_end, ilseg_seq, idmooff, ir_line,
irec_dep, isou_comp, ids_seqno, n_datum,
iofb_cntr, iofb_no, iline_no, ifrn_trno,
iiline_no, ixline_no, idiskiter, isrf_sloc,
is_line, iriline_n, irxline_n, irchan;
} StdHdr;
#ifdef DEFINE_CGLOBALS
#if defined (CRAY)
StdHdr STD_HDRCZ;
StdHdr *stdHdr = &STD_HDRCZ;
#elif defined (CONVEX)
extern StdHdr _std_hdrcz_;
StdHdr *stdHdr = &_std_hdrcz_;
#elif defined SOLARIS
extern StdHdr std_hdrcz_;
StdHdr *stdHdr = &std_hdrcz_;
#else
extern StdHdr std_hdrcz_;
StdHdr *stdHdr = &std_hdrcz_;
#endif
#else
#if defined (CRAY)
extern StdHdr STD_HDRCZ, *stdHdr;
#elif defined (CONVEX)
extern StdHdr _std_hdrcz_, *stdHdr;
#else
extern StdHdr std_hdrcz_, *stdHdr;
#endif
#endif /* DEFINE_CGLOBALS */
/* space global */
typedef struct globalSpaceStruct {
int ispace[2]; /* match dimension of FORTRAN ISPACEz array */
} GlobalSpace;
#ifdef DEFINE_CGLOBALS
#if defined (CRAY)
GlobalSpace SPACEZ;
GlobalSpace *globalSpace = &SPACEZ;
#elif defined (CONVEX)
extern GlobalSpace _spacez_;
GlobalSpace *globalSpace = &_spacez_;
#elif defined SOLARIS
extern GlobalSpace spacez_;
GlobalSpace *globalSpace = &spacez_;
#else
extern GlobalSpace spacez_;
GlobalSpace *globalSpace = &spacez_;

Other Docs

Known Problems

cglobal.h534

Developers Programming Guide

#endif
#else
#if defined (CRAY)
extern GlobalSpace SPACEZ, *globalSpace;
#elif defined (CONVEX)
extern GlobalSpace _spacez_, *globalSpace;
#else
extern GlobalSpace spacez_, *globalSpace;
#endif
#endif
/* macros to assist C programmer in declaring saved parameters */
/* Note: NSAVEDPARMS must match dimension of SAVE_AR in global.inc */
#define NSAVEDPARMS 1000
#if defined (CRAY)
struct {
float buffer[NSAVEDPARMS];
} SAVED_PARMS;
#define ENDPARMS(p) } *(p)=(void*)(&SAVED_PARMS.buffer[0]);
#elif defined (CONVEX)
extern struct block {
float buffer[NSAVEDPARMS];
} _saved_parms_;
#define ENDPARMS(p) } *(p)=(void*)(&_saved_parms_.buffer[0]);
#else
extern struct {
float buffer[NSAVEDPARMS];
} saved_parms_;
#define ENDPARMS(p) } *(p)=(void*)(&saved_parms_.buffer[0]);
#endif
#define BEGINPARMS static struct { float _save1z_;
#define NPARMS(p) (1+sizeof(*p)/sizeof(float));
/* last-trace-in-ensemble flag */
#define LASTTR 1
#define NLAST 0
/* trace type */
#define IAUX 0 /* general auxiliary trace */
#define ILIVE 1 /* live data trace */
#define IDEAD 2 /* dead trace */
#define IDUMMY 3 /* dummy trace */
#define ITBREAK 4 /* time-break trace */
#define IUPHOLE 5 /* uphole trace */
#define ISWEEP 6 /* sweep trace */
#define ITIMING 7 /* timing trace */
#define IWBREAK 8 /* water break trace */
#define IOTHER 9 /* any other trace */
#define IWLOG 10 /* well log trace */
#define ICORRUPTED 11 /* corrupted header (internal use only) */
/* tool types */
#define ISIMPLE 1 /* simple (trace in, trace out) tool */
#define IENSEMBLE 2 /* ensemble tool */

Other Docs

Known Problems

cglobal.h535

#define
#define
#define
#define
#define
#define
#define

Developers Programming Guide

ICOMPLEX 3 /* complex tool */


IFLOW 4 /* flow control tool (not valid for user tools) */
INPUT 6 /* input tool (implies complex tool) */
IROLLGATE 7 /* rolling gate tool */
IPANEL 8 /* panel tool */
ISNL_BUFF 9 /* one-buffer tool */
IDBL_BUFF 10 /* two-buffer tool */

/* The following numbers might be better in cpromax.h */


/* system-wide formats */
#define INT4 1
#define IREAL4 2
#define IREAL8 3
#define INTCHAR 4
#define ICHAR 5
#define ICHARR 6
#define ILOGIC 7
/* system-wide NULL numbers. */
#include <cnull.h>
/* include the resource type definitions */
#include "resource.inc"
/* release numbers */
#define SOFTRL 6.0 /* software */
#define GEORLS 6.0 /* geometry */
/* Global errno set by system after error on calling a UNIX function */
#include <errno.h>
extern int errno;
#endif /* CGLOBAL_H */

Other Docs

Known Problems

cglobal.h536

Other Docs

Developers Programming Guide

Known Problems

537

Developers Programming Guide

Appendix: Ordered Parameter File


Examples

This appendix provides examples for work with the Ordered


Parameter Files (TRC, SIN, etc). The FORTRAN example is a
stand-alone program which is started from the command line
and which opens and reads files. The C example is a stand-alone
program and menu which compares ordered parameter files in
different ProMAX line directories. This was a prototype
program for the quality control of processes used across
hardware platforms.

Topics covered in this appendix:

db_disp.f
comp_opf.menu
comp_opf.c

Other Docs

Known Problems

db_disp.f538

Developers Programming Guide

db_disp.f
PROGRAM DB_DISP
C ..... Utility to poke around in the database
IMPLICIT NONE
#include "global.inc"
CHARACTER CORDNAM*3, CINFO*8, CNAME*8, CREPLY*1, CWORK*144,
&
CFORMAT*9, CNULL*1
CHARACTER*8 CINFOBUF(100), CNAMEBUF(100)
CHARACTER*80 CDESCBUF(100)
CHARACTER CAREA(16), CLINE(16)
INTEGER IWORDBUF(100), IFORMBUF(100), INULLBUF(100),
&
IBUFF(100000), IERR, INUL, IKEY, LMIN, LMAX, LINC,
&
NSTORED, IGDATE, IGTIME, NGTRACE, NFOUND, I, IREPLY,
&
IRFIRST, IRLAST, IRFLAG, NVALS, IND, IRETURN, IDATEBUF(100)
REAL RBUFF(100000), RNUL, SOFTRLSE
REAL*8 RCBUFF(500)
EQUIVALENCE (INUL,RNUL)
EQUIVALENCE (IBUFF,RBUFF)
EQUIVALENCE (IBUFF,RCBUFF)
C ..... Initialize:
IKEY = 0
IERR = 0
CNULL = CHAR(0)
CINFO = '
CNAME = '

'
'

C ..... Call a crude function to let the user select an area and line
50
CALL DB_CHOOSE_AL( CAREA, CLINE, IRETURN )
C ..... If return status is not 0, act accordingly
IF ( IRETURN .EQ. 1 ) THEN
WRITE (*,*) 'No areas exist'
STOP
ELSEIF ( IRETURN .EQ. 2 ) THEN
C ......... User wants to quit
STOP
ENDIF
C ..... Initialize the area and line
CALL DB_INIT_LINE( CAREA, CLINE, IERR )
90

WRITE
WRITE
WRITE
WRITE
WRITE
WRITE
WRITE
WRITE
WRITE
WRITE
WRITE

Other Docs

(*,*)
(*,*)
(*,*)
(*,*)
(*,*)
(*,*)
(*,*)
(*,*)
(*,*)
(*,*)
(*,*)

'Choose an ordered database:'


'1)
'2)
'3)
'4)
'5)
'6)
'7)

LIN (line)'
TRC (trace)'
SRF (surface location)'
SIN (source)'
CDP'
CHN (channel)'
start over'

Known Problems

db_disp.f539

Developers Programming Guide

WRITE (*,*) 'Enter 1-7 >'


READ (*,'(A1)') CREPLY
IF ( CREPLY .EQ. '1' ) THEN
CORDNAM = 'LIN'
ELSEIF ( CREPLY .EQ. '2' ) THEN
CORDNAM = 'TRC'
ELSEIF ( CREPLY .EQ. '3' ) THEN
CORDNAM = 'SRF'
ELSEIF ( CREPLY .EQ. '4' ) THEN
CORDNAM = 'SIN'
ELSEIF ( CREPLY .EQ. '5' ) THEN
CORDNAM = 'CDP'
ELSEIF ( CREPLY .EQ. '6' ) THEN
CORDNAM = 'CHN'
ELSEIF ( CREPLY .EQ. '7' ) THEN
GO TO 50
ELSE
WRITE (*,*) 'ERROR - invalid response'
GO TO 90
ENDIF
IF ( IKEY .NE. 0 ) THEN
C ......... Better unlock whatever was locked (call DB_ORDUNLK)
CALL DB_ORDUNLK( IKEY, IERR )
IF ( IERR .NE. 0 ) THEN
WRITE (*,*) 'ERROR opening database file, try again'
GO TO 90
ENDIF
ENDIF
C ..... Lock the ordered database file that was selected (call DB_ORDLOCK)
CALL DB_ORDLOCK( CORDNAM, IKEY, IERR )
IF ( IERR .NE. 0 ) THEN
CALL REPORT_DB_ERR( IERR )
WRITE (*,*) 'ERROR opening database file, try again'
GO TO 90
ENDIF
C ..... Get info on the order (call DB_ORDINFO)
CALL DB_ORDINFO( IKEY, '
', LMIN, LMAX, LINC,
&
NSTORED, SOFTRLSE, IGDATE, IGTIME, NGTRACE, IERR )
IF ( IERR .NE. 0 ) THEN
WRITE (*,*) 'ERROR opening database file, try again'
GO TO 90
ENDIF
C ..... Write out the first and last location, increment, and number of
C ..... stored parameters
WRITE (*,*)
WRITE (*,*) 'First location
= ', LMIN
WRITE (*,*) 'Last location
= ', LMAX
WRITE (*,*) 'Location increment
= ', LINC
WRITE (*,*) 'Number of stored parameters = ', NSTORED
110

WRITE
WRITE
WRITE
WRITE

Other Docs

(*,*)
(*,*) 'Select an option:'
(*,*)
(*,*) '1) Review ordered database global parameters'

Known Problems

db_disp.f540

Developers Programming Guide

WRITE
WRITE
WRITE
WRITE
WRITE
WRITE
&

(*,*) '2) Choose a different ordered database'


(*,*) '3) View list of information types'
(*,*) '4) View list of all stored parameters'
(*,*) '5) Select an information type'
(*,*) '6) Select a parameter'
(*,*) '7) Retrieve values for the currently'
//' selected parameter'
WRITE (*,*) '8) Delete the currently selected parameter'
WRITE (*,*) '9) Exit'
WRITE (*,*)
WRITE (*,*) 'Enter 1-8 >'
READ (*,'(A1)') CREPLY

IF ( CREPLY .EQ. '1' ) THEN


C ......... Review ordered database global parameters
WRITE (*,*)
WRITE (*,*) 'First location
WRITE (*,*) 'Last location
WRITE (*,*) 'Location increment
WRITE (*,*) 'Number of stored parameters

=
=
=
=

',
',
',
',

LMIN
LMAX
LINC
NSTORED

ELSEIF ( CREPLY .EQ. '2' ) THEN


C ......... Choose a different ordered database
GO TO 90
ELSEIF ( CREPLY .EQ. '3' ) THEN
C ......... View list of information types (call DB_INFOTYPS)
CALL DB_INFOTYPS( IKEY, '
', NSTORED, NFOUND,
&
CINFOBUF, IERR )
IF ( IERR .NE. 0 ) THEN
WRITE (*,*) 'Error retrieving list of information types'
ELSE
WRITE (*,*)
WRITE (*,*) 'Names of all existing information types:'
DO 120 I=1,NFOUND
WRITE (*,'(1X,A8)') CINFOBUF(I)
120
CONTINUE
ENDIF
ELSEIF ( CREPLY .EQ. '4' ) THEN
C ......... View list of all stored parameters (call DB_ORDPARM)
CALL DB_ORDPARM( IKEY, CORDNAM, NSTORED, CINFOBUF, CNAMEBUF,
&
CDESCBUF, IWORDBUF, IFORMBUF, INULLBUF, IDATEBUF, IERR )
IF ( IERR .NE. 0 ) THEN
WRITE (*,*) 'ERROR retrieving list of stored parameters'
ELSE

&

WRITE (*,*)
WRITE (*,*) 'Infotype
Name
Length Format'
//'
Null value
Date created'
WRITE (*,*)
DO 130 I=1,NSTORED
............. Give the character name of the format
IF ( IFORMBUF(I) .EQ. INT4pz ) THEN
CFORMAT = 'INTEGER'
ELSEIF ( IFORMBUF(I) .EQ. IREAL4pz ) THEN
CFORMAT = 'REAL'

Other Docs

Known Problems

db_disp.f541

&
&

&

&
130
140
150

Developers Programming Guide

ELSEIF ( IFORMBUF(I) .EQ. IREAL8pz ) THEN


CFORMAT = 'REAL*8'
ELSEIF ( IFORMBUF(I) .EQ. INTCHARpz ) THEN
CFORMAT = 'CHAR-INT'
ELSEIF ( IFORMBUF(I) .EQ. ICHARpz ) THEN
CFORMAT = 'CHARACTER'
ELSE
CFORMAT = 'deleted '
ENDIF
IF ( IFORMBUF(I) .EQ. INT4pz ) THEN
WRITE (*,140) CINFOBUF(I), CNAMEBUF(I),
IWORDBUF(I), CFORMAT, INULLBUF(I),
IDATEBUF(I)
ELSE
INUL = INULLBUF(I)
WRITE (*,150) CINFOBUF(I), CNAMEBUF(I),
IWORDBUF(I), CFORMAT, RNUL, IDATEBUF(I)
ENDIF
WRITE (*,'(1X,A13,A80)') 'Description: ',
CDESCBUF(I)
CONTINUE
FORMAT(1X,A8,4X,A8,2X,I6,2X,A8,2X,I12, 4X,I12)
FORMAT(1X,A8,4X,A8,2X,I6,2X,A8,2X,G12.1,4X,I12)
ENDIF

ELSEIF ( CREPLY .EQ. '5' ) THEN


C ......... Select an information type (call DB_INFOTYPS)
CALL DB_INFOTYPS( IKEY, '
', NSTORED, NFOUND,
&
CINFOBUF, IERR )
IF ( IERR .NE. 0 ) THEN
WRITE (*,*) 'Error retrieving list of information types'
GO TO 110
ENDIF
WRITE (*,*)
WRITE (*,*) 'Existing information types:'
DO 160 I=1,NFOUND
WRITE (*,'(1X,I4,1X,A8)') I, CINFOBUF(I)
160
CONTINUE
WRITE (*,*)
WRITE (*,*) 'Select an information type (enter number) >'
READ (*,'(I4)') IREPLY
IF ( IREPLY .LT. 1 .OR. IREPLY .GT. NFOUND ) THEN
WRITE (*,*) 'ERROR - invalid response'
CINFO = '
'
GO TO 110
ENDIF
CINFO = CINFOBUF(IREPLY)
C ......... Show the list of all name for this info type (call DB_INFOLIST)
CALL DB_INFOLIST( IKEY, '
', CINFO, NSTORED, NFOUND,
&
CNAMEBUF, CDESCBUF, IDATEBUF, IERR )
IF ( IERR .NE. 0 ) THEN
WRITE (*,*) 'Error retrieving list of names'
GO TO 110
ENDIF
WRITE (*,*)
WRITE (*,*) 'Stored parameters for this info type:'
WRITE (*,*)

Other Docs

Known Problems

db_disp.f542

&
170

Developers Programming Guide

DO 170 I=1,NSTORED
WRITE (*,*) 'Name= ', CNAMEBUF(I),
'
Date created= ', IDATEBUF(I)
WRITE (*,'(1X,A13,A65)') 'Description: ', CDESCBUF(I)
CONTINUE

ELSEIF ( CREPLY .EQ. '6' ) THEN


C ......... Select a parameter
IF ( CINFO .EQ. '
' ) THEN
WRITE (*,*) 'ERROR - no info type is selected'
GO TO 110
ENDIF
C ......... Show the list of all name for the current info
C ......... type (call DB_INFOLIST)
CALL DB_INFOLIST( IKEY, '
', CINFO, NSTORED, NFOUND,
&
CNAMEBUF, CDESCBUF, IDATEBUF, IERR )
IF ( IERR .NE. 0 ) THEN
WRITE (*,*) 'Error retrieving list of names'
GO TO 110
ENDIF
WRITE (*,*)
WRITE (*,*) 'Stored parameters for the current info type:'
DO 180 I=1,NFOUND
CWORK = CDESCBUF(I)
WRITE (*,'(1X,I4,1X,A8,2X,A60)') I, CNAMEBUF(I),
&
CWORK(1:60)
180
CONTINUE
WRITE (*,*)
WRITE (*,*) 'Select a parameter (enter number) >'
READ (*,'(I4)') IREPLY
IF ( IREPLY .LT. 1 .OR. IREPLY .GT. NFOUND ) THEN
WRITE (*,*) 'ERROR - invalid response'
CNAME = '
'
GO TO 110
ENDIF
CNAME = CNAMEBUF(IREPLY)
ELSEIF ( CREPLY .EQ. '7' ) THEN
C ......... Retrieve values for the currently selected parameter
IF ( CNAME .EQ. '
' ) THEN
WRITE (*,*) 'ERROR - no parameter is selected'
GO TO 110
ENDIF
190
WRITE (*,*)
WRITE (*,*) 'Do you wish to select a range of'
&
//' values (yes/no) >'
READ (*,'(A1)') CREPLY
IF ( CREPLY .EQ. 'Y' .OR. CREPLY .EQ. 'y' ) THEN
IRFLAG = 1
WRITE (*,*) 'First location available
= ', LMIN
WRITE (*,*) 'Last location available
= ', LMAX
WRITE (*,*) 'Enter first location >'
READ (*,'(I10)') IRFIRST
IF ( IRFIRST .LT. LMIN .OR. IRFIRST .GT. LMAX ) THEN
WRITE (*,*) 'ERROR - value out of range'
GO TO 190
ENDIF
WRITE (*,*) 'Enter last location >'
READ (*,'(I10)') IRLAST

Other Docs

Known Problems

db_disp.f543

Developers Programming Guide

IF ( IRLAST .LT. LMIN .OR. IRLAST .GT. LMAX


.OR. IRLAST .LT. IRFIRST ) THEN
WRITE (*,*) 'ERROR - value out of range'
GO TO 190
ENDIF
ELSEIF ( CREPLY .EQ. 'N' .OR. CREPLY .EQ. 'n' ) THEN
IRFLAG = 0
IRFIRST = LMIN
IRLAST = LMAX
ELSE
WRITE (*,*) 'ERROR - invalid response'
GO TO 190
ENDIF
C ......... Get the values (call DB_PARMGET)
CALL DB_PARMGET( IKEY, '
', CINFO, CNAME,
&
IRFLAG, IRFIRST, IRLAST, IBUFF, IERR )
IF ( IERR .NE. 0 ) THEN
WRITE (*,*) 'ERROR - getting values from database'
GO TO 110
ENDIF
C ......... Get the format of the parameter (call DB_PARMINFO)
CALL DB_PARMINFO( IKEY, '
', CINFO, CNAME, CDESCBUF,
&
IWORDBUF, IFORMBUF, INULLBUF, IDATEBUF, IERR )
IF ( IERR .NE. 0 ) THEN
WRITE (*,*) 'ERROR - getting info from database'
GO TO 110
ENDIF
NVALS = (IRLAST-IRFIRST) / LINC + 1
DO 200 I=1,NVALS
IND = IRFIRST + (I-1)*LINC
IF ( IFORMBUF(1) .EQ. INT4pz ) THEN
WRITE (*,*) IND, IBUFF(I)
ELSEIF ( IFORMBUF(1) .EQ. IREAL4pz ) THEN
WRITE (*,*) IND, RBUFF(I)
ELSE
WRITE (*,*) 'ERROR - format', IFORMBUF(1),
&
' not supported'
GO TO 110
ENDIF
200
CONTINUE
&

ELSEIF ( CREPLY .EQ. '8' ) THEN


IF ( CNAME .EQ. '
' ) THEN
WRITE (*,*) 'ERROR - no parameter is selected'
GO TO 110
ENDIF
WRITE (*,*)
WRITE (*,*) 'Are you sure that you want to delete ',
&
CNAME, '?'
WRITE (*,*) 'Enter yes or no >'
READ (*,'(A1)') CREPLY
IF ( CREPLY .NE. 'Y' .AND. CREPLY .NE. 'y' ) GO TO 110
C ......... Delete the parameter (call DB_PARMDEL)
CALL DB_PARMDEL( IKEY, '
', CINFO, CNAME, IERR )
IF ( IERR .NE. 0 ) THEN
WRITE (*,*) 'ERROR - deleting parameter'
ENDIF
ELSEIF ( CREPLY .EQ. '9' ) THEN

Other Docs

Known Problems

db_disp.f544

Developers Programming Guide

C ......... Exit
C ......... Unlock the database (call DB_ORDUNLK)
CALL DB_ORDUNLK( IKEY, IERR )
STOP
ELSE
WRITE (*,*) 'ERROR - invalid response'
ENDIF
GO TO 110
END

Other Docs

Known Problems

comp_opf.menu545

Developers Programming Guide

comp_opf.menu
'(
name: COMP_OPF
label: "OPF Compare for QC*"
value_tab: 50
parameter: AREA2
text: "Comparison Area name"
type: edit:
type_desc: (28 80 5 " FORMAT: string
EXAMPLE: test_area1
HELP: EMACS Editor Widget (scroll with down/up arrow keys)
CURSOR MOVEMENT: Use the arrow keys:->,<-,etc.;Point the mouse cursor,click B1
CM: Ctrl-AMove the cursor to the BEGINNING of the current line
CM: Ctrl-EMove the cursor to the END of the current line
EDITING: All keyboard entry is in 'insert' mode
E: Backspace, Delete keysDelete one character to the LEFT of the cursor
E: Ctrl-D Delete one character to the RIGHT of the cursor
E: Ctrl-KKILL to the end of the line (from the cursor)
E: Ctrl-YYANK back the contents of the kill buffer; 'Cut and
paste'; (Can move the cursor first) " 3 )
value: "test_area"
mouse_text: "Enter name of the area containing the OPF to compare. "
parameter: LINE2
text: "Comparison Line name"
type: edit:
type_desc: (28 80 5 " FORMAT: string
EXAMPLE: test_line
HELP: EMACS Editor Widget (scroll with down/up arrow keys)
CURSOR MOVEMENT: Use the arrow keys:->,<-,etc.;Point the mouse cursor,click B1
CM: Ctrl-AMove the cursor to the BEGINNING of the current line
CM: Ctrl-EMove the cursor to the END of the current line
EDITING: All keyboard entry is in 'insert' mode
E: Backspace, Delete keysDelete one character to the LEFT of the cursor
E: Ctrl-D Delete one character to the RIGHT of the cursor
E: Ctrl-KKILL to the end of the line (from the cursor)
E: Ctrl-YYANK back the contents of the kill buffer; 'Cut and
paste'; (Can move the cursor first) " 3 )
value: "test_line"
mouse_text: "Enter name of the line containing the OPF to compare. "
parameter: OPF_NAME
text: "OPF type"
type: edit:
type_desc: (28 80 5 " FORMAT: string
EXAMPLE: SIN or TRC
HELP: EMACS Editor Widget (scroll with down/up arrow keys)
CURSOR MOVEMENT: Use the arrow keys:->,<-,etc.;Point the mouse cursor,click B1
CM: Ctrl-AMove the cursor to the BEGINNING of the current line
CM: Ctrl-EMove the cursor to the END of the current line
EDITING: All keyboard entry is in 'insert' mode
E: Backspace, Delete keysDelete one character to the LEFT of the cursor
E: Ctrl-D Delete one character to the RIGHT of the cursor
E: Ctrl-KKILL to the end of the line (from the cursor)

Other Docs

Known Problems

comp_opf.menu546

Developers Programming Guide

E:

Ctrl-YYANK back the contents of the kill buffer; 'Cut and


paste'; (Can move the cursor first) " 3 )
value: "TRC"
mouse_text: "Enter three-letter character string of the OPF to compare. TRC or
SIN for example"
parameter: PARMNAME
text: "Paramter Name"
type: edit:
type_desc: (28 80 5 " FORMAT: string
EXAMPLE: FB_PICK
HELP: EMACS Editor Widget (scroll with down/up arrow keys)
CURSOR MOVEMENT: Use the arrow keys:->,<-,etc.;Point the mouse cursor,click B1
CM: Ctrl-AMove the cursor to the BEGINNING of the current line
CM: Ctrl-EMove the cursor to the END of the current line
EDITING: All keyboard entry is in 'insert' mode
E: Backspace, Delete keysDelete one character to the LEFT of the cursor
E: Ctrl-D Delete one character to the RIGHT of the cursor
E: Ctrl-KKILL to the end of the line (from the cursor)
E: Ctrl-YYANK back the contents of the kill buffer; 'Cut and
paste'; (Can move the cursor first) " 3 )
value: "FB_PICK"
mouse_text: "Enter the parameter name within the OPF to compare. Example would be
FB_PICK"
parameter: INFOTYPE
text: "Information type of the paramter"
type: edit:
type_desc: (28 80 5 " FORMAT: string
EXAMPLE: STATICS or GEOMETRY
HELP: EMACS Editor Widget (scroll with down/up arrow keys)
CURSOR MOVEMENT: Use the arrow keys:->,<-,etc.;Point the mouse cursor,click B1
CM: Ctrl-AMove the cursor to the BEGINNING of the current line
CM: Ctrl-EMove the cursor to the END of the current line
EDITING: All keyboard entry is in 'insert' mode
E: Backspace, Delete keysDelete one character to the LEFT of the cursor
E: Ctrl-D Delete one character to the RIGHT of the cursor
E: Ctrl-KKILL to the end of the line (from the cursor)
E: Ctrl-YYANK back the contents of the kill buffer; 'Cut and
paste'; (Can move the cursor first) " 3 )
value: "STATICS"
mouse_text: "Enter the information type of the OPF to compare. Example would be
STATICS"
parameter: TOLERANC
text: "Percent error tolerated"
type: typein:
type_desc: ( real: 6 0.0 nil )
value: 0.001
mouse_text: "Percent error tolerated in floating point database values, see help
file for error calculation method."
exec_data: ("COMP_OPF"
("SPECIAL"
("TOOLTYPE"
("PATHNAME"
)
("GENERAL"

implicit: "STAND_ALONE")
implicit: "/promax/1998.6/rs6000/exe/comp_opf.exe")

("version" implicit: "%Q% %M%

Other Docs

%I%

%G%")

Known Problems

comp_opf.menu547

Developers Programming Guide

("AREA2
"
("LINE2
"
("OPF_NAME"
("PARMNAME"
("INFOTYPE"
("TOLERANC"

implicit:
implicit:
implicit:
implicit:
implicit:
implicit:

(value
(value
(value
(value
(value
(value

'AREA2
'LINE2
'OPF_NAME
'PARMNAME
'INFOTYPE
'TOLERANC

))
))
))
))
))
))

)
)
)

Other Docs

Known Problems

comp_opf.c548

Developers Programming Guide

comp_opf.c
/*
/*
/*
/*
/*
/*
/*
/*
/*

----------------------------------------------------------------*/
comp_opf
this is a stand-alone ProMAX module for comparing opf files
in separate areas and lines and primarily for use in QC of
promax processing modules.
original code by B. Fuller, 31-oct-94 (BOO!)
----------------------------------------------------------------*/

#include
#include
#include
#include

"cglobal.h"
"cpromax.h"
<stdio.h>
<math.h>

void main( int argc, char **argv )


{
static char *sccsid = "%Z% %Q% %M% %I% %G%";
/* declare local variables */
char cpacket_file[129], area1[17], line1[17];
char *area2, *line2;
char *opfName, *parmName, *infoType;
int numErrorsFound = 0;
int errCode, id_packet, format;
int ival1, ival2, loc;
int i_128=128;
float *fval1, *fval2;
float diff, mean;
float tolerance, totalError = 0.0;
void *opfPntr1, *opfPntr2;
void *parmPntr1, *parmPntr2;
/* set the global pointers */
GlobalRuntime *gr = globalRuntime;
GlobalGeom
*gg = globalGeom;
GlobalMisc
*gm = globalMisc;

/* Put argv[1] into a string called cpacket_file */


u_carr2str_( argv[1], cpacket_file, &i_128, strlen(argv[1]) );
/* null terminate the string at the end */
cpacket_file[128] = '\0';
/* Open the parameter packet file */
initStandAlone(argc, argv, "COMP_OPF");
/* the area and line paramters */
uParGetString("AREA2
", &area2 );
uParGetString("LINE2
", &line2 );

Other Docs

Known Problems

comp_opf.c549

uParGetString("OPF_NAME",
uParGetString("PARMNAME",
uParGetString("INFOTYPE",
uParGetFloat ("TOLERANC",

Developers Programming Guide

&opfName );
&parmName );
&infoType );
&tolerance );

opfPntr1 = opfOpen( opfName );


if( opfPntr1 == NULL ){
uErrFatal("Error opening %s database file in %s %s", opfName, area1, line1
);
}
parmPntr1 = opfInitBufGet( opfPntr1, infoType, parmName );
if( parmPntr1 == NULL ){
uErrFatal("Error opening paramter %s in %s %s \n", parmName, area1, line1
);
}

/* initialize the global variables and open the OPF for line2 */
db_init_line_( area2, line2, &errCode );
if( errCode != 0 ){
uErrFatal("Error initializing the database for %s, %s.", area2, line2);
}
opfPntr2 = opfOpen( opfName );
if( opfPntr2 == NULL ){
uErrFatal("Error opening %s database file in %s %s", opfName, area2, line2
);
}
parmPntr2 = opfInitBufGet( opfPntr2, infoType, parmName );
if( parmPntr2 == NULL ){
uErrFatal("Error opening paramter %s in %s %s \n", parmName, area2, line2
);
}

/* check the format of the opf */


format = opfParmFormat( opfPntr1, infoType, parmName );
if( format != HDRINT ){
if(format != HDRFLOAT ){
uErrFatal("This module only compares FLOAT and INT opf paramters.");
}
}
/* check the boundaries of the opfs */
if( opfLocMin( opfPntr1 ) != opfLocMin( opfPntr2 ) ){
uErrFatal("The minumum opf location doesn't match for the two lines.");
}
if( opfLocMax( opfPntr1 ) != opfLocMax( opfPntr2 ) ){
uErrFatal("The minumum opf location doesn't match for the two lines.");
}
if( opfLocInc( opfPntr1 ) != opfLocInc( opfPntr2 ) ){
uErrFatal("The opf location incrment doesn't match for the two lines.");
}

Other Docs

Known Problems

comp_opf.c550

Developers Programming Guide

for( loc = opfLocMin(opfPntr1); loc <= opfLocMax(opfPntr1); loc +=


opfLocInc(opfPntr1) ){
errCode = opfBufGet( parmPntr1, loc, &ival1 );
errCode = opfBufGet( parmPntr2, loc, &ival2 );
if( format == HDRINT ){
if( ival1 != ival2 ){
numErrorsFound++;
totalError += fabs(diff);
}
}
else{
fval1 = (float*)(&ival1);
fval2 = (float*)(&ival2);
diff = *fval1 - *fval2;
if( *fval1 == 0.0 ){
if( fabs(*fval2) > tolerance ){
numErrorsFound++;
totalError += fabs(diff);
}
}
else{
if( fabs(diff/(*fval1)) > tolerance ){
numErrorsFound++;
totalError += fabs(diff);
}
}
}
}
errCode = opfCloseBufGet( opfPntr1 );
errCode = opfCloseBufGet( opfPntr2 );
errCode = opfClose( opfPntr1 );
errCode = opfClose( opfPntr2 );
if( numErrorsFound > 0 ){
uErrFatal("Database comparison failed at %d locations with a mean error of
%f",
numErrorsFound, totalError/numErrorsFound );
}
/* notify the system of a normal completion */
printf("****************************************\n");
printf("****************************************\n");
printf(" NO errors detected in OPF comparison\n");
printf("****************************************\n");
printf("****************************************\n");
u_comp_normal_();
}

Other Docs

Known Problems

551

Developers Programming Guide

Appendix: Lisp Menu Example

This appendix provides an example of a Lisp menu program..

Topics covered in this appendix:

EXAMPLE.menu

Other Docs

Known Problems

EXAMPLE.menu552

Developers Programming Guide

EXAMPLE.menu
(
name: PROG_NAME
label: Sample ProMAX Menu
value_tab: 48

parameter: CHOOSE1
text: This is an item you can choose
type: choose:
type_desc: (
(Item 1 1 Mouse pointing help for Item 1. )
(Item 2 2 Mouse pointing help for Item 2. )
(Item 3 3 Mouse pointing help for Item 3. ) )
value: 3
mouse_text: This is the mouse pointing help you see when you point to the This
is an item you can choose text.

parameter: CHOOSE2
text: This menu entry will generate a pop choose
type: pop_choose:
type_desc: (
(Item 1 1 Mouse pointing help for Item 1. )
(Item 2 2 Mouse pointing help for Item 2. )
(Item 3 3 Mouse pointing help for Item 3. ) )
value: 3
mouse_text: This is the mouse pointing help you see when you point to the menu
line.

parameter: CIRCULAR1
text: This item rotates in a circular fashion
type: circular:
type_desc: (
(Item 1 1 Mouse pointing help for Item 1. )
(Item 2 2 Mouse pointing help for Item 2. ) )
value: 3
mouse_text: This is the mouse pointing help you see when you point to the menu
line.

parameter: SIMPLE_REAL
text: This is a simple REAL number item
type: real:
value: 1.0
mouse_text: Mouse pointing help goes here (simple reals are 10 characters wide
and have no input test limits).

parameter: FANCY_REAL
text: This is a sophisticated REAL number item
type: typein:
type_desc: ( real: 6 1.0e-4 nil )
value: 2.0

Other Docs

Known Problems

EXAMPLE.menu553

Developers Programming Guide

mouse_text: Mouse pointing help goes here (this real is 6 characters wide, test
limits are 1.0E-4 (lower) with no upper limit).

parameter: SIMPLE_INTEGER
text: This is a simple INTEGER number item
type: int:
value: 3
mouse_text: Mouse pointing help goes here (simple integers are 8 characters wide
and have no input test limits).

parameter: FANCY_INTEGER
text: This is a sophisticated INTEGER number item
type: typein:
type_desc: ( int: 3 nil 999999 )
value: 4
mouse_text: Mouse pointing help goes here (this integer is 8 characters wide,
test limits are 999999 (upper) with no lower limit).

parameter: BOOLEAN1
text: This is a BOOLEAN (true/false) type
type: boolean:
value: nil
mouse_text: This mouse pointing help explains the item (note: default value:
can be t (true) or nil (false).

parameter: STRING1
text: This is a STRING type
type: typein:
type_desc: (string: 30)
value: Initial default goes here
mouse_text: This mouse pointing help should normally include the input format
and an example.

parameter: EDIT_STRING
text: This is an EDITOR field type
type: edit:
type_desc: (30 80 5 Format: Enter format example here, followed by a carriage
return
Example: Enter Example here
HELP: EMACS Editor Widget (scroll with down/up arrow keys)
CURSOR MOVEMENT: Use the arrow keys:->,<-,etc.;Point the mouse cursor,click B1
CM: Ctrl-AMove the cursor to the BEGINNING of the current line
CM: Ctrl-EMove the cursor to the END of the current line
EDITING: All keyboard entry is in insert mode
E: Backspace, Delete keysDelete one character to the LEFT of the cursor
E: Ctrl-D Delete one character to the RIGHT of the cursor
E: Ctrl-KKILL to the end of the line (from the cursor)
E: Ctrl-YYANK back the contents of the kill buffer; Cut and
paste; (Can move the cursor first) 3 )
value: Initial default goes here
mouse_text: This item calls the EDIT function. The type_desc: dictates an
editor 80 characters by 5 lines (30 chars to show on the menu.

Other Docs

Known Problems

EXAMPLE.menu554

Developers Programming Guide

parameter: DATA_FILE
text: Used to select a trace data file
type: function:
type_desc: (dataset_list datasets)
value: no entry
selected_item: INVALID
mouse_text: Use Mouse Button 1 to select a dataset file description from the
DATASETS menu.

parameter: HEADER_SELECT
text: Used to select a trace header word
type: function:
type_desc: (header_list headers)
value: SOURCE
selected_item: Live source number
mouse_text: This option calls a C language function that presents the user
with a list of trace header words to choose from.

parameter: TIME_GATES
text: Used to select a TIME GATE parameter file
type: function:
type_desc: ((parm_list GAT) parms)
value: no entry
selected_item: * No Parameter File has been Selected *
mouse_text: Use Mouse Button 1 to select a gate parameter file from the
parameter file menu.

parameter: MUTE_FILE
text: Used to select a MUTE TIMES parameter file
type: function:
type_desc: ((parm_list MUT) parms)
value: no entry
selected_item: * No Parameter File has been Selected *
mouse_text: Use Mouse Button 1 to select a MUTE parameter file from the
parameter file menu.

parameter: VEL_FILE
text: Used to select a VELOCITY parameter file
type: function:
type_desc: ((parm_list VEL) parms)
value: no entry
selected_item: * No Parameter File has been Selected *
mouse_text: Use Mouse Button 1 to select a VELOCITY parameter file from the
parameter file menu.

parameter: HORIZON_FILE
text: Used to select an AUTOSTATICS HORIZON file
type: function:
type_desc: ((parm_list AHZ) parms)
value: no entry
selected_item: * No Parameter File has been Selected *
mouse_text: Use Mouse Button 1 to select an AUTOSTATICS HORIZON file from the
parameter file menu.

Other Docs

Known Problems

EXAMPLE.menu555

Developers Programming Guide

parameter: KILL_FILE
text: Used to select a TRACE KILL parameter file
type: function:
type_desc: ((parm_list KIL) parms)
value: no entry
selected_item: * No Parameter File has been Selected *
mouse_text: Use Mouse Button 1 to select a TRACE KILL parameter file from the
parameter file menu.

parameter: REVERSE_FILE
text: Used to select a TRACE REVERSAL parameter file
type: function:
type_desc: ((parm_list RVS) parms)
value: no entry
selected_item: * No Parameter File has been Selected *
mouse_text: Use Mouse Button 1 to select a TRACE REVERSAL parameter file from
the parameter file menu.
exec_data: (PROG_NAME
(GENERAL
(version implicit: @(#)EXAMPLE.menu 40.1 11/24/92 )
(PARM1 implicit: (value CHOOSE1))
(PARM2 implicit: (value CHOOSE2))
(PARM3 implicit: (value CIRCULAR1))
(PARM4 implicit: (value SIMPLE_REAL))
(PARM5 implicit: (value FANCY_REAL))
(PARM6 implicit: (value SIMPLE_INTEGER))
(PARM7 implicit: (value FANCY_INTEGER))
(PARM8 implicit: (if (value BOOLEAN1) 1 0 ))
(PARM9 implicit: (value STRING1))
(PARM10 implicit: (value EDIT_STRING))
(PARM11 implicit: (value DATA_FILE))
(PARM12 implicit: (value HEADER_SELECT))
(PARM13 implicit: (value TIME_GATES))
(PARM14 implicit: (value MUTE_FILE))
(PARM15 implicit: (value VEL_FILE))
(PARM16 implicit: (value HORIZON_FILE))
(PARM17 implicit: (value KILL_FILE))
(PARM18 implicit: (value REVERSE_FILE))
)
)
rules: (
(rule1 ( = ( value SIMPLE_INTEGER ) 3 ) (do_show FANCY_REAL) (do_not_show
FANCY_REAL))
(rule2 ( > ( value FANCY_INTEGER ) 0 ) (do_show SIMPLE_REAL) (do_not_show
SIMPLE_REAL))
(rule3 (value BOOLEAN1) (progn (do_not_show STRING1)
(do_not_show EDIT_STRING)
(do_not_show HEADER_SELECT))
(progn (do_show STRING1)
(do_show EDIT_STRING)
(do_show HEADER_SELECT)))
)
)

Other Docs

Known Problems

EXAMPLE.menu556

Other Docs

Developers Programming Guide

Known Problems

557

Developers Programming Guide

Appendix: C Library Summary

This appendix provides a series of tables to describe the C


Library subroutines. To see the complete subroutine
description, use the aman routine to display the man page. For
example, aman DB_AREACOUNT will display the man page for
DB_AREACOUNT. For more information on using the aman
facility see the Man Page Reference chapter.

Topics covered in this appendix:

Other Docs

Error Routines502
Control Functions503
Parameter Input505
Configuration506
Database507
Memory Allocation/Management516
Trace Headers520
Trace Muting522
Velocity (Geophysical Routines)523
Vector Routines525
Parameter Lists525
Packet Files527
Parameter Interpolation528
Unix Interface529
IPCTools531
Parameter Tables537
PVM549
Matrix Functions556
Interpolation Routines559
Math Functions568
Signal Processing573

Known Problems

558

Developers Programming Guide

Plotting575
Data Structures576
Sorting and Searching580

Other Docs

Known Problems

Error Routines559

Developers Programming Guide

Error Routines
Error Routines

Other Docs

Subroutine

Description

exErrFatal

Prints error message before killing process

exErrMessage

Prints diagnostic message without killing process.

exErrWarn

Prints warning message without killing process.

exErrStop

Stops flow immediately, prints message, & calls tools in c

exErrHelp

Prompts user to select an option. An X window automatic


with the possible options. Options are in the string text an
by a vertical bar (|). For example: exErrHelp(choice 1|ch
3).

uErrFatal

Prints error message before killing process.

uErrMessage

Prints diagnostic message without killing process.

uErrWarn

Prints warning message without killing process. This is d


uErrMessage() in the preamble printed before the messag

uErrStop

Kills process and print a message. This is different from u


preamble.

uErrHelp

Prompts the user to select an option. An X window autom


with the possible options. The options are in the string fo
separated by a vertical bar (|). For example: uErrHelp(ch
2|choice 3,&ichoice).

Known Problems

Control Functions560

Developers Programming Guide

Control Functions
Control Functions

Other Docs

Subroutine

Description

exFillMode

Sets mode of the current tool to fill mode; no trace is retur


and one trace will be accepted in the next call of this tool

exFlushMode

Sets mode of the current tool to flush mode; one trace is r


call, and no trace will be accepted in the next call of this t

exPipeMode

Sets mode of the current tool to pipe mode; one trace is re


call, and one trace will be accepted in the next call of this
no other traces to input, the module will not be called aga

exPushMode

Sets mode of the current tool to push mode; one trace is r


call, and one trace will be accepted in the next call of this
routine will be called even if there are no more traces to i

exQuitMode

Sets mode of the current tool to quit mode; no more trace


this complex tool and no more are input.

exTraceHeadersOnlyOK

Called by a processing tool in initialization phase if the to


trace headers only. (By default, tools require traces.)

exPanelParms

Called by a processing tool in initialization phase if the to


process data in panels, either post-stack or pre-stack. This
large stacked sections or common-offset sections to be pr
panels that can fit in memory.

memCheckResBuf

Checks the memory buffers allocated by the ProMAX for


allocator, MEM_RESBUFF(). Does not check memory al
malloc(). This is useful if an array passed by a fortran rou
routine is being corrupted by the C routine.

Known Problems

Parameter Input561

Developers Programming Guide

Parameter Input
Parameter Input

Other Docs

Subroutine

Description

exParInfo

Gets information for a parameter.

exParNOccurs

Determines number of occurences of a parameter.

exParNValues

Determines number of values of a parameter.

exParExists

Determines whether the parameter exists in the packet file

exParFormat

Determines format of a parameter.

exParWordsPerValue

Determines number of words per value of a parameter.

exParGetInt

Gets integer values of a parameter.

exParGetIntN

Gets integer values of a parameter.

exParGetFloat

Gets float values of a parameter.

exParGetFloatN

Gets float values of a parameter.

exParGetDouble

Gets double values of a parameter.

exParGetString

Gets character string of a parameter.

exParGetStringN

Gets character string of a parameter.

getPar

General subroutine for getting a parameter that is compati


Stanford getpar() routines. The obselete occurence param
removed.

exParReturnInt

Gets integer value of a parameter.

exParReturnFloat

Gets float value of a parameter.

exParReturnString

Gets String of a parameter from packet files.

Known Problems

Configuration562

Developers Programming Guide

Configuration
Configuration

Other Docs

Subroutine

Description

configDevList

Returns a list of all of the devices of a particular type that


configuration file.

Known Problems

Database563

Developers Programming Guide

Database
Database

Other Docs

Subroutine

Description

opfCreate

Creates a new OPF.

opfExists

Determines whether an OPF exists.

opfParmInfo

Returns the description, length, and format of a paramete

opfParmFormat

Returns the format of a parameter.

opfParmLength

Returns the length of a parameter (in words).

opfParmExists

Determines whether the parameter exists.

dbCloseDomainProject

Closes and frees domain project capability initialized wit


dbInitDomainProject().

dbInitDomainProject

Initializes domain project capability which projects a pos


domain (such as CDP) into another one (such as Surface
is, what surface location corresponds to CDP 127.

dbCloseEnsembleMap

Closes and frees ensemble mapping capability initialized


dbInitEnsembleMap().

dbInitEnsembleMap

Initializes ensemble mapping capability which maps a par


elevation) from one domain (such as CDP) to another (su
location); that is, what is the elevation at the surface locat
CDP 127.

dbCloseTraceMap

Closes and frees trace mapping capability initialized with


dbInitTraceMap().

dbInitTraceMap

Initializes trace mapping capability which, given two loca


domain, gives the corresponding location in another doma
is the traceno of SIN 2 and CHN 88 (domain1 is SIN, dom
and domain3 is traceno).

dbDomainProject

Projects a position from one domain (such as CDP) into a


(such as Surface Location); dbInitDomainProject() must fi

dbEnsembleMap

Maps a parameter (such as elevation) from one domain (s


another (such as surface location); that is, what is the elev
surface location nearest to CDP 127.

dbTraceMap

Maps a parameter (such as elevation) from one domain (s


another (such as surface location); that is, what is the elev
surface location nearest to CDP 127.

opfOpen

Opens a database file; performs error checking.

opfClose

Closes a database file.

opfPut

Puts a value to the database.

Known Problems

Database564

Developers Programming Guide

Database (Continued)

Other Docs

Subroutine

Description

opfGet

Gets a value from the database.

opfGetChar

Gets a string from the database.

opfGetAll

Gets a range of values from the database.

opfGetRange

Gets a range of values from the database.

opfLock

Locks an ordered database file (open read/write).

opfParmCreate

Creates a parameter in the data base.

opfParmDelete

Deletes a parameter in the data base.

opfInitBufGet

Initializes getting a value from the database in a buffered

opfInitBufPut

Initializes putting a float value to the database in a buffere

opfBufGet

Gets values from the database in a buffered fashion.

opfBufPut

Puts values into the database in a buffered fashion.

opfBufPutFloat

Puts a float value to the database in a buffered fashion.

opfBufPutFloats

Puts a float value to the database in a buffered fashion.

opfBufGetInt

Gets int values from the database in a buffered fashion.

opfBufPutInt

Puts an integer value to the database in a buffered fashion

opfBufPutInts

Puts an integer value to the database in a buffered fashion

opfBufGetDouble

Gets double values from the database in a buffered fashio

opfBufPutDouble

Puts a float value to the database in a buffered fashion.

opfBufPutDoubles

Puts a double value to the database in a buffered fashion.

opfCloseBufGet

Closes Buffered input.

opfCloseBufPut

Closes Buffered output.

opfInitGetXY

Initializes getting the (X,Y) values for the location corres


database.

opfCloseGetXY

Closes getting the (X,Y) values for the location correspon


database.

opfGetXY

Gets the (X,Y) values for the location corresponding to a


actually a macro for two opfGet()s.

dbLineParmPut

Puts a global line parameter in the data base.

getHashName

Converts a character description to a full path name of the


type. The pathname has the proper directory of the area a
filename is produced by hashing the character description

Known Problems

Database565

Developers Programming Guide

Database (Continued)
Subroutine

Description

getFullName

Converts a file name, as read in from a packet file, to a fu


the parameter table. The pathname has the proper directo
and line.

opfGetParmDesc

Gets a description of a parameter from the ordered databa

opfPutFloat

Puts a float value to the database.

opfPutFloats

Puts several float values to a data base location that has le


than one.

opfPutDouble

Puts a double value to the data base.

opfPutDoubles

Puts several double values to a data base location that has


than one.

opfPutInt

Puts an integer value to the database.

opfPutInts

Puts an array of integer values to one location in the datab


length greater than one.

opfPutChar

Puts a string to the database.

opfPutAll

Puts a range of values to the database.

opfPutRange

Puts a range of values from the database.

opfInitPseudoLine
opfDeinitPseudoLine

Other Docs

opfDomain

Returns domain of opf pointer.

opfLastErr

Returns last error produced from an opf access.

opfLocMin

Returns minimum location of opf.

opfLocMax

Returns maximum location of opf.

opfNStored

Returns number of values stored per location.

opfParmList

Returns a character string containing the names of the par


particular info type. Includes parameters with no format (
Freeing the returned space is left to the user.

dbDataInt

Gets information on a data set, integer version; for standonly.

dbDataChar

Gets information on a data set, string version; for stand-a


only.

dbCreateParmFile

Creates and initializes a parameter file that can be used fo


in a non-standard table format.

dbOpenParmFile

Opens a parameter file that can be used for binary input in


table format.

Known Problems

Database566

Developers Programming Guide

Database (Continued)

Other Docs

Subroutine

Description

dbRewindParmFile

Positions file opened with dbOpenParmFile() at the end o


portion and at the beginning of the user data position.

dbInitSRFtoCDPmap

Determines mapping between Surface location coordinate


coordinates from input headers of traces. The mapping is
using the SRF_SLOC, SOU_SLOC, & CDP standard hea
header index is taken from the structure *stdHdr.

dbSRFtoCDPmap

Converts a surface location to a CDP location.

dbCDPtoSRFmap

Converts a CDP location to a surface location.

promaxPath

Get a Promax path name.

scratchSpace

Returns number of kilobytes in ProMAX scratch space.

opfLocInc

Returns the location increment in the ordered paramter fil

opfSoftRlse

Returns the software release in use when the OPF was cre

opfIgDate

Returns the creation date of the associated geometry.

opfIgTime

Returns the creation time of the associated geometry.

opf

Returns number of traces on the line when the geometry w

datasetHeaderFileExists

Specifies whether the table has an associated header file.

datasetReadHeaderFile

Reads the header file associated with a table into the Para

datasetWriteHeaderFile

Writes a parameter group into a header file associated wit

d3CDPToXY

Given a CDP, returns the corresponding X,Y coordinates

d3XYToCDP

Given an X,Y coordinate, returns the corresponding CDP


only).

d3XYToXline

Given an X,Y coordinate, returns the corresponding cross


(3D only).

d3XYToInline

Given an X,Y coordinate, returns the corresponding inlin


only).

d3LinesToCDP

Given an inline and crossline number, returns the corresp


number (3D only).

d3CDPToLines

Given a CDP number, returns the corresponding inline an


number (3D only).

d3LinesToXY

Given inline and crossline numbers, gets the correspondin


coordinates.

Known Problems

Memory Allocation/Management567

Developers Programming Guide

Memory Allocation/Management
Memory Allocation/Management

Other Docs

Subroutine

Description

promaxCheckmem

Checks whether the ends of any of the arrays allocated by


promaxMalloc() or promaxRealloc() have been overwritt

promaxRealloc

Similar to realloc() but checks whether the array has been


leaves marks for subsequent checking the ends of the arra

promaxMalloc

Similar to malloc() but leaves marks for subsequent check


the arrays.

promaxCalloc

Similar to calloc() but leaves marks for subsequent check


the arrays.

promaxFree

Similar to free() but checks whether array ends have been


before freeing.

alloc1

Allocates a 1-d array.

realloc1

Reallocates a 1-d array.

free1

Frees a 1-d array.

alloc2

Allocates a 2-d array.

free2

Frees a 2-d array.

alloc3

Allocates a 3-d array.

free3

Frees a 3-d array.

alloc4

Allocates a 4-d array.

free4

Frees a 4-d array.

alloc1int

Allocates a 1-d array of ints.

realloc1int

Reallocates a 1-d array of ints.

free1int

Frees a 1-d array of ints.

alloc2int

Allocates a 2-d array of ints.

free2int

Frees a 2-d array of ints.

alloc3int

Allocates a 3-d array of ints.

free3int

Frees a 3-d array of ints.

alloc1float

Allocates a 1-d array of floats.

realloc1float

Reallocates a 1-d array of floats.

free1float

Frees a 1-d array of floats.

alloc2float

Allocates a 2-d array of floats.

Known Problems

Memory Allocation/Management568

Developers Programming Guide

Memory Allocation/Management (Continued)

Other Docs

Subroutine

Description

free2float

Frees a 2-d array of floats.

alloc3float

Allocates a 3-d array of floats.

free3float

Frees a 3-d array of floats.

alloc1double

Allocates a 1-d array of doubles.

realloc1double

Reallocates a 1-d array of doubles.

free1double

Frees a 1-d array of doubles.

alloc2double

Allocates a 2-d array of doubles.

free2double

Frees a 2-d array of doubles.

alloc3double

Allocates a 3-d array of doubles.

free3double

Frees a 3-d array of doubles.

alloc1complex

Allocates a 1-d array of complexes.

realloc1complex

Reallocates a 1-d array of complexes.

free1complex

Frees a 1-d array of complexes.

alloc2complex

Allocates a 2-d array of complexes.

free2complex

Frees a 2-d array of complexes.

alloc3complex

Allocates a 3-d array of complexes.

free3complex

Frees a 3-d array of complexes.

memAllAllocated

Returns total memory allocated minus that freed, as speci


uordblks member of the structure returned from the syste
call.

memArenaSize

Returns size of the heap, as specified by the arena member


returned from the system mallinfo() call.

memBytesAllocated

Returns number of bytes allocated by this memory alloca

memAlloc1

Allocates a 1-d array.

memRealloc1

Reallocates a 1-d array.

memFree1

Frees a 1-d array.

Known Problems

Trace Headers569

Developers Programming Guide

Trace Headers
Trace Headers

Other Docs

Subroutine

Description

hdrInfo

Gets information for a trace header entry specified by nam

hdrIndexInfo

Gets information for a trace header entry specified by ind

hdrExists

Determines whether or not a header entry with specified n

hdrIndexExists

Determines whether or not a header entry with specified i

hdrDesc

Returns description of trace header entry specified by nam

hdrIndexName

Returns description of trace header entry specified by ind

hdrIndexDesc

Returns description of trace header entry specified by ind

hdrLength

Returns length (in words) of trace header entry specified b

hdrIndexLength

Returns length (in words) of trace header entry specified b

hdrFormat

Returns format of trace header entry specified by name.

hdrIndexFormat

Returns format of trace header entry specified by index.

hdrIndex

Returns index of trace header entry specified by name.

hdrAdd

Adds a new entry to trace header and return index.

hdrAddStd

Adds a standard entry to trace header.

defStdHdr

Defines the standard headers that must always be present

initStdHdr

Initializes the standard headers that must always be prese

initHdrs

Clears all header values. Sets the standard header entries t


trace to their defaults. Sets others that exist to reasonable

initHeaderManip

Initializes for later header interpolation.

headerInterpolate

Interpolates a header based on two other headers.

headerStack

Averages headers based on weights.

headerStackN

Averages serval headers.

isStdHdrName

Checks to see if hdrName is one of the standard headers.

Known Problems

Trace Muting570

Developers Programming Guide

Trace Muting
Trace Muting

Other Docs

Subroutine

Description

muteAlloc

Allocates and initializes a mute handler.

stMuteAlloc

Allocates and initializes a mute handler in a socket tool.

muteFree

Frees a mute handler.

muteGetTimes

Gets tapered mute start and end times from trace header.

muteSetTimes

Sets tapered mute start and end times in trace header.

muteApply

Applies tapered mutes to a trace.

muteSlide

Slides and applies tapered mutes according to first and las


samples.

muteFindZeros

Finds locations of zeroed samples in a trace.

muteRezero

Re-zeros samples that were previously zero and tapers su

Known Problems

Velocity (Geophysical Routines)571

Developers Programming Guide

Velocity (Geophysical Routines)


Velocity (Geophysical Routines)

Other Docs

Subroutine

Description

convertVTable

Converts velocity from one type to another; that is, RMS


time to Interval velocities in depth.

vIntStepConv

Converts RMS velocity to interval using constant velocity

resampleTbl

Resamples Table to regular intervals.

convert_v_table_

Fortran wrapper for convert_v_table().

tblToMatrix

Creates a matrix of velocities from a velocity table.

matrixToTbl

Puts a matrix of velocities into a velocity table.

smoothVelMatrix

Smooths a matrix of velocities.

getTblAvg

Gets the average value in a table.

getResampTblAvg

Gets the average value in table resampled to a regular grid

tblMixInterpXYu

Interpolates a vector of z(x,y) values, uniformly sampled i


x, but mixed in the X direction. The purpose of this subro
smooth the velocities for migrations.

avgTbl

Obselete function that is replaced by tblAvg().

tblAvg

Creates a one averaged velocity function V(z) from a vari


field, V(x,z). Averaging is spatially weighted, such that fu
weighted by the distance of their neighboring functions.

apertureVIT

Computes the maximum aperture for a velocity function (


tracing.

apertureVID

Computes the maximum aperture for a velocity function (i


tracing.

checkMigVelTbl

Checks velocities for migration. Bombs if velocites are n


Prints warnings if minimum velocity is less than 100, ma
is greater than 30000, and the ratio of the maximum to th
velocity is greater than 20.

interpVrmsPairsToVint

Computes uniformly sampled interval velocities to fit spe


vrms.

Known Problems

Vector Routines572

Developers Programming Guide

Vector Routines
Vector Routines

Other Docs

Subroutine

Description

vClr

Clears a vector.

vMov

Copies elements from one vector to another.

vsMul

Vector scalar multiply.

vAdd

Vector add: c[incc*i]= a[inca*i] + b[incb*i].

vsMA

Vector add: c[incc*i]= a[inca*i] * b + c[incc*i].

vFill

Fills a vector with a constant.

Known Problems

Parameter Lists573

Developers Programming Guide

Parameter Lists
Parameter Lists

Other Docs

Subroutine

Description

listAlloc

Allocates and initializes a new parameter list (for use with

listAllocInts

Allocates and initializes a new parameter list (for use with

listFree

Frees parameter List.

listReady

Signals List is ready.

listDescribe

Sets description of parameter list.

listAdd

Adds parameter starting value, ending value, and value in


parameter list.

listAddInts

Adds parameter starting value, ending value, and value in


parameter list.

listFromDatabase

Gets a parameter list from database.

listToDatabase

Puts a parameter list to database.

listDecode

Creates a list by decoding a character string.

listInfoUpdate

Gets information on a list.

listGet

Gets range of values for the bottom level.

listGetInts

Gets range of values for the bottom level.

listCheck

Checks whether a set of values is within the list range.

listCheckInts

Checks whether a set of values is within the list range.

Known Problems

Packet Files574

Developers Programming Guide

Packet Files
Packet Files

Other Docs

Subroutine

Description

pktFileClose

Closes a packet file.

pktFileCreate

Creates a packet file.

pktFileOpen

Opens a packet file.

pktInit

Initializes a packet in a packet file.

pktGroupInit

Initializes a group in packet in a packet file.

pktOutParmN

Puts multiple values for one parameter into the packet file

pktOutInt

Puts an integer parameter into the packet file.

pktOutFloat

Puts a float parameter into the packet file.

pktOutDouble

Puts a double parameter into the packet file.

pktOutString

Puts a double parameter into the packet file.

pktGetNGroups

Gets the number of groups in a packet file.

pktGroupCopy

Copies groups from one packet to another.

pktParmInfo

Gets information on a parameter in the packet file.

pktGroupInfo

Gets information on a group in the packet file.

pktGetMaxParmLength

Gets the maximum length of a parameter in a packet.

Known Problems

Parameter Interpolation575

Developers Programming Guide

Parameter Interpolation
Parameter Interpolation

Other Docs

Subroutine

Description

intGet

Interpolates/extrapolates z values at specified x and y.

intVecX1X2

Interpolates/extrapolates z values at specified x1, x2, and


sampled y. This is similar to intVec(), except the (x1,x2) c
passed instead of the routine determining them from the e
number using the Ordered Parameter Files.

intVec

Interpolates/extrapolates z values at specified x1, x2, and


sampled y.

interp

Interpolates z values at x1, x2, and y, for y = fy, fy+dy, ...

Known Problems

Unix Interface576

Developers Programming Guide

Unix Interface
Unix Interface

Other Docs

Subroutine

Description

maybeSearchPath

Checks to see if envvar is a search path indicated by cont


more :. If yes, searches one at a time for the existance o
hostname.

promaxHostPath

Returns the path to specific directories and files in the Pro


structure.

promaxPathName

Returns the path to specific directories and files in the Pro


structure. Local host-pecific version of promaxHostPath()

promaxPath

Returns the path to specific directories and files in the Pro


structure. Backward-compatible version of promaxPathN

promax_path_

Returns the path to specific directories and files in the Pro


structure. Fortran wrapper for promaxPath().

promaxHostExtPath

Returns array of paths to specific directories and files in t


extended directory structure.

promaxExtPath

Returns array of paths to specific directories and files in t


extended directory structure for the calling host.

promaxLinePath

Returns full path name of current ProMAX Line. Calls


promaxPathName() and concatenates the globalChar->ca
globalChar->cline.

promaxFlowPath

Returns full path name of current ProMAX Flow. Calls


promaxPathName() and concatenates the globalChar->ca
globalChar->cline.

diskAvail

A nicer interface for determining the amount of disk spac


directory.

cpusec

Returns cpu time (UNIX user time) in seconds.

cputime

Returns cpu time (UNIX user time) in seconds using ANS

wallsec

Returns elapsed time (wall clock time) in seconds.

walltime

Returns elapsed time (wall clock time) in seconds using A


Return value will be an integral number of seconds since
returned by the time() intrinsic, are the number of second
epoch.

Known Problems

IPC Tools577

Developers Programming Guide

IPC Tools
IPC Tools

Other Docs

Subroutine

Description

isParallelTool

Specifies whether this module is being executed as a para

pstConnectToServer

Establishs connection from a parallel socket tool to the Pr


processing flow.

stConnectToServer

Establishs connection to the ProMAX processing flow.

stSetToolName

Establishes the tool name.

stGetTrace

Reads in a trace from the ProMAX flow into a socket too

stEOFReached

Determines whether a previous data read reached an EOF

stGetEnsemble

Reads in an Ensemble from the ProMAX flow into a sock

pstGetEnsemble

Reads in an Ensemble from the ProMAX flow into a sock

stPutTrace

Writes in a trace to the ProMAX flow.

stPutEnsemble

Writes an Ensemble to the ProMAX flow.

pstPutEnsemble

Writes an Ensemble to the ProMAX flow.

stCloseSocketLink

Closes the socket link to the ProMAX flow.

stStopFlow

Stops the ProMAX flow immediately.

stPassSocketLink

Closes the socket link to the ProMAX flow, but has the flo
pass traces so the flow continues without this tool.

stEndInitialization

Signals the end of program initialization to the ProMAX


causes the init phase of the flow to return. After this call,
be sent and received.

stInputTool

Specifies that the tool is an input tool.

stEnableExitContinue

Enables a socket tool to later call stPassSocketLink(). Thi


be called in the init phase so that stEnableExitContinue()
called in the exec phase.

stGetStdHdr

Gets the standard header indexes.

stHdrAdd

Adds a header to the data; see also sHdrAddStd().

stHdrIndexName

Gets the name associated with a header index.

stHdrAddStd

Adds a ProMAX standard header to the data. The descrip


format are read from system files.

stHdrExists

Determines whether a header entry exists.

stHdrDesc

Gets the description associated with a header entry.

stHdrIndex

Gets the index of a header.

Known Problems

IPC Tools578

Developers Programming Guide

IPC Tools (Continued)

Other Docs

Subroutine

Description

stHdrLength

Gets the length of a header word.

stHdrFormat

Gets the format of a header.

stSetOutPanels

Sets Panel dimensions for later panel output. If stSetPanel


this is not, it is assumed that the output panel dimensions
to the input panel dimensions.

stSetPanels

Sets Panel dimensions for later panel input and output. Th


the normal executive panel tool, except that the executive
the choices of panel parameters. The purpose of this tool
group of traces, like a portion of an ensemble or stacked s
managable in a limited amount of memory. Each group o
treated as a sub-ensemble. The groups can be overlapping
effects. The groups are recombined on output. If data is s
of stacked traces is passed; if data is not stacked, only tho
the end of the ensemble is passed. So, a migration does no
if it is working with stacked data or a series of NMOd, D
offset sections. Or, FK filter does not need to know if it is
gather or stacked data.

stGetPanel

Reads in a panel of traces.

stPutPanel

Writes out a panel of traces.

stErrFatal

Prints error message before killing process.

stErrMessage

Prints diagnostic message (without killing process).

stErrWarn

Prints warning message (without killing process).

stErrHelp

Prompts the user to select an option. An X window autom


with the possible options. The options are in the string tex
separated by a vertical bar (|). For example: stErrHelp(ch
2|choice 3).

stCheckConnection

Checks whether socket link to the executive is still alive.

stSetDiskIter

Causes Disk Data Input to iterate over the list of input tra

stStatMemReserve

Tells the executive how much memory the IPC tools will
calls increment the memory usage.

st_connect_to_server_

Establishes connection to the ProMAX processing flow.

st_set_tool_name_

Establishes the tool name.

st_get_trace_

Reads in a trace from the ProMAX flow into a socket too

st_eof_reached_

Determines whether a previous data read reached an EOF

st_get_ensemble_

Reads in an Ensemble from the ProMAX flow into a sock

st_put_trace_

Writes in a trace to the ProMAX flow.

st_put_ensemble_

Writes an Ensemble to the ProMAX flow.

Known Problems

IPC Tools579

Developers Programming Guide

IPC Tools (Continued)

Other Docs

Subroutine

Description

st_close_socket_link_

Closes the socket link to the ProMAX flow.

st_end_init_

Signals the end of program initializtion to the ProMAX fl


the init phase of the flow to return. After this call, only tra
and received.

st_input_tool_

Specifies this tool as an input tool.

st_hdr_add_

Adds a header to the data; see also ST_HDR_SRD_ADD

st_hdr_std_add_

Adds a ProMAX standard header to the data. The descrip


format are read from system files.

st_set_panels_

Sets Panel dimensions for later panel input and output. Th


the normal executive panel tool, except that the executive
the choices of panel parameters. The purpose of this tool
group of traces, like a portion of an ensemble or stacked s
managable in a limited amount of memory. Each group o
treated as a sub-ensemble. The groups can be overlapping
effects. The groups are recombined on output. If data is s
of stacked traces is passed; if data is not stacked, only tho
the end of the ensemble is passed. So, a migration does no
if it is working with stacked data or a series of NMOd, D
offset sections. Or, FK filter does not need to know if it is
gather or stacked data.

st_get_panel_

Reads in a panel of traces.

st_put_panel_

Writes out a panel of traces.

Known Problems

Parameter Tables580

Developers Programming Guide

Parameter Tables
Parameter Tables

Other Docs

Subroutine

Description

tblAllocate

Allocates and initializes a new parameter table for z(x,y).

tblAllocTb3

Makes a tbl out of a tb3.

tblAllocTmp

Allocates and initializes a temporary parameter table for z


case in which true spatial coordinates can be ignored.

tblFree

Frees parameter table.

tblFetchTb3

Returns the underlying tb3 so that the tb3 functions can b

tblSetExtrap

Sets x and y extrapolation methods.

tblResolveX1X2

Given an X (ensemble number), returns the spatial coordi


used within the table functions.

tblAddXY

Adds z value(s) at specified (x,y) point.

tblAddXYs

Adds z value(s) for an array of y coordinates and constan

tblGetX

Gets X location from a table. This is identical to calling: t


ix_counter, 0, x_loc, NULL, NULL, NULL ). This routin
gaurantee the functions are retrieved in order of increasin

tblGetEnsemble

Gets ensemble number (X location) (CDP,SIN,etc) for a g


in order of increasing X.

tblCopy

Copies all groups from tbl2 to tbl1. tbl1 does not have to

tblRMStoDIP

Converts a azimuthally varying Dip-Vels velocity field to


field.

tblGetXYs

Gets X-Y-Z group from a table. This routine does not gua
functions are retrieved in order of increasing X.

tblDeleteXY

Deletes z value(s) at specified (x,y) point.

tblDeleteX

Deletes all z value(s) at specified x coordinate.

tblClear

Clears all entrys in a table.

tblInterpXY

Interpolates z(x,y) value(s) at specified (x,y) point.

tblInterpXYu

Interpolates a vector of z(x,y) values, uniformly sampled i


x.

dbTblUpdate

Updates a table using the OPFs.

tblDescFromDatabase

Gets a table description from database using the hash labe


is needed because the menu can return the hash name of a
(using Add option) table for output. To save the table, how
the description. See also tblToDatabaseHashName.

Known Problems

Parameter Tables581

Developers Programming Guide

Parameter Tables (Continued)

Other Docs

Subroutine

Description

tblGetType

Gets three letter code that identifies the table type.

tblSetType

Sets three letter code that identifies the table type.

tblFromDatabase

Gets a parameter table from database.

tblToDatabaseHashName

Puts a parameter table to database using a hash label. Thi


be used when the menu returns the hash name of a table.
copies the description of that table into the description of
written. A Fatal error occurs if the table does not already

tblToDatabase

Puts a parameter table to database.

tblHeaderFileExists

Specifies whether the table has an associated heaer file.

tblReadHeaderFile

Reads the header file associated with a table into the Para

tblWriteHeaderFile

Writes a parameter group into a header file associated wit

tblFromVelPar

Loads a parameter table from a location:times-vels type o


string.

tblXMin

Gets minimum X value for table. For 2D tables, this is the


tblX1Min(). For 3D tables, this is ensemble number while
coordinate.

tblXMax

Gets maximum X value for table. For 2D tables, this is th


tblX1Max(). For 3D tables, this is ensemble number whil
coordinate.

tblMinMax

Gets several maximum and minimum values for table. If N


for an address, that value is not returned.

tblX1Min

Gets minimum X1 value for table.

tblX1Max

Gets maximum X1 value for table.

tblX2Min

Gets minimum X2 value for table.

tblX2Max

Gets maximum X2 value for table.

tblYMin

Gets minimum Y value for table.

tblYMax

Gets maximum Y value for table.

tblZMax

Gets maximum Z value for table. This function assumes o


per node.

tblZMin

Gets minimum Z value for table. This function assumes o


per node.

tblCountX

Gets number of locations in table.

tblCountMaxY

Gets maximum number of samples per node in a table.

tblCountZ

Gets number of z values per sample in a table.

Known Problems

Parameter Tables582

Developers Programming Guide

Parameter Tables (Continued)

Other Docs

Subroutine

Description

tblDesc

Gets table description.

tblDescX

Gets table X description.

tblDescY

Gets table Y description.

tblDescZ

Gets table Z description.

tblEqual

Checks whether two tables have identical values.

tblSetYZ

Adds z value(s) for y coordinates and constant (x1,x2) co

tblDeleteYZ

Deletes z value(s) at specified ( (x1,x2),y) point.

tblDelete

Deletes all z value(s) at specified (x1,x2) coordinate.

tblInterpZ

Interpolates a vector of z( (x1,x2) ,y) values, uniformly sa


constant x.

tblIndexX

Gets node coordinates by index from table.

tblGetYZ

Gets sample coordinates and values from an existing nod

tb3Alloc

Allocates a new empty table.

tb3Free

Frees a table.

tb3SetData

Sets user-specified data in node of table. If node does not e


with the specified data. If data exists, replaces it.

tb3SetYZ

Sets samples in node of table. If node does not exist, mak


specified samples. If samples exist at specified y, replaces

tb3SetExtrapY

Sets method used to extrapolate in y.

tb3GetTri

Gets pointer to the triangulation structure used for the tab

tb3GetData

Gets user-specified data from an existing node of table.

tb3GetYZ

Gets sample coordinates and values from an existing nod

tb3GetZ

Gets sample values from an existing node in table.

tb3GetExtrapY

Gets method used to extrapolate in y.

tb3InterpZ

Interpolates z values at specified node and sample coordin

tb3DeleteData

Deletes user-specified data from an existing node in table


no samples, deletes the node.

tb3DeleteYZ

Deletes sample coordinates and values from an existing n


the node has no user-specified data, deletes the node.

tb3Delete

Deletes an existing node from table.

tb3CleanData

Removes nodes with no data, if any exist.

tb3CleanYZ

Removes nodes with no samples, if any exist.

Known Problems

Parameter Tables583

Developers Programming Guide

Parameter Tables (Continued)

Other Docs

Subroutine

Description

tb3NearestX

Finds node nearest to specified node coordinates.

tb3NearestY

Finds sample nearest to specified sample coordinate in ex


table.

tb3UniformY

Determines if node is sampled uniformly.

tb3CountX

Gets number of nodes in table.

tb3CountY

Gets number of samples from an existing node in table.

tb3CountZ

Gets number of z values per sample in a table.

tb3CountMaxY

Gets maximum number of samples per node in table.

tb3DeltaY

Gets sampling interval from an existing node in table.

tb3FirstY

Gets first sample coordinate from an existing node in tabl

tb3IndexX

Gets node coordinates by index from table.

tb3IndexY

Gets sample coordinates by index from table.

tb3HasX

Determines if a node exists in a table.

tb3HasY

Determines if a sample exists in an existing node in a tabl

tb3InsideX

Determines if point is inside convex hull of nodes in a tab

tb3InsideY

Determines if sample is inside the range of sample coordi


existing node in table.

tb3InsideMinY

Determines if sample is inside the minimum range of sam


that would be used to interpolate/extrapolate.

tb3InsideMaxY

Determines if sample is inside the maximum range of sam


that would be used to interpolate/extrapolate.

tb3InsideLinY

Determines if sample is inside the linearlyinterpolated/constant-extrapolated range of samples in no


be used to interpolate/extrapolate.

tb3MinMax

Returns minimum and maximum node and sample coordi


sample values.

makeSamples

Allocates and initializes samples. If ny==0, samples are n


NULL is returned. If y==NULL, uniform sampling is spe
fy.

killSamples

Frees samples.

sortSamples

Sorts samples by increasing y coordinate.

removeDuplicateSamples

Removes duplicate samples (those which have identical y

uniformSamples

Returns 1 if sampling is uniform; 0, otherwise. If samplin


frees space used to store sample coordinates.

Known Problems

Parameter Tables584

Developers Programming Guide

Parameter Tables (Continued)

Other Docs

Subroutine

Description

setSample

Sets sample and returns updated samples.

deleteSample

Deletes sample, if it exists, and returns updated samples.

findSample

Returns index of sample with coordinate yFind; returns found.

locateSample

Determines largest iy such that y[iy] < yLocate or y[iy] =


where == is defined by the APPROX macro. If yLocate
-1. If y[iy] == yLocate (as defined by APPROX), returns
returns 0.

makeNode

Makes a new node, with samples and data attached.

killNode

Deletes a node, if the node exists. User-specified data is n

makeSortedNodes

Returns array of nodes sorted by x1; if no nodes, returns N

killSortedNodes

Deletes array of nodes sorted by x1, if the array exists.

findNode

Returns node (x1,x2), if it exists; otherwise, returns NUL

initNodeState

Initializes/resets the roving node and its coordinates.

cleanNodes

Cleans up nodes by removing nodes with no data and/or s


what=0, removes nodes with no data. For what=1, remove
samples.

makeTempBoundaryNodes

Creates temporary boundary nodes, if necessary, to facilit


interpolation.

killTempBoundaryNodes

Destroys all temporary boundary nodes.

interpNode

Linearly interpolates/extrapolates z values at the specified

makeInterpABC

Computes interpolation coefficients a,b,c for z = a + b*x1

updateInterpNodes

Updates nodes relevant for interpolation at node coordina


Returns 1 if nodes were changed; 0, otherwise.

makeInterp

Makes table interpolator.

killInterp

Kills table interpolator.

updateInterp

Updates the table interpolator; if it does not exist, makes

Known Problems

PVM585

Developers Programming Guide

PVM
PVM

Other Docs

Subroutine

Description

pvm_pvmd

Starts pvm daemon, if one is not already running, and enr


pvm.

pvm_rMinContext

Returns minimum valid value for an context label

pvm_rMaxContext

Returns maximum valid value for an context label

pvm_rMinMsgtag

Returns minimum valid value for a message tag

pvm_rMaxMsgtag

Returns maximum valid value for a message tag

pvm_rmsgtomsg

Converts contextualized message tag to ordinary PVM m

pvm_rnewContext

Generates a unique context number

pvm_rcurrentContext

Returns current context number (does not change context

pvm_rsetContext

Sets context number to new value

pvm_rbufinfo

Returns information about the requested message buffer

pvm_rsend

Immediately sends the data in the active message buffer

pvm_rmcast

Multicasts the data in the active message buffer to a set of

pvm_rbcast

Immediately broadcasts the data in the active message bu


group
**********************************************
********************
Input: group name of an existing group context message c
<=
context <= CONTEXT_MAX) msgtag message tag suppl
<= msgtag
<= MSG_MAX) Returned: >= 0 -> success ; < 0 -> error

pvm_rrecv

Blocks until a message with specified context and messag


arrived from the specified source, and places message in a
receive buffer

pvm_rnrecv

Non-blocking receive

pvm_rrecvm

Accepts one of a list of messages from receive queue

pvm_rnrecvm

Accepts one of a list of messages from receive queue (no

pvm_rprobe

Determines whether specified message is in the receive qu

pvm_rprobem

Determines whether one of list of messages is in receive q

pvm_crecv

PVM checking re-entrant receive. This receive acts like a


receive if the sending process is still alive. If the sending p
function returns with the error PvmNoTask.

Known Problems

PVM586

Developers Programming Guide

PVM (Continued)

Other Docs

Subroutine

Description

pvm_rcrecv

PVM checking re-entrant receive. This receive acts like a


receive if the sending process is still alive. If the sending p
function returns with the error PvmNoTask.

pvm_rcrecvm

PVM checking re-entrant multiple receive. This receive a


blocking receive if the sending process is still alive. If the
dies, this function returns with the error PvmNoTask.

pvm_rmrecv

Accepts a message from one of a list of tasks

pvm_rmnrecv

Accepts a message from one of a list of tasks (non-blocki

pvm_rcmrecv

PVM checking re-entrant multicast receive. This receive


blocking multi-receive if the sending processes are still al
message queue is empty and a sending process dies, this f
with the error PvmNoTask.

packenvstring

Packs an environment into a single null-terminated string


string, the environmental variable strings are delimited by
characters.

getenvstring

Packs the environment into a single null-terminated string


string, the environmental variable strings are delimited by
characters.

parenviron

Parses the packed environment string created by getenvst


returns an array of environmental variable strings

initPvmtool

Connects to parent ProMAX processing flow, sets up envi


packet file, and initializes database

setPvmtoolType

Sets state to a valid ProMAX tool type

execPvmtool

Signals exec that initialization of this tool is complete and


to begin execution.

endPvmtool

Tells exec that this tool has finished, and leaves PVM

ptAtEOF

Informs whether EOF has been reached

ptGetTrace

Gets a trace from the parent ProMAX flow

ptPutTrace

Sends a trace to the parent ProMAX flow

ptGetEnsemble

Gets an ensemble from the parent ProMAX flow

ptPutEnsemble

Sends an ensemble to parent ProMAX flow

ptSetPanels

Sets panel dimensions for later input and output

ptSetOutPanels

Sets output panel dimensions

ptGetPanel

Gets a panel of traces from the parent ProMAX flow

ptPutPanel

Sends a panel of traces to the parent ProMAX flow

ptSndPromaxHeader

Sends ProMAX header to another PVM process

Known Problems

PVM587

Developers Programming Guide

PVM (Continued)

Other Docs

Subroutine

Description

ptRcvPromaxHeader

Receives ProMAX header from another PVM process

ptSndPromaxGlobals

Sends ProMAX global data structures

ptRcvPromaxGlobals

Receives ProMAX global data structures

ptSndPromaxToolType

Sends ProMAX tooltype to another PVM process

ptRcvPromaxToolType

Sends ProMAX tooltype to another PVM process

dbInitLine

Initializes database for given line and area

rcvProtocolInfo

Receives data transfer protocol information from parent p

rcvPacketFile

Receives a packet file from parent and opens it for this to

sndDone

Sends a finished signal to the ProMAX exec

socket_send

Sends message to another process via socket

socket_recv

Receives message from another process via socket

unixSocketConnect

Creates a client endpoint of a Unix socket connection and


server

inetSocketConnect

Creates a client endpoint of a INET socket connection an


server

pkPromaxHeader

PVM pack ProMAX header

upkPromaxHeader

Receives ProMAX header from another PVM process

pkGlobalAcquis

Sends ProMAX global acquisition info to another PVM p

upkGlobalAcquis

Receives ProMAX global acquisition info from another P

pkGlobalChar

Sends ProMAX global character info to another PVM pro

upkGlobalChar

Receives ProMAX global character info from another PV

pkGlobalCoord

Sends ProMAX global coord info to another PVM proces

upkGlobalCoord

Receives ProMAX global coord info from another PVM p

pkGlobalGeom

Sends ProMAX global geometry info to another PVM pr

upkGlobalGeom

Receives ProMAX global geometry info from another PV

pkGlobalMisc

Sends ProMAX global misc info to another PVM process

upkGlobalMisc

Receives ProMAX global misc info from another PVM p

pkGlobalRuntime

Sends ProMAX global runtime info to another PVM proc

upkGlobalRuntime

Receives ProMAX global runtime info from another PVM

pkGlobalXY

Sends ProMAX global XY info to another PVM process

upkGlobalXY

Receives ProMAX global XY info from another PVM pr

Known Problems

Matrix Functions588

Developers Programming Guide

Matrix Functions
Matrix Functions

Other Docs

Subroutine

Description

dgefa

Gaussian elimination to obtain the LU factorization of a m

dgeco

Gaussian elimination to obtain the LU factorization and c


number of a matrix

dgesl

Solves linear system Ax = b or Ax = b after LU factoriza

sgefa

Gaussian elimination to obtain the LU factorization of a m

sgeco

Gaussian elimination to obtain the LU factorization and c


number of a matrix

sgesl

Solves linear system Ax = b or Ax = b after LU factoriza

sqrdc

Uses Householder transformations to compute the QR de


an n by p matrix x. Column pivoting based on the 2-norm
columns may be performed at the users option.

sqrsl

Uses the output of sqrdc to compute coordinate transform


projections, and least squares solutions. For k <= MIN(n,
matrix xk = (x[jpvt[0]], x[jpvt[1]], ..., x[jpvt[k-1]]) formed
jpvt[0], jpvt[1], ..., jpvt[k-1] of the original n by p matrix
to sqrdc. (If no pivoting was done, xk consists of the first
in their original order.) sqrdc produces a factored orthogo
and an upper triangular matrix R such that xk = Q * (R) (
information is contained in coded form in the arrays x and

sqrst

Computes least squares solutions to the system Xb = y wh


either under-determined or over-determined. The user ma
tolerance to limit the columns of X used in computing the
effect, a set of columns with a condition number approxim
by 1/tol is used, the other components of b being set to ze

stoepd

Solves a symmetric Toeplitz linear system of equations Rf


version)

tridif

Solves a tridiagonal linear system of equations Tu=r for u

vanded

Solves Vandermonde system of equations Vx=b (double v

vandef

Solves Vandermonde system of equations Vx=b (float ver

isamax

Returns index of element with maximum absolute value

sasum

Returns sum of absolute values

saxpy

Computes y[i] = y[i]+a*x[i]

scopy

Copies x[i] to y[i] (i.e., set y[i] = x[i])

sdot

Returns sum of x[i]*y[i] (i.e., return the dot product of x

Known Problems

Matrix Functions589

Developers Programming Guide

Matrix Functions (Continued)

Other Docs

Subroutine

Description

snrm2

Returns square root of sum of squares of x[i] (i.e. length o

sscal

Computes x[i] = a*x[i]

sswap

Swaps x[i] and y[i]

Known Problems

Interpolation Routines590

Developers Programming Guide

Interpolation Routines
Interpolation Routines

Other Docs

Subroutine

Description

cmonot

Computes cubic interpolation coefficients via the Fritschwhich preserves monotonicity

cakima

Computes cubic interpolation coefficients via Akimas m

csplin

Computes cubic spline interpolation coefficients for inter


continuous second derivatives

dsinc

Returns sinc(x) = sin(PI*x)/(PI*x) (double version)

fsinc

Returns sinc(x) = sin(PI*x)/(PI*x) (float version)

intcub

Evaluate y(x), y(x), y(x), ... via piecewise cubic interpo

intl2b

Bilinear interpolation of a 2-D array of bytes

intl2bx

Interpolates between input x values (FOR INTERNAL U

intl2by

Interpolates between input y values (FOR INTERNAL U

intlin

Evaluates y(x) via linear interpolation of y(x[0]), y(x[1]),

ints8c

Interpolation of a uniformly-sampled complex function y(


8-coefficient sinc approximations; maximum error for fre
than 0.6 nyquist is less than one percent

ints8r

Interpolation of a uniformly-sampled real function y(x) v


8-coefficient sinc approximations; maximum error for fre
than 0.6 nyquist is less than one percent

intt8c

Interpolation of a uniformly-sampled complex function y(


8-coefficient interpolators

intt8r

Interpolation of a uniformly-sampled real function y(x) v


coefficient interpolators

mksinc

Computes least-squares optimal sinc interpolation coeffic

yclip

Clips a function y(x) defined by linear interpolation of the


sampled values: y(fx), y(fx+dx), ..., y(fx+(nx-1)*dx). Retu
of samples in the clipped function.

yxtoxy

Computes a regularly-sampled, monotonically increasing


from a regularly-sampled, monotonically increasing func
inverse linear interpolation

tinAlloc

Allocates a new (empty) triangulated interpolator

tinFree

Frees a triangulated interpolator

tinAdd

Adds an array of z values at the specified x,y

tinAddWithData

Adds an array of z values and user-specified data at the sp

Known Problems

Interpolation Routines591

Developers Programming Guide

Interpolation Routines (Continued)

Other Docs

Subroutine

Description

tinData

Returns user-specified data nearest to the specified x,y

tinDelete

Deletes the array of z values nearest to the specified x,y

tinInterp

Interpolates/extrapolates z at specified x,y

tinInterpRange

Interpolates/extrapolates a range of zs at specified x,y

tinInterpZ

Interpolates/extrapolates one z value with index iz at spec

tinTri

Returns the triangulation for a triangulated interpolator

interp0

Method=0 interpolation of z values at specified x,y

interp1

Method=1 interpolation of z values at specified x,y

makeNodeData

Allocates space for node data and set its members

makeTempNodeData

Allocates space for temporary boundary node data and se

deleteNode

Deletes specified node and its data, and invalidate gradien

killNodeData

Frees space for node data

naborNodes

Returns null-terminated list of nodes that are nabors of th

makeGradients

Computes gradients for one node

shfs8r

Shifts a uniformly-sampled real-valued function y(x) via


8-coefficient sinc approximations; maximum error for fre
than 0.6*nyquist is less than one percent.

triAlloc

Allocates a new (empty) triangulation

triFree

Frees a triangulation

triAddNode

Adds point (x,y) to triangulation t and return node

triDeleteNode

Deletes node from triangulation

triNearestNode

Finds node in triangulation that is nearest to a point (x,y)

triNearestNodes

Finds the n nodes in triangulation that are nearest to the p

triLocatePoint

Locates point (x,y) in triangulation t

triBaryCoords

Computes barycentric coordinates of a point (x,y) in a tri

triAddTempBoundaryNode

If the node opposite any boundary edge is near enough to


far enough from the its endpoints, creates and returns a te
between the endpoints of the edge; otherwise, returns NU

triTempBoundaryNode

If any temporary boundary nodes exist, returns one; other


NULL

triIsBoundaryNode

Determines whether or not a node is a boundary node

triIsTempBoundaryNode

Determines whether or not a node is a temporary boundar

Known Problems

Interpolation Routines592

Developers Programming Guide

Interpolation Routines (Continued)

Other Docs

Subroutine

Description

insertNodeBefore

Inserts node m before node n into node list of triangulatio

killNode

Destroys node n in triangulation t

makeNabor

Makes node m a neighbor in a new list of neighbors of no

makeNaborAfter

Makes node l a neighbor after node m in list of neighbors

killNabor

Deletes node m from list of neighbors of node n

naborForNode

Returns neighbor corresponding to node m from list of ne


n

makeNodeInside

Makes node inside triangle defined by nodes n1, n2, and n


counter-clockwise

makeNodeOutside

Makes node outside boundary; connects the new node n t


nodes between n1 and n2 inclusive, where n1 is the leftm
from n) node on the boundary that is visible from n, and n
rightmost node on the boundary visible from n

makeNodeOnLine

Makes node on line of co-linear nodes; connects the new


n1 and n2. If n2 is NULL, then n1 is assumed to be an en
new mnode n will become the new end node. If n2 is not
is assumed to be left of n2.

makeNodeOffLine

Makes node off line of co-linear nodes; connects the new


nodes in line

afterMakeNode

After adding a new node to a valid triangulation, swaps e


necessary to obtain a Delaunay triangulation

beforeKillNodeInside

Prepares to kill an interior node of a triangulation. Swaps


Delaunay triangulation will result when node is disconne

beforeKillNodeOutside

Prepares to kill a boundary node of a triangulation. Swaps


Delaunay triangulation will result when node is disconne

killNodeInside

Destroys interior node of a triangulation

killNodeOutside

Destroys node on boundary of triangulation, with remaini


co-linear

killTempBoundaryNodes

Kills all temporary nodes on boundary of triangulation

killNodeOnLine

Destroys node on line of co-linear nodes

killNodeOffLine

Destroys node off line of co-linear nodes

oppositeNode

Returns node opposite n1, on the other side of edge n2-n3


n1,n2,n3 are currently triangle vertices in counter-clockw
Returns NULL if edge n2-n3 is a boundary edge.

swapTest

Determines whether or not to replace edge n2-n3 with ed


quadrilateral, in which n1,n2,n3 are currently triangle ver
counter-clockwise order. Returns non-zero iff swap shoul

Known Problems

Interpolation Routines593

Developers Programming Guide

Interpolation Routines (Continued)

Other Docs

Subroutine

Description

swapTestDelete

Determines whether or not to swap edge n-n2 with edge n


node n is going to be destroyed and n1, n2, and n3 are thr
nodes now connected to n, ordered counter-clockwise. Re
iff swap should be performed.

swapEdge

Replaces edge n2-n3 with edge n1-n4 in convex quadrilat


n1,n2,n3 are currently triangle vertices in counter-clockw

locatePoint

Locates point (x,y) inside or outside triangulation t

locateOutside

Locates point (x,y) outside (or on) boundary of triangulat

visibleNodes

Finds leftmost and rightmost boundary nodes visible from

otherNodesColinear

Determines if all nodes except this one are co-linear

circum

Computes center and radius-squared of circumcircle of a

nodeInCircum

Determines if node is inside circumcircle of triangle

nodeInTri

Determines if node is inside triangle

perturb

Perturbs a float into a Double with pseudo-random least-s

checkNode

Ensures node is valid; used for debugging

checkTri

Ensures triangulation is valid; used for debugging

ct2Init

Given three pairs of 2D position vectors expressed in two


systems, determines and saves transformation information
transformation of vectors from one coordinate system to t
calls to ct2Transform()

ct2Transform

Transforms a 2D vector from one coordinate system to an

ress8c

Resamples a uniformly-sampled complex function y(x) v


sinc approximations; maximum error for frequiencies les
nyquist is less than one percent

ress8r

Resamples a uniformly-sampled real function y(x) via 8-c


approximations; maximum error for frequiencies less than
less than one percent

Known Problems

Math Functions594

Developers Programming Guide

Math Functions
Math Functions

Other Docs

Subroutine

Description

tokensCreate

Splits a string into null-terminated tokens

tokensCompress

Removes whitespace from tokens

tokenInt

Converts token to int; for example, token=2 yields i=2

tokenPairInt

Converts token to pair of ints; for example, token=2--3


i2=-3

tokenReplicatedInt

Converts token to replicated int; for example, 2(3) yield

tokenIteratedInt

Converts token to iterated int; for example, token=2-6(2


d=2, i=2

tokenDecodeInts

Decodes int tokens specified in a compact style to an arra


example, string=-5 - -1(2), 0, 1-3(1),4(2) yields n=9 and
0, 1, 2, 3, 4, 4}

tokenFloat

Converts token to float; for example, token=2.34 yields

tokenPairFloat

Converts token to pair of floats; for example, token=2--3


f2=-3.2

tokenReplicatedFloat

Converts token to replicated float; . 2.34(3) yields n=3,

tokenIteratedFloat

Converts token to iterated float; for example, token=2-3(


d=0.5, f=2

tokenDecodeFloats

Decodes float tokens specified in a compact style to an arr


example, string=-2--1.4(0.2),0,1-2.5(0.5),3(2) yields n=
-1.8, -1.6, -1.4, 0, 1, 1.5, 2, 2.5, 3, 3}

tioOpen

Opens a file for buffered typed I/O (uses fopen)

tioOpenU

Opens a file for unbuffered typed I/O (uses open)

tioClose

Closes a file that was opened by tioOpen or tioOpenU

stateFromHandle

Converts a file handle into a pointer

tioPrintOpenFiles

Prints the state of all open files

tioSetSwapflag

Establishes the need for byte swapping on a file that was


tioOpen or tioOpenU. This routine or tioReadSwapflag m
before any I/O is done on a file.

tioUnsetSwapflag

De-establishes the need for byte swapping on a file

tioReadSwapflag

Establishes the need for byte swapping on a file that was


tioOpen or tioOpenU. This routine or tioSetSwapflag mu
before any I/O is done on a file.

tioResizeBuff

Ensures that the work buffer is large enough

Known Problems

Math Functions595

Developers Programming Guide

Math Functions (Continued)

Other Docs

Subroutine

Description

tioEof

Checks the end-of-file indicator for a open file

tioSync

Performs sync on a file (flushes buffers to disk)

tioSetLock

Locks a file (denying access to other processes)

tioCheckLock

Checks to see if a file is locked by another process

tioFcntl

Does I/O control on an open file

airya

Returns approximation to the Airy function Ai(x)

airyap

Returns approximation to the derivative of the Airy funct

airyb

Returns approximation to the Airy function Bi(x)

airybp

Returns approximation to the derivative of the Airy funct

idamax

Returns index of element with maximum absolute value

dasum

Returns sum of absolute values

daxpy

Computes y[i] = y[i]+a*x[i]

dcopy

Copies x[i] to y[i] (i.e., set y[i] = x[i])

ddot

Returns sum of x[i]*y[i] (i.e., return the dot product of x

dnrm2

Returns square root of sum of squares of x[i] (i.e. length o

dscal

Computes x[i] = a*x[i]

dswap

Swaps x[i] and y[i]

frannor

Returns a normally distributed random float

srannor

Seed random number generator

franuni

Returns a pseudo-random float between 0.0 (inclusive) an


(exclusive)

sranuni

Seed random number generator

quest

Returns an estimate of a specified quantile

questalloc

Alloc, init, & return pointer to a quantile estimator

questupdate

Updates and returns a quantile estimate

questfree

Frees quantile estimator

Known Problems

Signal Processing596

Developers Programming Guide

Signal Processing
Signal Processing

Other Docs

Subroutine

Description

antialias

Anti-alias filter; use before increasing the sampling interv


(sub-sampling)

bfdesign

Butterworth filter: computes number of poles and -3 db fr


low-pass or high-pass filter, given a frequency response c
two frequencies

bfhighpass

Butterworth filter: high-pass

bflowpass

Butterworth filter: low-pass

hankelalloc

Allocates and returns a pointer to a Hankel transformer

hankelfree

Frees a Hankel transformer

hankel0

Computes zero-order Hankel transform

hankel1

Computes first-order Hankel transform

hilbert

Computes Hilbert transform y of x

holbergd1

Computes coefficients of Holbergs 1st derivative filter

mkdiff

Makes discrete Taylor series approximation to nth deriva

mkhdiff

Computes filter approximating the bandlimited half-differ

abelalloc

Allocates and returns a pointer to an Abel transformer

abelfree

Frees an Abel transformer

abel

Computes Abel transform

xcor

Computes z = x cross-correlated with y; that is,


ifx+lx-1 z[i] = sum x[j]*y[i+j] ; i = ifz,...,ifz+lz-1 j=ifx

conv

Computes z = x convolved with y; that is,


ifx+lx-1 z[i] = sum x[j]*y[i-j] ; i = ifz,...,ifz+lz-1 j=ifx

npfa

Returns smallest valid n not less than nmin for prime fact

npfao

Returns optimal n between nmin and nmax for prime fact

npfar

Returns smallest valid n not less than nmin for real-to-com


complex-to-real prime factor ffts

npfaro

Returns optimal n between nmin and nmax for real-to-com


complex-to-real prime factor ffts

pfa2cc

Prime factor fft: 2-D complex to complex transforms, in p

pfa2cr

Prime factor fft: 2-D complex to real transforms

pfa2rc

Prime factor fft: 2-D real to complex transforms

Known Problems

Signal Processing597

Developers Programming Guide

Signal Processing (Continued)

Other Docs

Subroutine

Description

pfacc

Prime factor fft: complex to complex transform, in place

pfacr

Prime factor fft: complex to real transform

pfamcc

Prime factor fft: multiple complex to complex transforms

pfarc

Prime factor fft: real to complex transform

Known Problems

Plotting598

Developers Programming Guide

Plotting
Plotting

Other Docs

Subroutine

Description

scaxis

Computes a readable scale for use in plotting axes

pp1d

Printer plot of a 1-dimensional array

pplot1

Printer plot of a 1-dimensional array

Known Problems

Data Structures599

Developers Programming Guide

Data Structures
Data Structures

Other Docs

Subroutine

Description

heapFree

Frees a heap previously allocated by heapAlloc()

heapSetGrow

Resets the heap length increment

heapIsEmpty

Determines whether heap is empty

heapCount

Determines # items in heap

heapInsert

Inserts an item into the heap

heapRemove

Removes the top item from the heap

heapDelete

Removes the specified item from the heap

heapReSort

Resorts a corrupted heap array to restore the heap conditi

llAllocNode

Allocates a new list node

llFreeNode

Frees a list node

llInit

Initializes a linked list

llEmpty

Determines whether list contains any elements

llInsert

Inserts data at beginning of list

llAppend

Appends data to end of list

llDelete

Removes data from beginning of list

llGet

Retrieves data from beginning of list, without deleting

llNext

Returns pointer to next node in a list

llFree

Frees a linked list

queueAlloc

Allocates a new (empty) queue

queueFree

Frees a queue

queueEmpty

Determines whether queue is empty

queueAdd

Adds data to end of queue

queuePop

Deletes data from queue

queueGet

Retrieves data from queue, without deleting

queueCount

Determines number of items in the queue

dequeAlloc

Allocates a new (empty) deque

dequeFree

Frees a deque

dequeEmpty

Determines whether deque is empty

Known Problems

Data Structures600

Developers Programming Guide

Data Structures (Continued)

Other Docs

Subroutine

Description

dequeAdd

Adds data to end of deque

dequePush

Adds data to beginning of deque

dequePop

Deletes data from deque

dequeGet

Retrieves data from deque, without deleting

dequeCount

Determines number of items in the deque

stackAlloc

Allocates a new (empty) stack

stackFree

Frees a stack

stackEmpty

Determines whether stack is empty

stackPush

Adds data to stack

stackPop

Deletes data from stack

stackGet

Retrieves data from stack, without deleting

stackCount

Determines number of items in the stack

pqFree

Frees a priority queue previously allocated by pqAlloc()

pqSetGrow

Resets the priority queue length increment

pqIsEmpty

Determines whether priority queue is empty

pqCount

Determines # items in priority queue

pqInsert

Inserts an item into the priority queue

pqRemove

Removes the top item from the priority queue

bmalloc

Allocates and returns a pointer to a big matrix

bmfree

Frees a big matrix

bmread

Reads a vector from a big matrix

bmwrite

Writes a vector to a big matrix

rbtFree

Free a red-black tree

rbtFind

Finds data

rbtMin

Finds smallest data

rbtMax

Finds largest data

rbtAfter

Finds data after specified data

rbtBefore

Finds data before specified data

rbtInsert

Inserts data into tree. If the same data already exists in tre
is inserted.

Known Problems

Data Structures601

Developers Programming Guide

Data Structures (Continued)

Other Docs

Subroutine

Description

rbtInsertUnique

Inserts data into tree if it does NOT already exist in tree

rbtDelete

Deletes data from tree

Known Problems

Sorting and Searching602

Developers Programming Guide

Sorting and Searching


Sorting & Searching

Other Docs

Subroutine

Description

hpsort

Sorts an array so that a[0] <= a[1] <= ... <= a[n-1]

qkipart

Quicksort partition (FOR INTERNAL USE ONLY): Take


a random element from the subarray a[p:q] of a[0:n-1], an
indices in the subarray i[p:q] in such a way that there exist
with the following properties: p <= j < k <= q, provided t
<= x, for p <= l <= j a[i[l]] == x, for j < l < k a[i[l]] >= x,
This effectively partitions the subarray with bounds [p:q]
upper subarrays with bounds [p:j] and [k:q].

qkiinss

Quicksort insertion sort (FOR INTERNAL USE ONLY):


of indices bounded by p and q so that a[i[p]] <= a[i[p+1]]

qkisort

Sorts an array of indices i[] so that a[i[0]] <= a[i[1]] <= ..

qkifind

Partially sorts an array of indices i[] so that the index i[m]


would have if the entire array of indices were sorted, such
a[i[1]] <= ... <= a[i[n-1]]

qkpart

Quicksort partition (FOR INTERNAL USE ONLY): Take


random element from the subarray a[p:q] of a[0:n-1], and
elements in this subarray in such a way that there exist in
with the following properties: p <= j < k <= q, provided th
x, for p <= l <= j a[l] == x, for j < l < k a[l] >= x, for k <=
effectively partitions the subarray with bounds [p:q] into l
subarrays with bounds [p:j] and [k:q].

qkinss

Quicksort insertion sort (FOR INTERNAL USE ONLY):


bounded by p and q so that a[p] <= a[p+1] <= ... <= a[q]

qksort

Sorts an array such that a[0] <= a[1] <= ... <= a[n-1]

qkfind

Partially sorts an array so that the element a[m] has the va


have if the entire array were sorted such that a[0] <= a[1]

xindex

Determines index of x with respect to an array of x value

Known Problems

603

Developers Programming Guide

Appendix: FORTRAN Library


Summary

This appendix provides a series of tables which describe the


FORTRAN Library Subroutines. To see the complete
subroutine description, use the aman routine to display the man
page. For example, aman DB_AREACOUNT will display the man
page for DB_AREACOUNT. Each subroutine has a man page.
For more information on using the aman facility see the Man
Page Reference chapter.

Topics covered in this chapter:

Other Docs

Area/Line(Survey)/Flow584
Configuration589
Database Orders589
Domain Mapping592
Miscellaneous 1593
Trace I/O594
Trace Executive596
Trace Headers596
Memory Management597
Mute/Kill599
Statics600
Summing600
Error Routines600
Parameter Tables604
Tables Obsolete608
Parameter Interpolation608
Parameter Lists610
String Decoding613
Miscellaneous 2614

Known Problems

604

Developers Programming Guide

Other Docs

Parameter Input618
Packet Files619
Character Routines621
Seg-Y Disk622
Geophysical Routines622
Signal Processing627
Disk I/O634
SEG Vector Routines636
Resource Reporting642
UNIX Interface643

Known Problems

Area/Line(Survey)/Flow605

Developers Programming Guide

Area/Line(Survey)/Flow
Area/Line(Survey)/Flow

Other Docs

Subroutine

Description

DB_AREACOUNT

Returns the total number of areas in the ProMAX databas


number of characters in the longest area name

DB_AREALIST

Returns a list of the (null-terminated) names of all of the


ProMAX database

DB_CREATE_AREA

Creates a new area in the ProMAX database

DB_DELETE_AREA

Deletes an area in the ProMAX database

DB_MOVE_AREA

Moves (renames) an area in the ProMAX database

DB_COPY_AREA

Copies an area in the ProMAX database

DB_LINECOUNT

Returns the total number of lines in an area and the numb


in the longest line name

DB_LINELIST

Returns a list of the (null-terminated) names of all of the

DB_CREATE_LINE

Creates a new line in an area

DB_DELETE_LINE

Deletes a line in an area

DB_COPY_LINE

Copies a line in the ProMAX database

DB_MOVE_LINE

Moves (renames) a line in the ProMAX database

DB_INIT_LINE

Initializes the variables in global.inc for a line in the ProM

DB_FLOWCOUNT

Returns the total number of flows in a particular line in an


number of characters in the longest flow name

DB_FLOWLIST

Returns a list of the (null-terminated) names of all of the


particular line in an area

DB_CREATE_FLOW

Creates a new flow

DB_DELETE_FLOW

Deletes a flow

DB_COPY_FLOW

Copies a flow in the ProMAX database

DB_MOVE_FLOW

Moves (renames) a flow in the ProMAX database

DB_DATACOUNT

Returns the total number of datasets in a particular line in


number of characters in the longest dataset name

DB_PARMCOUNT

Returns the total number of parameter sets in a particular


and the number of characters in the longest parameter set

DB_TBL_COUNT

Returns the total number of tables in a particular line in a


number of characters in the longest table name

Known Problems

Area/Line(Survey)/Flow606

Developers Programming Guide

Area/Line(Survey)/Flow (Continued)

Other Docs

Subroutine

Description

DB_FOREIGN_COUNT

Returns the total number of foreign files in a particular lin


the number of characters in the longest name. Hidden dire
included.

DB_RE_FILE_COUNT

Returns the total number of files in a particular line whose


regular expression and the number of characters in the lon
Does not include directory names.

DB_LIST_COUNT

Returns the total number of lists in a particular line in an


number of characters in the longest list name

DB_DATALIST

Returns a list of the (null-terminated) names of all of the


particular line in an area.

DB_PARMLIST

Returns a list of the (null-terminated) names of all of the


(tables/lists) in a particular line in an area

DB_TBL_LIST

Returns a list of the (null-terminated) names of all of the


particular line in an area

DB_FOREIGN_LIST

Returns a list of the (null-terminated) names of all of the f


particular line in an area

DB_RE_FILE_LIST

Returns a list of the (null-terminated) names of files in a p


whose names match a regular expression

DB_LIST_LIST

Returns a list of the (null-terminated) names of all of the


particular line in an area

DB_DELETE_DATA

Deletes a dataset in the ProMAX database

DB_INIT_DATA

Initializes a dataset in the ProMAX database (stores the d


nothing else)

DB_MOVE_DATA

Moves (renames) a dataset in the ProMAX database

DB_COPY_DATA

Copies a dataset in the ProMAX database

DB_DELETE_PARM

Deletes a parameter set (table/list) in the ProMAX databa

DB_INIT_PARM

Initializes a parameter set (table/list) in the ProMAX data


description and nothing else)

DB_MOVE_PARM

Moves (renames) a parameter set (table/list) in the ProMA

DB_COPY_PARM

Copies a parameter set (table/list) in the ProMAX databa

DB_THDRCOUNT

Returns the number of basic standard trace header entries


number of standard trace header entries

DB_THDRCOUNT_STK

Returns the number of basic standard trace header entries


number of standard trace header entries used in post-stack

DB_THDRLIST

Returns the list of standard trace header entry names and


descriptions

Known Problems

Area/Line(Survey)/Flow607

Developers Programming Guide

Area/Line(Survey)/Flow (Continued)

Other Docs

Subroutine

Description

DB_THDRLIST_STK

Returns the list of standard trace header entry names and


descriptions used for post-stack processing

DB_DATA_INFO

Returns miscellaneous information for a particular datase

DB_INIT_CHECK

Checks to see if an area/survey has been initialized

Known Problems

Configuration608

Developers Programming Guide

Configuration
Configuration

Other Docs

Subroutine

Description

CONFIG_GET_INT

Returns a user-defined integer entry from the configuratio

CONFIG_GET_FLOAT

Returns a user-defined floating point entry from the confi

CONFIG_GET_STR

Returns a user-defined character string entry from the con

CONFIG_INFO

Returns information from the configuration file

CONFIG_DEV_COUNT

Returns the number of devices for a particular device type

CONFIG_DEV_LIST

Returns a list of devices for a particular device type

Known Problems

Database Orders609

Developers Programming Guide

Database Orders
Database Orders

Other Docs

Subroutine

Description

LINEDB_PARMPUT

Loads a particular parameter into the LIN database ordere


file. The parameter is not created by this routine. It is assu
parameter already exists and only its value is being modifi
parameters are created when the line is initialized).

DB_ORDLIST

Returns a list of the ordered parameter files that exist

DB_ORDCRE

Creates a new ordered parameter file

DB_ORD_MINMAX

Retrieves the min and max location for existing ordered p

DB_ORDINFO

Retrieves global info for an existing ordered parameter fil

DB_ORDPARM

Returns info for every parameter in an ordered parameter

DB_ORDOPEN

Opens an ordered parameter file in shared mode. Subsequ


be read-only. Significantly reduces I/O time for subsequen
No more than 100 files can be opened at one time.

DB_ORDLOCK

Locks an ordered parameter file, ensuring that other proce


access it until it is unlocked. Locking also significantly re
for subsequent database calls. No more than 100 files can b
time.

DB_ORDCLOSE

Closes an ordered parameter file

DB_ORDUNLK

Unlocks an ordered parameter file

DB_PARMCRE

Creates a NEW parameter in an existing ordered paramet

DB_PARMINFO

Retrieves information for one parameter from an ordered

DB_PARMPUT

Writes values for one parameter into an ordered database

DB_PARMGET

Reads values for one parameter from an ordered database

DB_PARMDEL

Deletes a parameter from an existing ordered parameter fi

DB_INFOLIST

Returns a list of NAMEs, descriptions, and dates for a un

DB_INFOTYPS

Returns a list of unique INFOTYPs

DB_ORDADD

Rebuilds and appends an ordered parameter file with mor

DB_BUFFRDPUT

Inputs parameter values to the database in a buffered fash


passed in one at a time.

Known Problems

Database Orders610

Developers Programming Guide

Database Orders (Continued)

Other Docs

Subroutine

Description

DB_BUFFRDGET

Outputs parameter values from the database in a buffered


are output one at a time.

DB_FIELD2NAMES

Extracts an order name, info type, and parm name from a


Normally the character field is extracted from a packet fil
output by the user interface by using the menu function
choose_new_db_parm or choose_old_db_parm.

Known Problems

Domain Mapping611

Developers Programming Guide

Domain Mapping
Domain Mapping
Subroutine

Description

DB_ENSEMBLE_MAP
DB_TRACE_MAP
DOMAIN_PROJECT

Other Docs

Projects points from one domain into another domain, ba


coordinates of points in both domains; for example, CAL
DOMAIN_PROJECT (ITOKEN, SIN, CDP, 44, & RC
This would return the CDP number that corresponds to th
SIN (shot index number) 44. The returned value is a floa
number that includes a fractional portion of the CDP num
can be called with more than one set of parameters within
process, and crooked lines are supported.

Known Problems

Miscellaneous 1612

Developers Programming Guide

Miscellaneous 1
Miscellaneous 1
Subroutine

Description

DB_FILNAME

Builds a database literal filename

DB_GLOBAL_GETPATH

Gets the contents of cdbpathz out of the global common

DB_MISC_FNAME

Builds a database filename for a miscellaneous file

DB_TBL_GET
DB_LIST_GET
DB_TBL_PUT
DB_LIST_PUT

Other Docs

DB_CHOOSE_AL

Prompts the user to select an area and line via I/O to stand

DB_CHOOSE_DATA

Prompts the user to select a dataset in an area and line

D3_CDP_TO_XY

Given a CDP, this routine returns the corresponding X,Y c


only)

D3_XY_TO_CDP

Given an X,Y coordinate, this routine returns the correspo


number (3-D only)

D3_XY_TO_XLINE

Given an X,Y coordinate, this routine returns the correspo


number (3-D only)

D3_XY_TO_INLINE

Given an X,Y coordinate, this routine returns the correspo


number (3-D only)

D3_LINES_TO_CDP

Given an inline and crossline number, this routine returns


corresponding CDP number (3-D only)

D3_CDP_TO_LINES

Given a CDP number, this routine returns the correspondi


crossline number (3-D only)

Known Problems

Trace I/O613

Developers Programming Guide

Trace I/O
Trace I/O

Other Docs

Subroutine

Description

DISKIO_GET_TR

Reads a trace and trace header from a dataset

DISKIO_GET_HDR

Reads a trace header (only) from a dataset

DISKIO_PUT_HDR

Writes a trace header (only) to a dataset

DISKIO_CLOSE

Closes all of the files associated with a dataset

DISKIO_OPEN

Opens all of the files associated with an existing dataset. F


FOR READING ONLY.

DISKIO_CREATE

Creates a new ProMAX dataset

DISKIO_GET_NDFILES

Gets the maximum number of directories used to store a d

DISKIO_DESC_GET

Returns the description stored within a dataset index file

DATASET_INFO_ALL

Returns all parameters that describe the state of the system


was written (replaces DISKIO_INFO).

DATASET_INFO

Returns parameters that describe the state of the system w


was written (replaces DISKIO_INFO).

DISKIO_THDR_SETUP

Creates all of the trace header words that exist in the data
map of header words from how they existed on disk to how
exist

Known Problems

Trace Executive614

Developers Programming Guide

Trace Executive
Trace Executive

Other Docs

Subroutine

Description

EX_PANEL_PARMS

Called during initialization phase by any tool that wishes


overlapping panels (2-D arrays of traces). Panel processin
pre-stack or post-stack.

EX_BUFF_PARMS

Sets parameters for single or double buffered tools

EX_SET_DISKITER

Causes Disk Data Input to iterate over the list of input tra

Known Problems

Trace Headers615

Developers Programming Guide

Trace Headers
Trace Headers

Other Docs

Subroutine

Description

HDR_ADD

Adds a new entry to the trace header

U_HDR_DELETE

Removes a trace header entry from the current list of head

HDR_DELETE_UPDATE

Corrects a trace header after a header entry is removed fro


list of header entries (via HDR_DELETE)

HDR_NAMINFO

Returns information for an existing trace header entry nam

HDR_INDINFO

Returns information for an existing trace header index nu

HDR_STD_ADD

Adds standard header words to the trace header if they do


exist

HDR_STD_INIT_VALS

Initializes the values in a trace header for all of the minim


header entries. This routine should be called by all input t

IS_STD_HDR_NAME

Checks to see if a header is one of the standard headers o

EX_GET_INTKEY

Converts any trace header key value into an integer

EX_GET_REALKEY

Load up a trace header key value into an real*4 value

EX_HDR_DELETE

Removes a trace header entry from the current list of head


intended for use by tools running under the executive

KILL_TRACE

Kills traces; also sets the relevant trace header entries

Known Problems

Memory Management616

Developers Programming Guide

Memory Management
Memory Management

Other Docs

Subroutine

Description

BV_FREE

Frees a Big Vector

BV_PUT

Puts values into a Big Vector

BV_GET

Gets values from a Big Vector

BV_SORT

Sorts the values in a Big Vector

BV_REORDER

Reorders the values in a Big Vector, based on a sort that w


previously using bvSort or BV_SORT

MEM_RESBUFF

Reserves a buffer of memory in the SPACE work arrayt


arrays ISPACEz (INTEGER) and RSPACEz (REAL). Th
accessed via a common block.

MEM_FREEBUFF

Frees a previously reserved buffer of memory in the SPAC

MEM_FREEBUFF_ALL

Frees all buffer of memory in the SPACE array

MEM_GROWBUFF

Checks to see if a buffer is out of space (MEMNEED=M


is, it reserves a new buffer of double size, moves the data
buffer, and frees the old buffer

MEM_TRAP

Checks for memory problems, displays a message if prob


stops the execution of the program. This routine is intend
debugging purposes; sprinkle through suspect source cod
where memory problems are caused.

Known Problems

Mute/Kill617

Developers Programming Guide

Mute/Kill
Mute/Kill

Other Docs

Subroutine

Description

REMUTE_INIT

Initializes for the REMUTE subroutine. Must be called on


call to REMUTE.

REMUTE

Remutes a buffer of traces (applies the same mute that exi


before some operation such as a filter). Must be the same
that was passed to REMUTE_INIT. REMUTE_INIT mut
before every call to REMUTE.

RESET_MUTES

Resets all of the standard mute times in a buffer of trace h


(typically after static shifts have been applied)

REMUTE_CHANGE

Resets the mute times in the trace headers and re-ramps th


some change has occurred in the data (such as NMO). Thi
the mute to move (in contrast to REMUTE).

Known Problems

Statics618

Developers Programming Guide

Statics
Statics

Other Docs

Subroutine

Description

STAT_SHIFT

Applies a static shift of STATIC milliseconds to TRACE


appropriate 8-point sinc function and a fast convolution ro

FRAC_STAT_APPLY

Utility subroutine used to apply any remaining fractional


word INA_STATz) to a group of traces

Known Problems

Summing619

Developers Programming Guide

Summing
Summing

Other Docs

Subroutine

Description

AT_WMEAN

Finds the alpha trimmed WEIGHTED mean of a group o


input arrays are DESTROYED by this routine.

AT_MEAN

Finds the alpha trimmed mean of a group of values. The i


DESTROYED by this routine.

HRZ_SMOOTH

Smooths horizon values with a triangular smoother, starti


X_HRZ(ICDP12(1)) and ending at X_HRZ(ICDP12(2)).

Known Problems

Error Routines620

Developers Programming Guide

Error Routines
Error Routines

Other Docs

Subroutine

Description

REPORT_PROMAX_ERR

Reports all types of ProMAX errors (writes to stdout)

U_ERR_STOP

1) Selects the appropriate destination for output messages


input message. 3) Stops the process, returning control to t
process.

U_ERR_FATAL

1) Selects the appropriate destination for output messages


input error message. 3) Stops the process, returning contr
process. This routine is not restricted for use by tools that
the executive.

U_ERR_POPWARN

Displays a warning message via a pop-up window (simila


U_ERR_HELP). This routine is intended for use by tools
linked into the executive (otherwise use EX_ERR_POPW

U_ERR_WARN

1) Selects the appropriate destination for output messages


input warning message. 3) Returns control to the routine
This routine is not resticted for use by tools that are linke
executive.

U_ERR_HELP

Prompts the user to provide help or select an option to ch


of action. This routine is intended for use by tools that are
the executive (otherwise use EX_ERR_HELP)

RM_SCRATCH_FILE

Removes a file if the file exists within the ProMAX scratc

U_ERR_SUPPRESS_WAR
N

Routine to allow suppression of system-level warnings

EX_ERR_RESTART

1) Selects the appropriate destination for output messages


user of the state of the system, including current trace, cu
and current tool. 3) Displays the input message. 4) Cleans
including calling tools in cleanup mode. 5) Restarts the p

EX_ERR_STOP

1) Selects the appropriate destination for output messages


user of the state of the system, including current trace, cu
and current tool. 3) Displays the input message. 4) Cleans
including calling tools in cleanup mode. 5) Stops the proc
control to the parent process.

EX_ERR_FATAL

1) Selects the appropriate destination for output messages


user of the state of the system, including current trace, cu
and current tool. 3) Displays the input error message. 4) C
job, including calling tools in cleanup mode. 5) Stops the
returning control to the parent process.

EX_ERR_POPWARN

Displays a warning message via a pop-up window (simila


EX_ERR_HELP). This routine is intended for use by tool
into the executive (otherwise use U_ERR_POPWARN).

Known Problems

Error Routines621

Developers Programming Guide

Error Routines (Continued)

Other Docs

Subroutine

Description

EX_ERR_WARN

1) Selects the appropriate destination for output messages


user of the state of the system, including the current tool.
input warning message. 4) Returns control to the routine

EX_ERR_MSG

1) Selects the appropriate destination for output messages


user of the state of the system, including the current tool.
input message. 4) If running in interactive mode, waits fo
press return. 5) Returns control to the calling routine.

EX_ERR_HELP

Prompts the user to provide help or select an option to ch


of action.

Known Problems

Parameter Tables622

Developers Programming Guide

Parameter Tables
Parameter Tables

Other Docs

Subroutine

Description

TBL_VAL_DECODE

This routine decodes a location:parameter string and load


parameter table. Typical input is CLIST = 5:20-30:-47.5/

TBL_GATE_DECODE

This routine decodes a location:time gates parameter strin


results in a parameter table. Typical input is
CGATE = 0:100-500,800-1800/5280:1200-1900,2100-2

TBL_VEL_DECODE

This routine decodes a location:times-vels parameter strin


results in a parameter table. Typical input is
CVEL = 1:0-5000,4000-12000/100:0-6000,4000-12800/

TBL_ALLOCATE

Allocates and initializes a new parameter table for z(x,y)

TBL_ALLOC_TMP

Allocates and initializes a temporary parameter table for z


case in which true spatial coordinates can be ignored

TBL_FETCH_TB3

Returns the underlying tb3 so that the tb3 functions can b

TBL_SET_EXTRAP

Sets x and y extrapolation methods

TBL_RESOLVE_X1_X2

Given an X (ensemble number), returns the spatial coordi


used within the table functions

TBL_ADD_XY

Adds z value(s) at specified (x,y) point

TBL_ADD_XYS

Adds z value(s) for an array of y coordinates and constan

TBL_GET_X

Gets X location from a table

TBL_GET_XYS

Gets X-Y-Z group from a table

TBL_DELETE_XY

Deletes z value(s) at specified (x,y) point

TBL_DELETE_X

Deletes all z value(s) at specified x coordinate

TBL_COPY

Copies all groups from tbl2 to tbl1. tbl1 does not have to

TBL_CLEAR

Clears all entries in a table

TBL_INTERP_XY

Interpolates z(x,y) value(s) at specified (x,y) points

TBL_INTERP_XY_U

Interpolates a vector of z(x,y) values, uniformly sampled i


x

TBL_FROM_VEL_PAR

Loads a parameter table from a location:times-vels type o


strings

TBL_X_MIN

Gets minimum X value for table

TBL_X_MAX

Gets maximum X value for table

TBL_MIN_MAX

Gets several maximum and minimum values for table

TBL_X1_MIN

Gets minimum X1 value for table

Known Problems

Parameter Tables623

Developers Programming Guide

Parameter Tables (Continued)

Other Docs

Subroutine

Description

TBL_X1_MAX

Gets maximum X value for table

TBL_X2_MIN

Gets minimum X2 value for table

TBL_X2_MAX

Gets maximum X2 value for table

TBL_Y_MIN

Gets minimum Y value for table

TBL_Y_MAX

Gets maximum Y value for table

TBL_Z_MIN

Gets minimum Z value for table

TBL_Z_MAX

Gets maximum Z value for table

TBL_COUNT_X

Gets number of locations in table

TBL_COUNT_MAX_Y

Gets maximum number of samples per node in a table

TBL_COUNT_Z

Gets number of z values per sample in a table

TBL_DESC

Gets table description

TBL_TO_DATABASE

Puts a parameter table to database

TBL_DESC_FROM_DB

Gets a table description from database using the hash labe


is needed because the menu can return only the hash nam
created (using Add option) table for output. To save the ta
we need the description.

TBL_SET_YZ

Adds z value(s) for y coordinates and constant (x1,x2) co

TBL_DELETE_YZ

Adds z value(s) for y coordinates and constant (x1,x2) co

TBL_DELETE_POS_

Deletes all z value(s) at specified (x1, x2) coordinates

TBL_INTERP_Z

Interpolates a vector of z( (x1,x2) ,y) values, uniformly sa


constant x

TBL_INDEX_X

Gets node coordinates by index from table

TBL_GET_YZ

Gets sample coordinates and values from an existing nod

EX_TBL_BUILD

Sets the primary and secondary header key values (norma


table interpolation)

Known Problems

Tables Obsolete624

Developers Programming Guide

Tables Obsolete
Tables Obsolete

Other Docs

Subroutine

Description

TBL_VAL_DECODE

This routine decodes a location:parameter string and load


parameter table. Typical input is CLIST = 5:20-30:-47.5/

TBL_GATE_DECODE

This routine decodes a location:time gates parameter strin


results in a parameter table. Typical input is
CGATE = 0:100-500,800-1800/5280:1200-1900,2100-2

TBL_VEL_DECODE

This routine decodes a location:times-vels parameter strin


results in a parameter table. Typical input is
CVEL = 1:0-5000,4000-12000/100:0-6000,4000-12800/

Known Problems

Parameter Interpolation625

Developers Programming Guide

Parameter Interpolation
Parameter Interpolation
Subroutine

Description

INT_GET

Interpolates values or groups of values by using the param


values are outside the ranges of the parameter table, the v
extrapolated, linearly extended from the last control or th
be set to true.

INT_VEC

Interpolates vectors NPTS_VEC long, starting at Y_STA


increment of Y_INC by using the parameter table. If the i
location values are outside the ranges of the parameter tab
may be extrapolated, linearly extended from the last contr
flag can be set to true.
Input arguments:
ID_TABLE - the table ID number
IX_XTRAPOLAT - 1 if the data is to be extrapolated in t
0 for linear extention (duplicate the last specified values)
NO_INTERP = 1 if the requested location is outside the r
values are defined
IY_XTRAPOLAT - 1 if the data is to be extrapolated in t
0 for linear extention (duplicate the last specified values)
NO_INTERP = 1 if the requested location is outside the r
values are defined. X - the desired output X location (prim
interpolated data.
Y_START - the starting Y (secondary key) value of the d
vector
Y_INC - the Y value increment for the desired output vec
NPTS_VEC - the number of output values for the desired
Output arguments: Z_VEC - the output array of interpola
NO_INTERP - 1 if the requested X and Y is outside the u
parameter interpolation values and the user forbade extrap
linear extention, else NO_INTERP = 0 if the interpolation

Warning: The parameter table must have been properly c


to TBL_END to be used by this subroutine. A fatal error w
is not the case. A fatal error will also occur if the paramet
more than one Z value per Y value.
Source file: /usr/src/lib/table/int.f

See also:
TBL_OPEN,TBL_WRITE,TBL_CLOSE,TBL_INIT,TBL
ADD,
TBL_GET,TBL_DELETE,TBL_END,TBL_FREE,INT_
INT_PS_KEYS

Other Docs

Sets the primary and secondary header key values (norma


table interpolation)

Known Problems

Parameter Lists626

Developers Programming Guide

Parameter Lists
Parameter Lists

Other Docs

Subroutine

Description

LIST_INIT_INTS

Initializes a totally new list for use with integer values

LIST_INIT

Initializes a totally new list for use with floating point val

LIST_INFO

Provides basic information from a lists header

LIST_DESC_REPLACE

Replaces the description of a list

LIST_FREE

Frees up all parameter list memory

LIST_ADD

Adds parameter starting value, ending value, and value in


to the parameter list

LIST_DELETE

Deletes certain cases of entries VALS(NUM_LEVELS) f


Returns IERR = 0 if the LIST entry deletion is successful
= 1 if the value set is not found in the LIST. Returns IERR
continuous bottom level value set is encountered. For exa
delete (1:3) from 1:1-5(2) but cannot delete (1:3) from
cases where VAL1.NE.VAL2, VAL_INC cannot = 0.0 (co
case). Returns IERR = 3 if any value set at a higher level
valued. For example, it can delete (1:3) from 1:1-5(2) bu
(1:3) from 1-2:1-5(2).

LIST_END

Compresses the parameter list, eliminating unused memo

LIST_CHECK

Tests input parameters against list values to see if they are


primary/secondary/tertiary/etc. value specifications

LIST_LEVEL_CHECK

Tests input parameters against list values to see if they are


value specifications for a particular level

LIST_GET

Tests input location parameters against list values to see if


the primary/secondary/tertiary/etc. list value specification
LIST_GET returns the bottom level LIST values VAL1_
VAL2_OUT and VAL_INC_OUT.

LIST_DECODE

Decodes an ASCII string and creates a parameter list in m


LIST_INIT must have been previously called, and LIST_
called after the last call to LIST_DECODE. This routine
LIST_ADD.

LIST_SORT

Sorts input arrays of header values for up to ten levels and


output list of trace index addresses

LIST_BV_SORT

Sorts input arrays of header values for up to ten levels and


output list of trace index addresses

LIST_SELECT

Selects input traces from input arrays of header values (up


and creates an output list of trace index addresses

Known Problems

Parameter Lists627

Developers Programming Guide

Parameter Lists (Continued)

Other Docs

Subroutine

Description

LIST_GL_GRAB

Grabs raw values previously entered into a parameter list

LIST_BUILD

Decodes a character string and creates a LIST

Known Problems

String Decoding628

Developers Programming Guide

String Decoding
String Decoding

Other Docs

Subroutine

Description

PAIR_DECODE

Decodes free form list of pairs of values, such as time gat


400-1200,1500-2000/ => 400.0, 1500.0 and 1200.0, 200

FLOAT_DECODE

Subroutine decodes free form list of floating point values


100,101.0-111.0(2),-118.5(2) =>
100.0,101.0,103.0,105.0,107.0,109.0,111.0,-118.5,-118.5
Legal characters are 0-9 plus ,()./ -*

DECODE_PREP

Prepares character strings for decoding (corrects bad synt


removes bad characters, etc.)

FLOAT_MAX_DECODE

Subroutine decodes free form list of floating point values


100,101.0-111.0(2),-118.5(2) =>
100.0,101.0,103.0,105.0,107.0,109.0,111.0,-118.5,-118.5
Legal characters are 0-9 plus ,()./ -*

HDR_LIST_DECODE

Decodes a list of header keys; for example, CDP,OFFSE


CKEY_NAME(1) = CDP and CKEY_NAME(2) = OF

Known Problems

Miscellaneous 2629

Developers Programming Guide

Miscellaneous 2
Miscellaneous 2
Subroutine

Description

PROMAX_PATH

Returns the path to specific directories and files in the Pro


structure. These paths can be controlled via environmenta
default root directory is /advance.

REGEXP_MATCH

Checks for a match between a regular expression and a st

VAX_TO_IEEE

Converts an array of VAX 32 bit floating point numbers t


floating point numbers

IEEE_TO_VAX

Converts an array of IEEE 32 bit floating point numbers t


floating point numbers

CONVEX_TO_IEEE

Converts an array of CONVEX 32 bit floating point numb


bit floating point numbers

IEEE_TO_CONVEX

Converts an array of IEEE 32 bit floating point numbers t


bit floating point numbers

CONVEX64_TO_IEEE

Converts an array of CONVEX 64 bit floating point numb


bit floating point numbers

IEEE_TO_CONVEX64

Converts an array of IEEE 32 bit floating point numbers t


bit floating point numbers

HEAPSORT

Sorts a real array RA of length N into ascending numeric


the Heapsort algorithm (see pg. 231 of Numerical Recipe
University Press, 1986)

HEAPSORT2

Sorts a real array RA of length N into ascending numeric


the Heapsort algorithm (see pg. 231 of Numerical Recipe
University Press, 1986). Differs from HEAPSORT in that
corresponding rearrangement of RB

HEAPSORT_INT

Sorts an integer array IA of length N into ascending nume


using the Heapsort algorithm (see pg. 231 of Numerical R
Cambridge University Press, 1986)

HEAPSORT2_INT

Sorts an integer array IA of length N into ascending nume


using the Heapsort algorithm (see pg. 231 of Numerical R
Cambridge University Press, 1986). Differs from HEAPS
makes the corresponding rearrangement of IB.

IMEDIAN

Finds the median of an array of integers

ISWAP

Swaps two integer values. On output, I1=I2 and I2=I1.

U_DOUBLE2INT

Loads a DOUBLE that is stored in an array (such as a trac


single INTEGER

U_DOUBLELOAD
U_DOUBLE2REAL

Other Docs

Known Problems

Miscellaneous 2630

Developers Programming Guide

Miscellaneous 2 (Continued)

Other Docs

Subroutine

Description

U_SWAPENDS4

Swaps the ends of 4-byte values to switch between big-en


little-endian machines (in place)

U_SWAPMOVE4

Swaps the ends of 4-byte values to switch between big-en


little-endian machines (NOT in place)

U_SWAPENDS2

Swaps the ends of 2-byte values to switch between big-en


little-endian machines (in place)

U_SWAPMOVE2

Swaps the ends of 2-byte values to switch between big-en


little-endian machines (NOT in place)

U_SWAPENDS8

Swaps the ends of 8-byte values to switch between big-en


little-endian machines (in place)

U_SWAPMOVE8

Swaps the ends of 8-byte values to switch between big-en


little-endian machines (NOT in place)

QUAD_INTERP

Performs a quadratic interpolation on 3 points. The X coo


points are assumed to be -1.0, 0.0, and 1.0, respectively.

FIND_NEAR_IVAL

Finds the index of a integer value in an array, assuming th


was found last time is a good place to start searching

FIND_NEAR_RVAL

Finds the index of a real value in an array, assuming that


was found last time is a good place to start searching

Known Problems

Parameter Input631

Developers Programming Guide

Parameter Input
Parameter Input

Other Docs

Subroutine

Description

EX_PARMINFO

Returns information for an input parameter in the current t


packet

U_PARMINFO

Returns information for an input parameter. Equivalent in


EX_PARMINFO, except that it is intended for use by stan
programs.

EX_PARMINFO_GRP

Returns information for an input parameter in Jth occurre


in the current tools parameter packet

EX_GETPARM

Returns values for an input parameter in the current tools


packet

EX_CGETPARM

Returns values for a character input parameter in the curr


parameter packet

U_GETPARM

Returns values for an input parameter. Equivalent in func


EX_GETPARM, except that it is intended for use by stan
programs.

U_CGETPARM

Returns values for a character input parameter. Equivalent


to EX_CGETPARM, except that it is intended for use by
programs.

EX_GETPARM_GRP

Returns values for an input parameter in Jth occurence of


current tools parameter packet

EX_GRP_OCCUR

Returns the number of occurrences of a group of paramet

EX_PARM_OCCUR

Returns the number of occurrences of an input parameter


tools input parameter packet

EX_PARM_OCCUR_GRP

Returns the number of occurrences of an input parameter i


of a group in the current tools parameter packet

Known Problems

Packet Files632

Developers Programming Guide

Packet Files
Packet Files

Other Docs

Subroutine

Description

PKT_ENDSWAP

Determines if a packet file was written on a machine with


endian type

PKT_HANDLE

Gets the actual file handle associated with a packet

PKT_INIT

Initializes a packet for output of a particular tools param

PKT_GROUPINIT

Initializes a group within a packet

PKT_OUTPARM

Outputs a parameter (or parameter list) within the current

PKT_FILCLOSE

Closes the current packet file

PKT_FILOPEN

Opens a new or existing packet file

PKT_TOOLNAM

Gets the name of a particular tool without loading the ent

PKT_LOAD

Loads a packet for a particular tool so that the contents of


be retrieved.

PKT_GET_NGROUPS

Returns the number of groups in the current tools packet.


during init phase.

PKT_GROUPINFO

Returns the name and number of parms in a particular grou


sequence number. This assumes that the group is within t
packet.

PKT_PINFO

Returns information for an input parameter within the cur

PKT_GET_PARM

Returns a buffer of values for an input parameter

PKT_OPEN_LOAD

Opens an existing packet file and loads the packet for a sp

PKT_COPY

Copies an input parameter packet from one file to another

PKT_SETID

Sets the packet id to enable later calls to the parmsubs.f s

PKT_GETID

Gets the current packet id

Known Problems

Character Routines633

Developers Programming Guide

Character Routines
Character Routines

Other Docs

Subroutine

Description

PROMAX_SEGY_OPEN

Opens the files for a ProMAX SEGY-like dataset

PROMAX_SEGY_CLOSE

Closes the files for a ProMAX SEGY-like dataset

PROMAX_SEGY_INIT

Initializes the header file for a ProMAX SEGY-like datas

PROMAX_SEGY_RINIT

Reads the initialization portion of the header file for a Pro


SEGY-like dataset

PROMAX_SEGY_WRITE

Writes a trace to the files of a ProMAX SEGY-like datase

PROMAX_SEGY_READ

Reads the next trace from the files of a ProMAX SEGY-li

Known Problems

Seg-Y Disk634

Developers Programming Guide

Seg-Y Disk
Seg-Y Disk

Other Docs

Subroutine

Description

PROMAX_SEGY_OPEN

Opens the files for a ProMAX SEGY-like dataset

PROMAX_SEGY_CLOSE

Closes the files for a ProMAX SEGY-like dataset

PROMAX_SEGY_INIT

Initializes the header file for a ProMAX SEGY-like datas

PROMAX_SEGY_RINIT

Reads the initialization portion of the header file for a Pro


SEGY-like dataset

PROMAX_SEGY_WRITE

Writes a trace to the files of a ProMAX SEGY-like datase

PROMAX_SEGY_READ

Reads the next trace from the files of a ProMAX SEGY-li

Known Problems

Geophysical Routines635

Developers Programming Guide

Geophysical Routines
Geophysical Routines

Other Docs

Subroutine

Description

STAT_AGC_RUNAVG

Does an agc or running average using an asymmetrical ga

STAT_AGC_RUNAVG1

Does an agc or running average using an asymmetrical ga

MEDIAN_SMOOTH

Computes a median smoothed version of VALS_IN and r


VALS_OUT. The output sample at NSMOOTH/2+1 is th
first NSMOOTH samples, and the operator then slides do
The first/last NSMOOTH/2 output samples use a growing
median smoother operator length. The first output sample
the first input sample, the second output sample is the me
three input samples, the third output sample is the median
input samples (if NSMOOTH.GE.5), etc.

RAGC_TRACE

Performs an Automatic Gain Control amplitude adjustme


algorithm used involves integrating the sample amplitude
quick method for determining the average amplitude with
of samples.
SUM_AMP must be 2*NUMSMP long.

AGC_TRACE

Performs an Automatic Gain Control amplitude adjustme


algorithm used involves integrating the sample amplitude
quick method for determining the average amplitude with
of samples.
SUM_AMP must be 2*NUMSMP long!!!

CONVERT_V_TABLE

Converts velocity from one type to another; that is, RMS


time to Interval velocities in depth. These conversions ho

INT_MIX_VEC

Interpolates a vector of z(x,y) values, uniformly sampled i


x, but averaged in the X direction. The purpose of this sub
smooth the velocities for migrations.

OPERDECON

Computes a least squares Wiener-Levinson deconvolution


cases: 1) Minimum Phase Spiking, 2) Minimum Phase Sp
correction only), 3) Zero Phase Spiking (amplitude correc
Minimum Phase Predictive

MEMCOF

Computes coefficients for a power spectra by maximum e

DECON_WORK_TIME

Generates and applies a deconvolution operator to a trace


predictive minimum phase options. Works in the time dom

NMO_APPLY

Applies NMO to a trace

NMO_UNAPPLY

Inverses (unapplies) a traces previously applied NMO

SPLIN1

Inputs X,Y pairs unequally sampled in X and the first der


first and last sample values (Y21,Y2N), computes the sec
of the interpolation function, and stores them in Y2ARR f
evaluation

Known Problems

Geophysical Routines636

Developers Programming Guide

Geophysical Routines (Continued)

Other Docs

Subroutine

Description

SPLIN2

Inputs data X,Y pairs in XARR and YARR and the secon
Y2ARR, and outputs a Y value (ANS) for X

SPLINE1

Inputs X,Y pairs unequally sampled in X, computes the s


derivatives of the interpolation function, and stores them
future spline evaluation. This spline assumes the second d
at the ends instead of suppling first derivate at each end a
conditions.

SYNTRC

General purpose synthetic trace generator

TRGEN

Generates a synthetic trace (TRACE) by interpolating int


wavelet WAV of amplitude RCF at each time TIM

CONV_JC

Performs time domain convolution

QUAD

Computes a quadrature filter (90 degree phase shifter)

PHASOR

Generates a constant phase shift operator

LOWPASS

Generates an Ormsby low pass filter where F1 is the left c


and F2 is the right stop frequency.

ORMSBAND

Generates an Ormsby bandpass filter (wavelet)

POLDIV

Divides polynomial ANUM by polynomial DENOM, pla


resulting quotient into QUO and the remainder into R.

GEOPH

Computes a theoretical geophone response for impulses i


Displacement 2) Velocity 3) acceleration. See Seismic Ins
Maurice Pieuchot, Geophysical Press, vol 2.

RICKER

Generates a Ricker wavelet with highest spectral content


PKFREQ

GET_RICKER_LEN

Generates a Ricker wavelet LENGTH for peak frequency


sample rate. SII in milliseconds, and cutoff amplitude CR

BUTTERLP

Generates Butterworth low pass symmetrical filters

KLAUDER

Generates an autocorrelated vibroseis wavelet for a linear

WAVTAPER

Tapers a symmetrical wavelet about the (NWAV - 1) / 2 +

CMPLX_FILTER_WORK

Performs frequency domain convolution of FILTER and C

FGEN

Generates a bandpass filter (optional notch) by editing an


initialized transform. All frequencies are HZ.

FGEN_BW

Generates a Butterworth bandpass filter (optional notch) b


pass initialized transform. All frequencies are HZ.

TD_FILTER

Applies a time-domain filter to an input trace

FD_FILTER

Applies a time-domain filter to an input trace

FILTER_WORK

Performs frequency domain convolution of FILTER and C

Known Problems

Signal Processing637

Developers Programming Guide

Signal Processing
Signal Processing
Subroutine

Description

CRFFT

Complex to real FFT

F_AUTO_COR

Performs autocorrelation in the frequency domain

GET_NFFT

Computes the nearest even prime factor product greater th


the number of samples NSAMP

MEMSPECT

Computes the maximum entropy power spectrum of the t


DATA where SAMPRAT is the time sample increment in
MEMSPECT computes NFREQ spectral values starting a
and incrementing DELTAF hz. The routine uses NCOF p
coefficients to compute each spectral contribution.

MIN_PHZ_GEN

Computes the complex spectrum of a minimum phase filt


Amplitude values are in the first NFFT/2+1 samples of A

PHASEFILTER

Applies a constant phase angle shift (PHASEADD) to all


TRACE

RCFFT

Real to complex FFT

EUREKA

Routine to generate a WIENER filter from the autocorrel


hand vector

RMEDIAN

Finds the median sample amplitude and returns its addres

HILBRT_FILT

Applies a time-domain HILBERT filter to an input trace.


TD_FILTER, since even filter samples are zeroes

COVARY

Calculates the normalized covariance between two signal


ARRMOV displaced against each other, -NLAGS through
ARRSTL is the waveform that is held stationary, and AR
waveform displaced through 2*NLAGS+1 delays noted a
the number of points to use in computing each correlation
ISSTART and MSTART are the indexes of the first points
arrays ARRSTL and ARRMOV, respectively, that will be
lag.
Caution: This means MSTART had better be larger than
ARRMOV had better be NPTS+2*NLAGS or longer.

Other Docs

Known Problems

Signal Processing638

Developers Programming Guide

Signal Processing (Continued)


Subroutine

Description

PICK_CORR

Picks the maximum correlation coefficient amplitude and


maximum magnitude correlation coefficient amplitude an
IREV_TEST=1. The time is relative to the center of the in
function (CORREL), which SHOULD have an ODD num
The amplitude and time are parabolically interpolated fro
nearest samples. If no positive peak is found and IREV_T
to 1, values of 0.0 are returned for T_PICK and QUALIT
IREV_PICK = 1, the value of QUALITY may be negativ
the time, T_PICK, is in REAL*4 sample shifts relative to
CORREL (whether NS is EVEN or ODD).

RANDOM_VALS

This subroutine creates an array of NUM_VALS output v


random values from VAL_MIN to VAL_MAX. ISEED is
for the random number generator and is changed on outpu
initialized to a large negative INTEGER*4. The random o
passed back in the VALS array.

FILT_SPIKE
MEAMGVZ

Vector average (NON_ZERO SAMPLES) element magni


RMSQVZ

DECON_APPLY

Computes and applies a least squares Wiener-Levinson de


for 4 cases 1) Minimum Phase Spiking, 2) Minimum Pha
(phase correction only), 3) Zero Phase Spiking, 4) Minim
Predictive

FILT_2D_HORZ

Horizontal filter (across traces), employing either a media


trimmed mean algorithm

FILT_2D_W_HORZ

Horizontal filter (across traces), employing either a WEIG


or a WEIGHTED alpha-trimmed mean algorithm

FILT_2D_C_HORZ

Horizontal filter (across traces), employing a simple corre


(weighted trace mix) algorithm

FILT_2D

Relatively fast 2-D spatial filter, using either a median or


alpha-trimmed mean algorithm

FILT_2D_SLOW

Simple but slow 2-D spatial filter, using either a median o


alpha-trimmed mean algorithm

FILT_2D_W

Relatively fast 2-D WEIGHTED filter, using either a weig


a weighted alpha-trimmed mean algorithm

FILT_2D_W_SLOW

Relatively slow (but with very simple code) 2-D WEIGHT


either a weighted median or a weighted alpha-trimmed m

FILT_2D_C

2-D filter (across traces and samples), employing a simple


D CONVOLUTIONAL filter algorithm.

WAT_MEAN

Finds the alpha trimmed WEIGHTED mean of a group o

Caution: The input arrays are DESTROYED by this rout

Other Docs

Known Problems

Signal Processing639

Developers Programming Guide

Signal Processing (Continued)


Subroutine

Description

MED_TRACE_AMP

Other Docs

GATE_AMP_EST

This subroutine computes a representave amplitude for a


samples NS1 & NS2. It subdivides the gate into NGATES
computes the average trace amplitude in each sub-gate, th
A_PICK as the median of the average gate amplitudes for
containing live samples. The value of A_PICK is also tes
from NaN, Infinity or other such invalid numbers. If detec
0.0 is returned for A_PICK.

MIN_PHZ_EQV

Computes the minimum phase complex spectrum of the i


array of NFFT/2+1 complex values using the Hilbert Tras
output is independent of the input phase.

BOXCAR_SMOOTH

Smooths input values with a BOXCAR smoother. True ze


values are optionally excluded from smoothing and the sm
normalization. The smoother length grows from ISMOOT
first sample to ISMOOTH, then similarly shrinks down to
1 for the last sample.

TRIANG_SMOOTH

Smooths input values with a TRIANGULAR smoother. T


values are optionally excluded from smoothing and the sm
normalization. The smoother length grows from ISMOOT
first sample to ISMOOTH, then similarly shrinks down to
1 for the last sample.

BOXCAR_FILTER

Filters input values with a BOXCAR filter. True zero sam


be optionally excluded from filtering and the filter norma
smoother length grows from ISMOOTH/2 + 1 at the first
ISMOOTH, then similarly shrinks down to ISMOOTH/2
sample.

TRIANG_FILTER

Filters input values with a TRIANGULAR filter. True zer


may be optionally excluded from filtering and the filter no
The smoother length grows from ISMOOTH/2 + 1 at the
ISMOOTH, then similarly shrinks down to ISMOOTH/2
sample.

NORM_TO_ONE

Normalizes an array of real values by the maximum posit


value becomes 1.0 on output, with all other values divide
maximum positive value. If no positive values exist in the
X_VALS array is returned unaltered.

DC_FILTER

Removes the DC component of an input array of values by


average sample value and subtracting it from the original

WINDOW

Builds and returns a windowing funtion

Known Problems

Disk I/O640

Developers Programming Guide

Disk I/O
Disk I/O

Other Docs

Subroutine

Description

FILE_OPEN

Routine to open a file

FILE_CLOSE

Routine to close a file

FILE_READ

Routine to read data from a file

FILE_WRITE

Routine to write data to a file

FILE_SEEK

Routine to seek in a file

FILE_CHECK

Routine to check to see if a file exists

TIO_OPEN

Opens a file for buffered typed I/O (uses fopen())

TIO_OPENU

Opens a file for unbuffered typed I/O (uses open())

TIO_CLOSE

Routine to close a file that was opened by TIO_OPEN

TIO_SET_SWAPFLAG

Routine to establish the need for byte swapping on a file t


by TIO_OPEN or TIO_OPENU. This routine or
TIO_READ_SWAPFLAG must be called before any I/O

TIO_READ_SWAPFLAG

Routine to establish the need for byte swapping on a file t


by TIO_OPEN or TIO_OPENU. This routine or TIO_SE
must be called before any I/O is done on a file.

CHAR_WRITE

Reads/writes buffers by type. Conversions (such as byte s


Cray->IEEE) are done on the fly.

TIO_SYNC

Performs sync on a file (flushes buffers to disk)

TIO_SET_LOCK

Locks a file (denying access to other processes)

TIO_CHECK_LOCK

Checks to see if a file is locked by another process

TIO_FCNTL

Does I/O control on an open file

Known Problems

SEG Vector Routines641

Developers Programming Guide

SEG Vector Routines


SEG Vector Routines
Subroutine

Description

ACOR
ACORF
ACORT
ASPEC
BLKMAN
CCOR
CCORF
CCORT
CDOTPR
CFFT
CFFTB
CFFTSC
COHER
CONV
CRVADD
CRVDIV
CRVMUL
CRVSUB
CSPEC
CVABS
CVADD
CVCMA
CVCMPX
CVCMUL
CVCONJ
CVDIV
CVEXP
CVEXPM

Other Docs

Known Problems

SEG Vector Routines642

Developers Programming Guide

SEG Vector Routines (Continued)


Subroutine

Description

CVFILL
CVMA
CVMAGS
CVMGSA
CVMOV
CVMUL
CVNEG
CVPHAS
CVRCIP
CVSQRT
CVSUB
DEQ22
DESAMP
DOTPR
FLNZ
HAMM
HANN
HIST
LVEQ
LVGE
LVGT
LVLE
LVLT
LVNE
LVNOT
MAXMGV
MAXV
MINMGV
MINV
MVE

Other Docs

Known Problems

SEG Vector Routines643

Developers Programming Guide

SEG Vector Routines (Continued)


Subroutine

Description

MVEMG
MVESQ
MVESSQ
NZCROS
POLAR
RECT
RFFT
RFFTB
RFFTSC
RMVESQ
SVDIV
SVE
SVEMG
SVESQ
SVESSQ
TCONVL
TRANS
VAAM
VABMRG
VABS
VADD
VAIMAG
VAINT
VAM
VAMERG
VASBM
VASM
VATAN
VATAN2
VAVEXP

Other Docs

Known Problems

SEG Vector Routines644

Developers Programming Guide

SEG Vector Routines (Continued)


Subroutine

Description

VAVLIN
VCLIP
VCLR
VCMERG
VCMPRS
VCOS
VDBCON
VDIV
VDIVZ
VERROR
VEXP
VEXP10
VFILL
VFILL8

Double-precision vector fill routine

VFLOAT
VFLOT2
VFRAC
VGATHR
VGEN
VGENP
VICLIP
VINDEX
VINT
VINT2
VINTB
VLINT
VLMERG
VLOG
VLOG10
VLOGZ

Other Docs

Known Problems

SEG Vector Routines645

Developers Programming Guide

SEG Vector Routines (Continued)


Subroutine

Description

VMA
VMAX
VMAXMG
VMIN
VMINMG
VMMA
VMMSB
VMOV
VMSA
VMSB
VMUL
VNABS
VNEG
VNINT
VNINT2
VPMERG
VPOLY
VPYTHG
VQINT
VRAMP
VREAL
VRECIP
VRSUM
VRVRS
VSADD
VSBM
VSBSBM
VSBSM
VSCATR
VSDIV

Other Docs

Known Problems

SEG Vector Routines646

Developers Programming Guide

SEG Vector Routines (Continued)


Subroutine

Description

VSIMPS
VSIN
VSMA
VSMSA
VSMSB
VSMUL
VSQ
VSQRT
VSQRTZ
VSSQ
VSUB
VSWAP
VTAN
VTHR
VTHRSC
VTMERG
VTRAPZ
VXCS
WIENER
VCHARMOV

Other Docs

CVMAG

Vector magnitude routine


C(IC) = SQRT(A(IA) * A(IA) + A(IA+1) * A(IA+1))

VIRAMP

INTEGER Vector ramp-building routine

Known Problems

Resource Reporting647

Developers Programming Guide

Resource Reporting
Resource Reporting

Other Docs

Subroutine

Description

U_STATMEM_RESERVE

Reserves static memory. Static memory is defined in this


memory that is reserved and not released until completion

U_DYNMEM_RESERVE

Reserves dynamic memory. Dynamic memory is defined


as memory that is reserved for traces within a flow, and is
the traces are passed on (this is allowed to occur many tim
flow, it is assumed that only two dynamic buffers exist at
one filling while one is flushing.

U_RESERVE

Reserves resources (such as memory and tape drives) for

Known Problems

UNIX Interface648

Developers Programming Guide

UNIX Interface
UNIX Interface
Subroutine

Description

C_FILECHECK

Determines if a file exists and if the user has read/write pr

C_DIRCHECK

Determines if a file is a directory

DISK_SPACE_SCRATCH

Returns the number of Kbytes of space available in the Pr


partition

DISK_SPACE_ADDL

Returns the number of Kbytes of space available on a disk

SPAWN
ALT_SHELL
C_RWNFLAG

Returns the octal open flag for read/write, new

C_RONFLAG

Returns the octal open flag for read-only, new

C_WONFLAG

Returns the octal open flag for write-only, new

C_RWOFLAG

Returns the octal open flag for read/write, old

C_ROOFLAG

Returns the octal open flag for read-only, old

C_WOOFLAG

Returns the octal open flag for write-only, old

C_RWRRMODE

Returns the octal protection mode equivalent to -rw-r--r-

C_RWXMODE

Returns the octal protection mode equivalent to drwxrwx


umask value will modify this at the users discretion.

C_RWXNMODE

Returns the octal protection mode equivalent to rwx-----

C_CHARTIME

Gets the current system time and date as a character array


Sun Sep 16 01:03:52 1985\n\0

C_TIME_CARR

Returns a time as a character array; for example, Sun Sep


1985\n\0

C_TIMES
C_TIME
C_UTIME

Other Docs

C_TMPNAM

Returns a temporary (scratch) file name

SHELL_COMMAND

Issues a command to the shell. Errors are treated as fatal.

SHELL_COMM_STAT

Issues a command to the shell. The status and error flag a

C_SYSTYPE

Returns the system type (big or little endian)

CHTIME

Returns the current system time as a character string

Known Problems

UNIX Interface649

Developers Programming Guide

UNIX Interface (Continued)

Other Docs

Subroutine

Description

CHDATE

Returns the current system date as a character string

UNIX_COM

Issues a UNIX command and returns the message that wo


displayed on the screen

Known Problems

UNIX Interface650

Other Docs

Developers Programming Guide

Known Problems

Index651

Developers Programming Guide

Index
Symbols
$PROMAX_HOME
.inc file
.promax
_mem

A
aliases
alloc
Alternate Executive
aman
amp_ratio (IPC FORTRAN example)
amp_ratio menu code (IPC example)
amp_ratio.f
amp_ratio.inc
amp_ratio.menu
ampRatio (IPC C example)
ampRatio.c
area, line, flow
FORTRAN subroutines
areas
atopdir
AVO ensemble tools
avo.f
avo.inc
avo.menu
avoC.c

C
C environment
C library summary
C programming examples
C structure names
canned command sequence (CCS)
cglobal.h (global include file example)
cglobal.h (include file example)
character routines (FORTRAN)
cleanup condition

Other Docs

coding standards
C
FORTRAN
overview
common blocks
communication
inter-process
trace headers
comp_opf.c
comp_opf.menu
complex tools
examples
options
configuration
C subroutines
FORTRAN subroutines
control functions (C)
converting to new system
cpromax.h
ctopdir
customizing the system

D
data structures (C)
database
C subroutines
OPF examples
orders (FORTRAN subroutines)
overview
db_disp.f
dbx
debugging
defun
Delaunay triangles
deque
directory
hierarchy
Landmark version
machine-dependent
Makefile options

Known Problems

Index652

Makefile rules
Master version
naming conventions
product-dependent
third-party software
User version
directory structure
development files
expanded
disk I/O (FORTRAN)
disk iteration examples
disk_iter.c
disk_iter.menu
domain mapping (FORTRAN)
double buffer tools
examples

E
ealloc
ens_define.f
ens_define.inc
ens_define.menu
ensemble definition programs
ensemble tools
examples
environmental variable
error routines
C subroutines
FORTRAN subroutines
EXAMPLE.menu (Lisp)
exec subroutine
Executive
execution routine
functions
initialization routine
tools
expanded directory structure

F
features, ProMAX System
files
changing, inline tool
changing, overview
changing, stand-alone or IPC tool

Other Docs

Developers Programming Guide

flow builder
flow execution
flows
FORTRAN
coding standards
library summary
subroutines
FrameMaker
autosave files
backup files
creating new file in
editing a file in
lock status
recover files
starting
working with files in
function, of ProMAX

G
geophysical routines (FORTRAN)
global include file examples
global parameters
global parameters, overview
global variables, overview
global.inc
gmake
GNU make

H
header entries
headers, overview
heap
helpfiles
common error messages
customizing the User Interface
example
FrameMaker-formatted
hypertext
interactive display
organization
parameters
references
theory section
usage section

Known Problems

Index653

hypertext

I
include files
examples
index values
trace headers
init subroutine
functions
inline tools, files to change
input tools
examples
overview
interp_db.c
interp_db.menu
interp_sb.c
interp_sb.menu
interpolation routines (C)
inter-process communication
trace headers
IPC
menu code
IPC C code
IPC FORTRAN code
IPC tools
C subroutines
examples
files to change
ISPACEz
iteration tools

L
libraries
library summary
C
FORTRAN
lines
linked lists
linking C and Fortran
Lisp
example

M
machine-dependent directories
Other Docs

Developers Programming Guide

make system
Makeadvance
User setup
Makeexec
steps
Makefile
conventions
directory
header files
options
rules
techniques
template instantiation
terms
variable prefixes
variables
Makefile_poststack
Makefile_prestack
man pages
math functions (C)
matrix functions (C)
memory management
_mem
alloc
C
C subroutines
deque
ealloc
FORTRAN
FORTRAN subroutines
heap
linked lists
multi-dimensional arrays
overview
priority queues
promax
queues
reallocation
routine names
RSPACEz and ISPACEz
stack
menus
adding
creating
files
multi-dimensional arrays

Known Problems

Index654

mute/kill (FORTRAN subroutines)

N
non-portable scripts

O
OPF, ordered parameter files
examples
for inter-tool communication
overview
overview of ProMAX system

P
packet files (C)
packet files (FORTRAN)
panel tools
examples
panel_test.f
panel_test.inc
panel_test.menu
panelTest.c
parameter input (C)
parameter input (FORTRAN)
parameter interpolation (C)
parameter interpolation (FORTRAN)
parameter list (C)
parameter list (FORTRAN)
parameter tables
Delaunay triangles
extrapolation
interpolation
overview
rules
structure
subroutine categories
x values
parameter tables (C)
parameter tables (FORTRAN)
parms structure
in re-entrancy
plotting (C)
portable code, rules for
portable scripts
poststack.c
Other Docs

Developers Programming Guide

poststack.f
prefixes, Makefile variable
prest_interp.c
pre-stack interpolation programs
prestack.f
prestack.menu
prestk_interp.f
prestk_interp.inc
prestk_interp.menu
priority queues
Processes file
processing pipeline
promax memory management routines
PVM (C)

Q
queues

R
reallocation, memory
recompilation
re-entrancy
regular expression
resource reporting (FORTRAN)
RSPACEz

S
sc_amp.f
sc_amp.inc
sc_amp.menu
scripts
non-portable
portable
SEG vector routines (FORTRAN)
Seg-Y disk (FORTRAN)
semblance.f
semblance.inc
semblance.menu
setup
Solaris
System Administrator
User
signal processing (C)
signal processing (FORTRAN)
Known Problems

Index655

simple processes, example


simple tool
simple tools
examples
simple.c
simple.menu
sine_wave.f
sine_wave.inc
sine_wave.menu
sineWave.c
single buffer tools
examples
Socket Tools
socket tools-see IPC tools
Solaris setup
sorting/searching (C)
stack
stand-alone tools
examples
files to change
overview
standard orders
list
statics (FORTRAN)
string decoding (FORTRAN)
summing (FORTRAN)
Super Executive
system
architecture
converting to new
customizing
overview
System Administrator setup
system overview, illustration

T
tables obsolete (FORTRAN)
third-party software
toggling products, .promax
tool anatomy
tools
adding
communication between
complex
complex, examples

Other Docs

Developers Programming Guide

complex, options
double buffer
double buffer examples
ensemble
ensemble, examples
executive
files to change
input
input, examples
IPC
IPC, examples
iteration
panel
panel, examples
simple
simple, examples
single buffer
single buffer, examples
stand-alone
stand-alone, examples
types
trace executive (FORTRAN)
Trace Headers
trace headers
alphabetical list
C subroutines
FORTRAN subroutines
geometry-related
index values
input-related
mute-related
special applications-related
special geometry-related
standard
statics-related
system-related
usage
trace I/O (FORTRAN)
trace interpolation examples
trace muting (C)
transform.c
transform.f
transform.inc
transform.menu

Known Problems

Index656

Developers Programming Guide

U
UNIX interface (C)
UNIX interface (FORTRAN)
User Interface
User setup
utopdir

V
variables, Makefile
vector routines (C)
vel_io.f
velocity (C)

Other Docs

Known Problems

You might also like