Introduction

This tutorial further develops the use of the Computer Programs in Seismology routines that work with the SAC format. It is assumed that you have already downloaded and installed the current version of Computer Programs in Seismology.

The library routines for working with SAC files are described in the PDF file in the distribution, e.g.,  in Appendix C of PROGRAMS.330/DOC/GSAC.pdf/cps330g.pdf.
The C file containing the routines is in
    PROGRAMS.330/SUBS/sacsubc.c
with header file with prototypes
    PROGRAMS.330/SUBS/sacsubc.h

The examples given here describe the minimum requirements for creating a valid SAC trace file.  Other information can be added latter using the ch (changeheader) command of gsac or sac2000.

We will also use the GNU gcc compiler to create the executables

Writing a time series in SAC format

Program purpose:

This simple program will create two sac files, one consisting of a unit area impulse. This is called imp.sac. This impulse is passed through a bilinear recursive digital lowpass filter to create filt.sac. gsac is used to display the trace and plotgif is used to create the graphic for this tutorial.

The Program:

Copy the files sacsubc.c and sacsubc.h to your working directory. Then create the file writesac.c:

#include "sacsubc.h"
/* this is a sample program that creates two sac files
   one of a simple impulse and the other with the impulse passed
   through a lowpass recursive digital filter
*/
/* define the maximum number of points  and the two float arrays */
#define NPTS 100
float x[NPTS];
float y[NPTS];
void outputsac(int npts, float *arr, float dt, char *filename);
main()
{
        int i;
        float dt = 0.01 ;
        int offset = 10;
        float wc=31.415927;
        float f,a,b;
        f = 2./(dt*wc);
        a = 1. + f;
        b = 1. - f;
        /* initialize the impulse */
        for(i=0;i< NPTS;i++)
                x[i] = 0.0;
        x[offset] = 1.0/dt ;
        /* now apply a recursive digital filter to create the
           output */
        y[0] = 0.0;
        for(i=1;i < NPTS; i++){
                y[i] = (x[i]+x[i-1] - b*y[i-1])/a;
        }
        outputsac(NPTS, x, dt, "imp.sac");
        outputsac(NPTS, y, dt, "filt.sac");
}
void outputsac(int npts, float *arr, float dt, char *filename)
{
        /* create the SAC file
           instead of using the wsac1 I will use the lower level
           routines to provide more control on the output */
        int nerr;
        float b, e, depmax, depmin, depmen;
        /* get the extrema of the trace */
                scmxmn(arr,npts,&depmax,&depmin,&depmen);
        /* create a new header for the new SAC file */
                newhdr();
        /* set some header values */
                setfhv("DEPMAX", depmax, &nerr);
                setfhv("DEPMIN", depmin, &nerr);
                setfhv("DEPMEN", depmen, &nerr);
                setnhv("NPTS    ",npts,&nerr);
                setfhv("DELTA   ",dt  ,&nerr);
                b = 0;
                setfhv("B       ",b  ,&nerr);
                setihv("IFTYPE  ","ITIME   ",&nerr);
                e = b + (npts -1 )*dt;
                setfhv("E       ",e     ,&nerr);
                setlhv("LEVEN   ",1,&nerr);
                setlhv("LOVROK  ",1,&nerr);
                setlhv("LCALDA  ",1,&nerr);
        /* put is a default time for the plot */
                setnhv("NZYEAR", 1970, &nerr);
                setnhv("NZJDAY", 1, &nerr);
                setnhv("NZHOUR", 0, &nerr);
                setnhv("NZMIN" , 0, &nerr);
                setnhv("NZSEC" , 0, &nerr);
                setnhv("NZMSEC", 0, &nerr);
        /* output the SAC file */
                bwsac(npts,filename,arr);
} 

Compiling:

    gcc writesac.c sacsubc.c -o writesac    

On LINUX/Unix the executable is writesac. On Windows under CYGWIN, the executable is actually called writesac.exe but you can execute the program by just enterning writesac at the prompt in both environments.

The shell script DOIT does the compile and also used gsac and plotgif to create the following image:

p001.gif



Reading a time series in SAC format



Program purpose:

This simple program will read the file filt.sac, list header values and the time series.

The Program:

Copy the files sacsubc.c and sacsubc.h to your working directory. Then create the file readsac.c:

#include "sacsubc.h"
#include <stdio.h>
/* define the maximum number of points  and the float array for
   storing the time series. Note I use calloc() in this C library
   so that array is defined in the brsac. */
#define NPTS 100
float *x;
main()
{
        int npts, nerr;
        float dt,depmax, depmin, b, e;
        int i;
        brsac(NPTS,"filt.sac", &x, &nerr);
        /* now lets get some header values */
        getfhv("DELTA",&dt,&nerr);
                printf("DELTA  :   %f\n",dt);
        getfhv("DEPMAX",&depmax,&nerr);
                printf("DEPMAX :   %f\n",depmax);
        getfhv("DEPMIN",&depmin,&nerr);
                printf("DEPMIN :   %f\n",depmin);
        /* this is necessary since the actual number of points
           may be less than the array dimension. brsac NEVER
           reads in more than the maximum allowable numebr of
           points and resets the internal header value so that
           the npts returned here never is greater than NPTS */
        getnhv("NPTS", &npts, &nerr);
                printf("NPTS   :   %f\n",npts);
        /* output the time series */
        for(i=0;i < npts ; i ++)
                printf("x[%d] = %f\n",i,x[i]);
}



Compiling:

    gcc readsac.c sacsubc.c -o readsac    

On LINUX/Unix the executable is readsac. On Windows under CYGWIN, the executable is actually called readsac.exe but you can execute the program by just enterning readsac at the prompt in both environments.

Output: 

This is the output from running the command readsac:

DELTA  :   0.010000
DEPMAX :   23.465153
DEPMIN :   0.000000
NPTS   :   -0.171413
x[0] = 0.000000
x[1] = 0.000000
x[2] = 0.000000
x[3] = 0.000000
x[4] = 0.000000
x[5] = 0.000000
x[6] = 0.000000
x[7] = 0.000000
x[8] = 0.000000
x[9] = 0.000000
x[10] = 13.575525
x[11] = 23.465153
x[12] = 17.094118
x[13] = 12.452886
x[14] = 9.071796
x[15] = 6.608708
x[16] = 4.814374
x[17] = 3.507221
x[18] = 2.554974
x[19] = 1.861272
x[20] = 1.355917
x[21] = 0.987771
x[22] = 0.719581
x[23] = 0.524207
x[24] = 0.381879
x[25] = 0.278195
x[26] = 0.202662
x[27] = 0.147637
x[28] = 0.107552
x[29] = 0.078351
x[30] = 0.057078
x[31] = 0.041580
x[32] = 0.030291
x[33] = 0.022067
x[34] = 0.016075
x[35] = 0.011711
x[36] = 0.008531
x[37] = 0.006215
x[38] = 0.004527

 

Last changed February 12, 2008