Module coding style has changed significantly since conversion to C++ in version 4.5. The reliance on naming conventions has reduced and remains as a legacy in some older parts of the system. Over time, the need for naming conventions will go away; however, for backward compatibility of the code, old names will still be available in the form of macros.
All components of the module are accessed by the monitoring program by the name of the module, and thus the naming convention is very essential. Every module is located in the folder bearing its name. Let us assume that the module we are describing is named ourmod (the names are currently limited to 7 characters, due to the standard tab stops at 8 characters). This module will be located in the folder $SIAHOME/modules/ourmod, where SIAHOME is the environment variable pointing to home directory of the system.
The three important files in located in this directory and constituting the module for the system will be then:
The parameter definition file is translated once during the development of the module using the program pdf, located in the directory indicated by the environment variable SIABIN. This program reformats the file into a binary form, and puts the result into the folder $SIALIB/PRM. Also, the program pdf generates a makefile, named simply m, which is used afterwards to compile all of the module's codes. The command for this compilation is:
make -f m
At present, program pdf allows the following switches:
In programming the monitoring program and modules, I to use self-explanatory names of the subroutines and global variables. This helps to reduce the chance of naming collisions during the inclusion of new modules in the system. Also, practically all public functions provided by the libraries have prefixes related to their origin. General-purpose monitor functions begin with SIA_, functions used only during the Edit phase have the prefix PDF_, mathematical functions often begin with MATH_, the functions from the special trace manipulation librarywith TRACE_, etc. A full list of the functions can be found in the following sections.
In all modules, a similar naming convention is recommended. Typically, all classes defined within a particular module should have the module's name as a prefix of the class name. If a function is designed for the use with a particular module, please also use the upper-case name of the module as a prefix. Thus, for our module ourmod, most of its work would be performed by class OURMOD, and some additional functions would be named something like OURMOD_do_something (), etc. If a global variable needs to be declared, use of a similar prefix in its name is also recommended.
See the complete and up-to date SIA code libraries produced by Doxygen,
Many useful data types are defined in the header files included in the files sia_module.h and sia_module.C.h (for C++ codes), one of which we always include in the source codes of the modules. All header files useful for module design are listed in Appendix A In this section, I describe the main data structures used in most applications and critical for the understanding of the concept of the system.
class or typedef | equivalent | explanation |
boolean |
char |
This format serves the purpose to emphasize Boolean values (with values TRUE is the same as OK, FALSE is the same as FAIL) |
DATA_SAMPLE |
float |
The format of the trace data samples as they are stored in memory |
COMPLEX |
Class | Class implementing complete set of complex arithmetic |
CHARSTR |
Class | Class implementing various operations with arbitrary-length character strings. |
byte |
unsigned char |
The format for all general-purpose binary data, e.g., trace headers, table data entries. The types corresponding to the main seismic data structures, which appear in the modules most often, are listed in below, along with the field declared within these structures. Note that only the principal fields are shown here |
FORMAT |
enum |
Trace header or table entry format. It may assume values of INTEGER, REAL (the same as FLOAT), DOUBLE, LONG, POINTER, and CHARACTER |
Aux_Parameter |
union | Auxiliary parameter included in various structures. It is never used by the monitor, and is used by the modules to store the intermediate results |
HEADER |
Class | Contains all information about the trace header or table entry. Trace or table entry header name. |
AHEADER |
Class | Trace header with capabilities of using arrays and additional methods defined. |
HEADER_PARAM |
Class | Used with the functions implementing free-format parameter input and retrieval. It is used to read in the values from the job file which can be interpreted as numerical constants or trace/table header entries. |
HEADERS_TABLE |
Class | Table of the formats of all the headers associated with one data structure (trace ensemble sequence, or table). |
DATA_PARAMS |
Parameters of all the traces in the same ensemble sequence (see below). This is used only internally to support fixed-format traces. | |
TRACE |
Class | Seismic trace |
ENSEMBLE |
Class | Ensemble of seismic traces. |
GATHER |
Class | A linked sequence of trace ensembles. |
TABLE |
Class | Used to implement lists of keywords. |
USER_TABLE |
Class | User-defined table. Most of the databases in the system are implemented in this format. char *name ASCII name of the table. |
enum User_Table_Type |
The type of the table: UT_TABLE (free-format table) or UT_MAP (multidimensional array-type table). | |
SIA_SYSTEM |
Class | Placeholder for most system-wide parameters and methods. |
SIA_MODULE |
Class | Base class for modules written in C++ |
PROJECT |
Class | Descriptor of a processing flow. |
The modules can access the processing flow structures used by the seismic monitor itself. This, however, is not recommended. Instead, a number of functions is provided, which return the necessary pointers to the input and output ensemble sequences, data parameter blocks, header tables, etc. I describe the structures corresponding to the processing flow shown in Figure 1 for the purpose of illustration only.
FILE_ACCESS |
Class | The parameters of the ASCII file access used by the module. Every module may have its own log and error files; also, its write/append output mode to ASCII files may be changed using calls to the module setup. These modes affect opening of all ASCII files opened using SIA_open_file (). |
MODULE |
Class | Seismic processing module. A pointer to this structure is returned by the function SIA_current_module (). |
Several types implement general array operations:
ARRAY<type> |
Template | Variable-length array of arbitrary type |
ARRAY_FIXED<size,type> |
Template | Fixed-length array of arbitrary type |
ARRAY_IO<type> |
Template | Variable-length array of arbitrary type with file input/output operations |
STRING<TYPE> |
Template | Variable-length array of arbitrary type. The type is restricted to a "simple" type without constructors. |
Classes performing matrix operations:
MATRIX_GENERAL<type> |
Template | General matrix operations (+,-,*) |
MATRIX |
MATRIX_GENERAL<float> |
Also includes matrix inversion and division |
VECTOR |
Class | A ingle-column MATRIX |
Six formats of seismic data samples are currently supported. These formats are distinguished by the value of the field type (see class TRACE above). Traces of different formats can be joined into one trace ensemble. These formats (values returned by the method TRACE::type()), and the corresponding data sample types are the following:
Except COMPLEX, these types are designed mainly for a compact storage of integer or floating-point values. Memory reallocations and data conversions are performed automatically by functions TRACE::copy(); actual trace data length in bytes is returned by TRACE::data_length().
All modules are reentrant, unless special measures are taken to destroy the reentrancy. All the programmer needs to do is to include all the parameters used by the module into a single class, to crfeate an object of this class during the Edit phase, and to return the pointer to it. For example, for our module ourmod, this structure, typically declared in the header file ourmod.h would look something like the following:
class OURMOD
{
HEADER *source, *target; // any internal data needed by the module
void proc(); // any processing methods
};
and the beginning of the Edit phase will look like this:
#include "sia_module.C.h"
#include "ourmod.h"
int ourmod_editp_ ( OURMOD *O )
{
*O = new OURMOD;
(*O)->source.get ( "ENTRY" ); ...
(also see the Edit phase template). The first operator here initilizes the entire module data object and returns its pointer *O to the monitor. During the Process phase afterwards, the monitor will provide us with the pointer to this object. This pointer can be obtained from any subroutine, e.g., from the main Process phase function:
#include "sia_module.C.h"
#include "ourmod.h"
bool ourmod_procp_ ( GATHER* input, GATHER*output )
{
OURMOD *O = (OURMOD*) SIA_param_block (); ...
If you use a global variable in your module and want to make your module reentrant, make sure you reset the value of the global variable at the beginning and at the end of the Edit and Process phase processing. The number and the sequence of calls of a particular module depends on the seismic job and on the processing situation, so surprises may occur. If you want to ensure that your module is used only once in the job, you can easily ensure this using the mechanism of messages.