The Process phase accepts pointers to the input and output trace ensemble gathers, and returns a Boolean value of TRUE or FALSE. The constants TRUE and FALSE are equivalenced to OK and FAIL respectively, for the purpose of better understanding of the meaning of the returned values of the Process phase.
The Process phase function, which has a predefined name (we still are describing the module ourmod):
boolean ourmod_procp_ ( GATHER *input, GATHER *input )
returns OK if it had "produced some output". More exactly, it returns OK if it is time to try to call the modules following the current module in the processing sequence. If there is some hope to continue processing, return OK. On the contrary, the Process phase should return FAIL if it did not change the state of its output gather. Then there is no need in calling the modules placed after this one, and the monitor will try calling the preceding modules.
If a module is called during the Process phase at all, it can be called in two different modes. If the Edit phase of the module had returned NORMAL_MODULE, the module is called only with some input, i.e., when its Process phase, or a Process phase of some preceding module had returned OK. If all the preceding modules had failed to produce an output, and the current module failed too, then all these modules will be never called again.
By contrast, if the corresponding Edit phase has returned EOF_MODULE, the module is given one more chance after all the input traces are exhausted. It temporarily becomes an input module, and is called repeatedly until it returns FAIL. After that, it is no longer called again.
To distinguish between the two types of calls above (this makes sense only for EOF modules), call function SIA_current_phase (), which returns one of the constants PROCESS_PHASE, EOF_PHASE, or EDIT_PHASE. The latter value, of course, is not expected during the Process phase at all, but may be used in some fancy routines that are used in both phases. Note that if our module ourmod is a fully compliant C++ module, the EOF state may be ascertained by simply calling method OURMOD::eof().
The pointer to the module's individual data block allocated by its Edit phase can be obtained from any subroutine using SIA_param_block (). This makes the use of global variables unnecessary ( and it also may harm reentrancy). The beginning of the Process phase usually likes like this:
OURMOD *O = (OURMOD*) SIA_param_block();
This gives us a pointer to all the internal module data. If a special initialization of the Process phase is required and has not been done during the Edit phase, the Boolean function SIA_first_call () informs the Process phase when it is called for the first time.
To summarize, the Process phase : usually obtains the pointer to the parameter block; checks the state of the input and output, and decide what to do. If it modifies the input and output trace gather; it returns OK; otherwise it should returns FAIL. I will illustrate this on some examples below.
Several important system functions provide information about the current state of the processing module:
We will start with the simplest example. Suppose our module ourmod is always working with one trace at a timeit inputs one trace and outputs one modified trace during every call. Many seismic processing tool work like this: filter, AGC, debiasing, single channel deconvolution, etc. Such modules are designed as NORMAL_MODULEs.
Three ways of performing such operations are used. We can process the trace while keeping it in the input sequence, or we can pass it to the output and process there. Alternatively, we can create new trace, process it, add it to the output, and remove the corresponding trace from the input.
The choice generally depends on the character of trace header manipulations and on the changes in the trace type, length, and sample interval. If trace sampling parameters are not changed, then the second style of those mentioned above is preferable.
Note that any trace left in the output sequence after the module returns may be taken away by other modules, regardless of the status (OK or FAIL) this module returns. Thus any trace put into the output sequence must be completed before our module returns to the monitor.
SIA_pass_trace() moves the first input trace to the output and returns the pointer to this trace. If there are no traces in the input, it returns NULL. Thus the Process phase looks like this:
#include "sia_module.C.h"
#include "ourmod.h"
boolean ourmod_procp_ ( GATHER *input, GATHER *output )
{
TRACE *t = SIA_pass_trace ( input, output ); // move a trace to the output
if ( !t ) // no input
return FAIL; // wait for data at input
OURMOD *O = (OURMOD*) SIA_param_block(); // get the pointer to module's data
O->do_what_you_want(t); // perform the desired operations with the trace
return OK; // tell the monitor to try further processing of the job
}
In the second example, we assume that the module needs to wait until a full ensemble is accumulated at its input. Such are the modules working with multicomponent data. The simplest examples are stacking, rotation of components, polarization filtering, etc.
Typically, such modules produce an output structurally different from the input, so what we need to do is:
Here is the example:
#include "sia_module.h"
#include "ourmod.h"
void OURMOD::do_what_you_want ( ENSEMBLE *e )
{
ENSEMBLE *output_ensemble = SIA_output()->add_ensemble();
// create a new output trace ensemble
/*----------------------------------------------------------------
Here you can do any processing with the ensemble 'e',
putting the resulting traces into 'output_ensemble'
-----------------------------------------------------------------*/
}
boolean ourmod_procp_ ( GATHER *input, GATHER *output )
{
ENSEMBLE *e;
if ( ! input->num_ensembles ) // no input
return FAIL;
if ( ! input->first_ensemble->closed() ) // wait for a full ensemble
return FAIL;
OURMOD *O = (OURMOD*) SIA_param_block();
O->do_what_you_want ( input->first_ensemble ); // perform the desired operations
input->first_ensemble->release(); // discard the input ensemble
return OK; /* done */
}
Some modules perform their operations only during the EOF phase, or they need to accumulate all or a certain number of ensembles before starting processing. An example is plotting, unless the number of plotted traces is too large. The simplest way to achieve this goal is simply to wait until the desired number of ensembles is accumulated, or until the data supply is exhausted:
#include "sia_module.C.h"
#include "ourmod.h"
boolean OURMOD::do_what_you_want ( GATHER *e )
{
if ( ! e->num_ensembles ) // nothing to do?
return FAIL;
/*--------------------------------------------------------------
Here you do any processing with the ensemble_sequence 'e'
-----------------------------------------------------------------*/
/*---- send all input ensembles to the output -------------------*/
while ( e->num_ensembles )
SIA_pass_ensemble ( e, SIA_output() );
return OK;
}
boolean ourmod_procp_ ( GATHER *input, GATHER *output )
{
OURMOD *O = (OURMOD*) SIA_param_block (); /* got all parameters */
/*--- if no more input expected, try to process what we have ----*/
if ( SIA_current_phase() == EOF_PHASE )
return O->do_what_you_want ( input );
/*-- otherwise wait until the necessary number of data is accumulated ---*/
if ( input->num_ensembles < num_ensembles_we_need )
return FAIL;
/*---- process and flush the data to the output ------------------*/
return O->do_what_you_want ( input ); /* done */
}