next up previous contents
Next: Writing a new program: Up: How to Write an Previous: Setting up the Makefile   Contents


A template SU program

Although variations are usually needed, a template for a typical SU program looks like the program listing below (we excerpted lines from the program sumute to build this template). The numbers in square brackets at the end of the lines in the listing are not part of the listing--we added them to facilitate discussion of the template. The secret to efficient SU coding is finding an existing program similar to the one you want to write. If you have trouble locating the right code or codes to ``clone,'' ask us--this can be the toughest part of the job!

/* SUMUTE: $Revision: 1.20 $ ; $Date: 2002/08/22 20:19:54 $      */  [1]

#include "su.h"                                                     [2]
#include "segy.h"

/*********************** self documentation **********************/ [3]
char *sdoc[] = {
"                                                                ",
" SUMUTE - ......                                                ",
"                                                                ",
" sumute <stdin >stdout                                          ",
"                                                                ",
" Required parameters:                                           ",
"         none                                                   ",
"                                                                ",
" Optional parameters:                                           ",
"        ...                                                     ",
"                                                                ",
" Trace header fields accessed: ns                               ",
" Trace header fields modified: none                             ",
"                                                                ",
NULL};
/**************** end self doc ***********************************/

/* Credits:
 *
 *        CWP: Jack Cohen, John Stockwell
 */


segy tr;                                                             [4]

main(int argc, char **argv)
{
        int ns;                /* number of samples          */      [5]
        ...


        /* Initialize */                 
        initargs(argc, argv);                                        [6]
        requestdoc(1);                                               [7]

        /* Get parameters */
        if (!getparint("ntaper", &ntaper))        ntaper = 0;        [8]

                                                
        /* Get info from first trace */
        if (!gettr(&tr)) err("can't read first trace");              [9]
        if (!tr.dt) err("dt header field must be set");              [10]

        /* Loop over traces */
        do {                                                         [11]
                int nt     = (int) tr.ns;                            [12]

                if (below == 0) {                                    [13]
                        nmute = NINT((t - tmin)/dt);
                        memset((void *) tr.data, (int) '\0', nmute*FSIZE);
                        for (i = 0; i < ntaper; ++i)
                                tr.data[i+nmute] *= taper[i];
                } else {
                        nmute = NINT((nt*dt - t)/dt);
                        memset((void *) (tr.data+nt-nmute),
                                        (int) '\0', nmute*FSIZE);
                        for (i = 0; i < ntaper; ++i)
                                tr.data[nt-nmute-1-i] *= taper[i];
                }
                puttr(&tr);                                           [14]
        } while (gettr(&tr));                                         [15]
        
        return EXIT_SUCCESS;                                          [16]
}
Discussion of numbered lines:

  1. We maintain the internal versions of the codes with the UNIX utility RCS. This item shows the string template for RCS.
  2. The file su.h includes (directly or indirectly) all our locally defined macros and prototypes. The file segy.h has the definitions for the trace header fields.
  3. The starred lines delimit the ``self-doc'' information--include them exactly as you find them in the codes since they are used by the automatic documentation shells. The style of the self-doc shown is typical except that often additional usage information is shown at the bottom and, of course, often there are more options. Look at some existing codes for ideas.
  4. This is an external declaration of an SU (SEG-Y) trace buffer. It is external to avoid wasting stack space.
  5. We usually describe the global variables at the time of declaration. Examine codes related to yours to increase consistency of nomenclature (there is no official SU naming standard).
  6. The initargs subroutine sets SU's command line passing facility (see page [*]).
  7. The requestdoc subroutine call specifies the circumstances under which self-doc will be echoed to the user. The argument `1' applies to the typical program that uses only standard input (i.e. <) to read an SU trace file. Use `0' for codes that create synthetic data (like suplane) and `2' for codes that require two input files (we could say ``et cetera,'' but there are no existing SU mains that require three or more input files).
  8. This is typical code for reading `parameters from the command line. Interpret it like this: ``If the user did not specify a value, then use the default value.'' The subroutine must be type-specific, here we are getting an integer parameter.
  9. Read the first trace, exit if empty. The subroutine fgettr ``knows about'' the SU trace format. Usually the trace file is read from standard input and then we use gettr which is a macro based on fgettr defined in su.h. Note that this code implies that the first trace is read into the trace buffer (here called tr), therefore we will have to process this trace before the next call to fgettr.
  10. We've read that first trace because, we need to get some trace parameters from the first trace header. Usually these are items like the number of samples (tr.ns) and/or the sampling interval (tr.dt) that, by the SEGY-Y standard, are the same for all traces.
  11. Since the first trace has been (typically) read before the main processing loop starts, we use a ``do-while'' that reads a new trace at the bottom of the loop.
  12. We favor using local variables where permitted.
  13. This is the seismic algorithm-here incomplete. We've left in some of the actual sumute code because it happens to contains lines that will be useful in the new code, we'll be writing below. You may want to call a subroutine here to do the real work.
  14. fputtr and puttr are the output analogs of fgettr and gettr.
  15. The loop end. gettr returns a 0 when the trace file is exhausted and the processing then stops.
  16. This is an ANSI-C macro conventionally used to indicate successful program termination.


next up previous contents
Next: Writing a new program: Up: How to Write an Previous: Setting up the Makefile   Contents
John Stockwell 2007-04-10