常用SEISMIC BINARY数据的读取

我们经常在野外采集一些地震数据,通常可以保存为SEGY和SEG2两种格式。然后,一炮一个文件,甚至一道就是一个文件。接着,拿回去数据,需要做一些处理。所有的数据处理都事先要将原始数据导入到计算机内存中。它具有某种固定的数据结构,可以用结构体变量和其它各自编程语言给出的某种数据结构来实现。C语言、FORTRAN语言和MATLAB语言中的STRUCT结构用得最多。SEGY数据在C语言中的结构描述如下所示[1],来自于SEISMIC UNIX中的代码:

Note: The web version of this archive does not contain the SEG-Y Trace files. These files are very large and would require extremely long download times. To obtain the complete CD-ROM archive, contact USGS Information at (888) ASK-USGS.

The seismic data are stored in SEG-Y, integer, Motorola format. The SEG-Y files on this CD-ROM conform to the SEG-Y standard format (Barry and others, 1975) with the exception of the 3600-byte reel identification header which is provided in ASCII format. Standard SEG-Y uses a EBCDIC 3600-byte reel identification header. The Delph Seismic version of SEG-Y consists of the following:

  • A 3600-byte reel identification header with the first 3200 bytes consisting of an ASCII header block and a 400-byte binary header block. Both headers include information specific to the line and reel number.
  • The trace data block follows the reel identification header. The first 240 bytes of each trace block is the binary trace identification header. The seismic data samples follow the trace identification header.

/* TYPEDEFS */
typedef struct {    /* segy - trace identification header */

    int tracl;    /* Trace sequence number within line
               --numbers continue to increase if the
               same line continues across multiple
               SEG Y files.
               byte# 1-4
             */

    int tracr;    /* Trace sequence number within SEG Y file
               ---each file starts with trace sequence
               one
               byte# 5-8
             */

    int fldr;    /* Original field record number
               byte# 9-12 
            */

    int tracf;    /* Trace number within original field record 
               byte# 13-16
            */

    int ep;        /* energy source point number
               ---Used when more than one record occurs
               at the same effective surface location.
               byte# 17-20
             */

    int cdp;    /* Ensemble number (i.e. CDP, CMP, CRP,...) 
               byte# 21-24
            */

    int cdpt;    /* trace number within the ensemble
               ---each ensemble starts with trace number one.
               byte# 25-28
             */

    short trid;    /* trace identification code:
            -1 = Other
                 0 = Unknown
             1 = Seismic data
             2 = Dead
             3 = Dummy
             4 = Time break
             5 = Uphole
             6 = Sweep
             7 = Timing
             8 = Water break
             9 = Near-field gun signature
            10 = Far-field gun signature
            11 = Seismic pressure sensor
            12 = Multicomponent seismic sensor
                - Vertical component
            13 = Multicomponent seismic sensor
                - Cross-line component 
            14 = Multicomponent seismic sensor
                - in-line component 
            15 = Rotated multicomponent seismic sensor
                - Vertical component
            16 = Rotated multicomponent seismic sensor
                - Transverse component
            17 = Rotated multicomponent seismic sensor
                - Radial component
            18 = Vibrator reaction mass
            19 = Vibrator baseplate
            20 = Vibrator estimated ground force
            21 = Vibrator reference
            22 = Time-velocity pairs
            23 ... N = optional use 
                (maximum N = 32,767)

            Following are CWP id flags:

            109 = autocorrelation
            110 = Fourier transformed - no packing
                 xr[0],xi[0], ..., xr[N-1],xi[N-1]
            111 = Fourier transformed - unpacked Nyquist
                 xr[0],xi[0],...,xr[N/2],xi[N/2]
            112 = Fourier transformed - packed Nyquist
                  even N:
                 xr[0],xr[N/2],xr[1],xi[1], ...,
                xr[N/2 -1],xi[N/2 -1]
                (note the exceptional second entry)
                 odd N:
                 xr[0],xr[(N-1)/2],xr[1],xi[1], ...,
                xr[(N-1)/2 -1],xi[(N-1)/2 -1],xi[(N-1)/2]
                (note the exceptional second & last entries)
            113 = Complex signal in the time domain
                 xr[0],xi[0], ..., xr[N-1],xi[N-1]
            114 = Fourier transformed - amplitude/phase
                 a[0],p[0], ..., a[N-1],p[N-1]
            115 = Complex time signal - amplitude/phase
                 a[0],p[0], ..., a[N-1],p[N-1]
            116 = Real part of complex trace from 0 to Nyquist
            117 = Imag part of complex trace from 0 to Nyquist
            118 = Amplitude of complex trace from 0 to Nyquist
            119 = Phase of complex trace from 0 to Nyquist
            121 = Wavenumber time domain (k-t)
            122 = Wavenumber frequency (k-omega)
            123 = Envelope of the complex time trace
            124 = Phase of the complex time trace
            125 = Frequency of the complex time trace
            126 = log amplitude
            127 = real cepstral domain F(t_c)= invfft[log[fft(F(t)]]
            130 = Depth-Range (z-x) traces
            201 = Seismic data packed to bytes (by supack1)
            202 = Seismic data packed to 2 bytes (by supack2)
               byte# 29-30
            */

    short nvs;    /* Number of vertically summed traces yielding
               this trace. (1 is one trace, 
               2 is two summed traces, etc.)
               byte# 31-32
             */

    short nhs;    /* Number of horizontally summed traces yielding
               this trace. (1 is one trace
               2 is two summed traces, etc.)
               byte# 33-34
             */

    short duse;    /* Data use:
                1 = Production
                2 = Test
               byte# 35-36
             */

    int offset;    /* Distance from the center of the source point 
               to the center of the receiver group 
               (negative if opposite to direction in which 
               the line was shot).
               byte# 37-40
             */

    int gelev;    /* Receiver group elevation from sea level
               (all elevations above the Vertical datum are 
               positive and below are negative).
               byte# 41-44
             */

    int selev;    /* Surface elevation at source.
               byte# 45-48
             */

    int sdepth;    /* Source depth below surface (a positive number).
               byte# 49-52
             */

    int gdel;    /* Datum elevation at receiver group.
               byte# 53-56
            */

    int sdel;    /* Datum elevation at source.
               byte# 57-60
            */

    int swdep;    /* Water depth at source.
               byte# 61-64
            */

    int gwdep;    /* Water depth at receiver group.
               byte# 65-68
            */

    short scalel;    /* Scalar to be applied to the previous 7 entries
               to give the real value. 
               Scalar = 1, +10, +100, +1000, +10000.
               If positive, scalar is used as a multiplier,
               if negative, scalar is used as a divisor.
               byte# 69-70
             */

    short scalco;    /* Scalar to be applied to the next 4 entries
               to give the real value. 
               Scalar = 1, +10, +100, +1000, +10000.
               If positive, scalar is used as a multiplier,
               if negative, scalar is used as a divisor.
               byte# 71-72
             */

    int  sx;    /* Source coordinate - X 
               byte# 73-76
            */

    int  sy;    /* Source coordinate - Y 
               byte# 77-80
            */

    int  gx;    /* Group coordinate - X 
               byte# 81-84
            */

    int  gy;    /* Group coordinate - Y 
               byte# 85-88
            */

    short counit;    /* Coordinate units: (for previous 4 entries and
                for the 7 entries before scalel)
               1 = Length (meters or feet)
               2 = Seconds of arc
               3 = Decimal degrees
               4 = Degrees, minutes, seconds (DMS)

            In case 2, the X values are longitude and 
            the Y values are latitude, a positive value designates
            the number of seconds east of Greenwich
                or north of the equator

            In case 4, to encode +-DDDMMSS
            counit = +-DDD*10^4 + MM*10^2 + SS,
            with scalco = 1. To encode +-DDDMMSS.ss
            counit = +-DDD*10^6 + MM*10^4 + SS*10^2 
            with scalco = -100.
               byte# 89-90
            */

    short wevel;    /* Weathering velocity. 
               byte# 91-92
            */

    short swevel;    /* Subweathering velocity. 
               byte# 93-94
            */

    short sut;    /* Uphole time at source in milliseconds. 
               byte# 95-96
            */

    short gut;    /* Uphole time at receiver group in milliseconds. 
               byte# 97-98
            */

    short sstat;    /* Source static correction in milliseconds. 
               byte# 99-100
            */

    short gstat;    /* Group static correction  in milliseconds.
               byte# 101-102
            */

    short tstat;    /* Total static applied  in milliseconds.
               (Zero if no static has been applied.)
               byte# 103-104
            */

    short laga;    /* Lag time A, time in ms between end of 240-
               byte trace identification header and time
               break, positive if time break occurs after
               end of header, time break is defined as
               the initiation pulse which maybe recorded
               on an auxiliary trace or as otherwise
               specified by the recording system 
               byte# 105-106
            */

    short lagb;    /* lag time B, time in ms between the time break
               and the initiation time of the energy source,
               may be positive or negative 
               byte# 107-108
            */

    short delrt;    /* delay recording time, time in ms between
               initiation time of energy source and time
               when recording of data samples begins
               (for deep water work if recording does not
               start at zero time) 
               byte# 109-110
            */

    short muts;    /* mute time--start 
               byte# 111-112
            */

    short mute;    /* mute time--end 
               byte# 113-114
            */

    unsigned short ns;    /* number of samples in this trace 
               byte# 115-116
            */

    unsigned short dt;    /* sample interval; in micro-seconds
               byte# 117-118
            */

    short gain;    /* gain type of field instruments code:
                1 = fixed
                2 = binary
                3 = floating point
                4 ---- N = optional use 
               byte# 119-120
            */

    short igc;    /* instrument gain constant 
               byte# 121-122
            */

    short igi;    /* instrument early or initial gain 
               byte# 123-124
            */

    short corr;    /* correlated:
                1 = no
                2 = yes 
               byte# 125-126
            */

    short sfs;    /* sweep frequency at start 
               byte# 127-128
            */

    short sfe;    /* sweep frequency at end
               byte# 129-130
            */

    short slen;    /* sweep length in ms 
               byte# 131-132
            */

    short styp;    /* sweep type code:
                1 = linear
                2 = cos-squared
                3 = other
               byte# 133-134
            */

    short stas;    /* sweep trace length at start in ms
               byte# 135-136
            */

    short stae;    /* sweep trace length at end in ms 
               byte# 137-138
            */

    short tatyp;    /* taper type: 1=linear, 2=cos^2, 3=other 
               byte# 139-140
            */

    short afilf;    /* alias filter frequency if used 
               byte# 141-142
            */

    short afils;    /* alias filter slope
               byte# 143-144
            */

    short nofilf;    /* notch filter frequency if used
               byte# 145-146
            */

    short nofils;    /* notch filter slope
               byte# 147-148
            */

    short lcf;    /* low cut frequency if used
               byte# 149-150
            */

    short hcf;    /* high cut frequncy if used
               byte# 151-152
            */

    short lcs;    /* low cut slope
               byte# 153-154
            */

    short hcs;    /* high cut slope
               byte# 155-156
            */

    short year;    /* year data recorded
               byte# 157-158
            */

    short day;    /* day of year
               byte# 159-160
            */

    short hour;    /* hour of day (24 hour clock) 
               byte# 161-162
            */

    short minute;    /* minute of hour
               byte# 163-164
            */

    short sec;    /* second of minute
               byte# 165-166
            */

    short timbas;    /* time basis code:
                1 = local
                2 = GMT
                3 = other
               byte# 167-168
            */

    short trwf;    /* trace weighting factor, defined as 1/2^N
               volts for the least sigificant bit
               byte# 169-170
            */

    short grnors;    /* geophone group number of roll switch
               position one
               byte# 171-172
            */

    short grnofr;    /* geophone group number of trace one within
               original field record
               byte# 173-174
            */

    short grnlof;    /* geophone group number of last trace within
               original field record
               byte# 175-176
            */

    short gaps;    /* gap size (total number of groups dropped)
               byte# 177-178
            */

    short otrav;    /* overtravel taper code:
                1 = down (or behind)
                2 = up (or ahead)
               byte# 179-180
            */

1.使用MATLAB读取外部SEISMIC BINARY DATA

由于SEISMIC BINARY DATA在工作中经常碰到。例如SEGY, SEG2格式的地震数据在石油勘探、天然地震以及工程物探中经常被存储在磁盘文件中。科技工作者们需要将这些磁盘中的SEISMIC BINARY DATA导入到计算机内存中。因此,这个工作可以利用FILE OPEN 和 READ, WRITE语句以及CLOSE语句实现。编程过程比较死板,需要一步一步来,遇到有重复步骤的可以稍微调用循环语句实现。为了对编程过程数据格式进行保密或者不触犯相关保密条例。以下SEISMIC BINARY DATA一律采用某数据格式来表达。

某二进制SEISMIC DATA的读取

path(path,'D:');
id=fopen('c4','r','ieee-le');%ieee-le为little endian;ieee-be为big endian
fseek(id,0,'bof');
fseek(id,4,'bof');
ntr=fread(id,1,'int16');
fseek(id,0,'bof');
fseek(id,10,'bof');
nt=fread(id,1,'int16');
data=zeros(nt,ntr);
data1=zeros(nt,ntr);
fseek(id,0,'bof');
fseek(id,14,'bof');
dt=fread(id,1,'int32');
for i=1:ntr
fseek(id,0,'bof');
fseek(id,512+nt*4*(i-1),'bof');
for j=1:nt
data(j,i)=fread(id,1,'int32');
end

for j=1:nt
data(j,i)=bitshift(int32(data(j,i)),0);%32位不做任何偏移,0偏移
end
end
%d=quantizer([32 16]);
%data1=bin2num(d,data);
data1=data.*1e10;
%data1=hex2dec(data);

image(data1(:,1:ntr));
fclose(id);

SEG2格式:

/* Copyright (c) Colorado School of Mines, 2002.*/
/* All rights reserved.                       */

/*
    FROM THE PUBLISHED VERSION IN GEOPHYSICS, SEPT '90
    Original Header:
    NAME:            SEG2SEGY.C
    VERSION:         V1.0
    CREATION DATE:   6/15/90
    AUTHOR:          Brett Bennett
    PURPOSE:         Conversion of the SEG2-PC standard data set 
         to SEG-Y 32-BIT format.
    LIMITATIONS:     In this implementation of the conversion only
    the data generated in the IBM byte ordering method can be
    converted.  i.e.  byte ordering must be LSB-MSB Data generated
    by a 68000 pro- cessor, for instance, will not convert.  A flag
    is however in the code for future addition of this capability.
    The SEG-Y file also differs slightly from Barry et al standard.
    Word 88 is defined as "last-trace-flag" rather than "Geophone
    group number of last trace within original file."  This
    simplification greatly reduces the amount of code needed for
    conversion.  Header word 92 is defined here as the
    Shot-Sequence-Number.  This is used to assign each trace group a
    unique number.

    EXTENSIVE REWRITE/HACK AND PORT: 11/95 
    AUTHOR: Ian Kay.  
    -Added code to handle running on big-endian machines.
    -Replaced all non-unix portable code and library calls.
    -Typed all the ints so they are the right types
        (on DOS int=short, on Unix int=long)
    -removed calls to "ieeeibm" since workstations are ieee floating point
        format as well.
    -partial addition of structures to handle the keywords and headers.
    but I eventually gave up.

    $Id: seg2segy.c,v 1.2 2003/02/06 19:05:45 pm Exp $

    Changes:
    Feb 96.  Trace header was not being written out with swap on bytes above
    89 although info is stored in 92,93,94.  Error in original, fixed.

    Oct 97.  Changed the input to command line, inspired by the seg2segy
    version in CWP/SU package.
    
    Jan 98.  
    fixed malloc problem; not enough space was malloced to hold the 
    string defpath. 
    freed the malloced space when finished. 
    closed the segykeyword file when finished.
    changed curf and lastf to int from short; this should allow digits
    in the file name prefix (but what will happen in DOS?).

    Sep 98.
    Ok.  So no one can figure out the segykeyword file mechanism, 
    so I've changed it.  Now, if the environment variable SEGKEYPATH
    is set , then that file is used for the segykeywords. If that
    isn't set then a system default is used /usr/local/lib/segykeyword
    or "segykeyw.ord" in the local directory in DOS.  Finally, neither
    of those exist, then the default values are built in.  

    NOTE that this means that you can do away with the segykeyword
    file altogether!

    $Log: seg2segy.c,v $
    Revision 1.2  2003/02/06 19:05:45  pm
    fixed sawtooth on 20bit packed data conversion case 3
    
    Revision 1.1  2003/02/06 18:44:59  pm
    working on 3rdparty seismic unix
    
    Revision 1.2  2002/11/12 16:01:43  john
    type changed on i,j,k to in
    t

    Revision 1.1  2001/04/12 17:55:11  john
    Initial revision

    Revision 1.7  1998/10/08 20:17:15  kay
    A little more cleanup...^[

    Revision 1.6  1998/10/07 18:54:40  kay
    Built in the defaults for the segykeyword file.  This file is no longer
    needed.

    Revision 1.5  1998/01/07 13:36:15  kay
    added new changes and a Log for the future

 */

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#ifndef __MSDOS__   
#include <unistd.h>
#define MAXSAMP 16384
#define MAXTRACES 16384
#else
#include <io.h>
#define MAXSAMP 4096
#define MAXTRACES 512
#endif

#ifndef NULL
#define NULL    ((void *)0)
#endif 

#define STRINGWIDTH 100
#define MAXKEYWORDS 100
#define MAXPARMS 10

/* global data... */
short int segyreelheader[1800];
int totalkeys;
char string1[200];
short int outhead[120];


typedef struct _SegyKeyTable
    {
    char segykeyword[STRINGWIDTH];
    int segyfunction;
    int segyheader;
    double segyparms[MAXPARMS];
    } SegyKeyTable;


void
swapshort (short *si)
{
/*      void swab(char *from, char *to, size_t nbytes); */
    short tempc;
    tempc = *si;
    swab ((char *) &tempc, (char *) si, sizeof (short));
}

void
swaplong (long *li)
{
    short sl, sh;
    long temp, temp1;
    temp = *li;
    sl = temp & 0x0000ffff;
    sh = (temp >> (8 * sizeof (short))) & 0x0000ffff;
    swapshort (&sl);
    swapshort (&sh);
    temp = (sl << (8 * sizeof (short)));
    temp1 = (sh & 0x0000ffff);
    temp = temp | temp1;

    *li = temp;
}

void
float_to_ibm(long from[], long to[], long n)
{
    register long fconv, fmant, ii, t;

    for (ii=0;ii<n;++ii) {
    fconv = from[ii];
    if (fconv) {
    fmant = (0x007fffff & fconv) | 0x00800000;
    t = (long) ((0x7f800000 & fconv) >> 23) - 126;
    while (t & 0x3) { ++t; fmant >>= 1; }
    fconv = (0x80000000 & fconv) | (((t>>2) + 64) << 24) | fmant; 
    } 
    to[ii] = fconv; 
    } 
    return; 
}

char *
strrev (char *s)
{
    char *tmpstr;
    int i, len;
    tmpstr = (char *) malloc (sizeof (char) * strlen (s));
    len = 0;
    while (s[len] != '\0')
     len++;
    for (i = 0; i < len; i++) {
    tmpstr[i] = s[len - 1 - i];
      tmpstr[i + 1] = '\0';
    }
    tmpstr[++i] = '\0';
    strcpy (s, tmpstr);
    free (tmpstr);
    tmpstr = (char *) NULL;
    return s;
}


void
parseSegyKeys(FILE *keyfptr, SegyKeyTable *keywords)
{
    int i, j;
    char input[STRINGWIDTH], inputbuf[STRINGWIDTH];
    char *token;
    i = 0;
    while (fgets (input, STRINGWIDTH, keyfptr)) {
    j = 0;
    if ( strlen(input) > (size_t)STRINGWIDTH) {
    fprintf (stderr, "String too long!\n (line:%d)\n", __LINE__);
    exit (-12);
    }
    /*  
     * if left most character = "*" then 
     * this line is a comment and should be ignored. 
     */
    if (input[0] == '*' || input[0] == '\n')  
    continue;

    strcpy (inputbuf, input);  /* make a working copy of input */
    token = strtok (inputbuf, " ");  /* search out space. */

    /* copy keyword into array */
    strncpy (keywords[i].segykeyword, token, 1 + strlen (token));

    /* get function value. */
    token = strtok (NULL, " ");
    keywords[i].segyfunction = atoi (token);  /* convert to value. */
    token = strtok (NULL, " ");

    /* get segy header pointer */
    keywords[i].segyheader = atoi (token);

    /* now start getting any parameters on the line. */
    token = strtok (NULL, " ");
    j = 0;
    while (token != NULL) {
    /* get next token and start putting them in their array location */
    keywords[i].segyparms[j] = atof (token);
    token = strtok (NULL, " ");
    j++;
    if (j > MAXPARMS) {
    printf ("Too many parameters in %s keyword\n", keywords[i].segykeyword);
    printf ("No more than %d allowed per function\n", j - 1);
    exit (-13);
    }
    }      /* end parameter extraction while loop */
    i++;      /* inc counter to keyword number */
    }        /* end keyword string while loop */
    totalkeys = i;
    
}        /* end parseSegyKeys() */

void
loadSegyKeyTableDefaults(SegyKeyTable * keywords)
{
char *defaults[] = {
"ACQUISITION_DATE 3 6 ",
"ACQUISITION_TIME 3 7 ",
"ALIAS_FILTER 5 0 1 71 72 ",
"CDP_NUMBER 5 1 1 12 ",
"CDP_TRACE 5 1 1 14 ",
"CHANNEL_NUMBER 5 1 1 8 ",
"CLIENT 3 1 ", 
"COMPANY 3 2 ",
"DATUM 5 1 1 28 ",
"DELAY 1 55 1000 ",
"END_OF_GROUP 1 88 1 ",
"FIXED_GAIN 1 61 1 ",
"FIXED_GAIN 1 62 1 ",
"HIGH_CUT_FILTER 5 0 1 76 78 ",
"INSTRUMENT 3 4 ",
"JOB_ID 3 9 ",
"LINE_ID 3 3 ",
"LOW_CUT_FILTER 5 0 1 75 77 ",
"NOTCH_FREQUENCY 5 0 1 73 ",
"OBSERVER 3 5 ",
"RAW_RECORD 5 1 1 6 ",
"RECEIVER_LOCATION 5 1 1 42 44 22 ",
"RECEIVER_STATION_NUMBER 1 93 1 ",
"SAMPLE_INTERVAL 1 59 1000000 ",
"SOURCE_LOCATION 5 1 1 38 40 26 ",
"SHOT_SEQUENCE_NUMBER 1 92 1 ",
"SOURCE_STATION_NUMBER 1 94 1 ",
"STACK 1 16 1 ",
"STATIC_CORRECTIONS 5 0 1 50 51 52 ",
"TRACE_SORT 2 1615 ",
"TRACE_TYPE 4 15 ",
"UNITS 3 8 ",
"AMPLITUDE_RECOVERY 0 0 ",
"BAND_REJECT_FILTER 0 0 ",
"DESCALING_FACTOR 0 0 ",
"DIGITAL_BAND_REJECT_FILTER 0 0 ",
"DIGITAL_HIGH_CUT_FILTER 0 0 ",
"DIGITAL_LOW_CUT_FILTER 0 0 ",
"GENERAL_CONSTANT 0 0 ",
"NOTE 0 0  ",
"POLARITY 0 0 ",
"PROCESSING_DATE 0 0 ",
"PROCESSING_TIME 0 0 ",
"RECEIVER 0 0  ",
"RECEIVER_GEOMETRY 0 0 ",
"RECEIVER_SPECS 0 0 ",
"SKEW 0 0  ",
"SOURCE 0 0 ",
"SOURCE_GEOMETRY 0 0 ",
NULL};
    char **defaultsptr=defaults;

    char tmpfilename[L_tmpnam];
    FILE *tmpfileptr;

    tmpnam(tmpfilename);
    tmpfileptr=fopen(tmpfilename, "w");
    /*fwrite(defaults, sizeof(char), strlen(defaults), tmpfileptr); */

    while(*defaultsptr) fprintf(tmpfileptr,"%s\n", *defaultsptr++);

    tmpfileptr=freopen(tmpfilename,"r",tmpfileptr);

    parseSegyKeys(tmpfileptr, keywords);
    fclose(tmpfileptr);
    remove(tmpfilename);
    
}        /* end loadSegyKeyTableDefaults() */


/*-----------------------------------------------------------------------
    READSEGYKEYS
    This routine reads in the valid keywords in file SEGKEYW.ORD 
    and stores the results in global arrays
----------------------------------------------------------------------*/
void
readSegyKeys (SegyKeyTable *keywords)
{
    char *envkeypath;
    char *syskeypath;
#ifdef __MSDOS__
    char *defpath = "segykeyw.ord";
#else
    char *defpath = "/usr/local/lib/segykeyword";
#endif

    FILE *keyfile;

    syskeypath = (char *) malloc ((strlen(defpath)+1) * sizeof(char));
    sprintf (syskeypath, "%s", defpath);
    envkeypath = getenv ("SEGKEYPATH");

    if (envkeypath != (char *) NULL)
    {
    if((keyfile=fopen(envkeypath,"rb")) != (FILE *)NULL)
    fprintf (stderr, "%s used for header word mapping.\n", envkeypath); 
    parseSegyKeys(keyfile, keywords);
    fclose (keyfile);
    } 
    else if ((keyfile = fopen (syskeypath, "rb")) != (FILE *)NULL)
    {
    fprintf (stderr, "Using header word mappings in %s\n",defpath);
    parseSegyKeys(keyfile, keywords);
    fclose (keyfile);
    } 
    else 
    { 
    fprintf (stderr, "Using default header word mappings. \n");
    loadSegyKeyTableDefaults(keywords);
    }
    free(syskeypath);
    return;
}        /* end readsegyKeys() */

/*------------------------------------------------------------
 * KEYCHECK
 * This routine compares list of keywords with the global string 1 and inserts
 * values found in the input string into specified header locations (see
 * segykeyw.ord).  KEYCHECK checks EVERY keyword for a match.  Repeated 
 * keywords are valid.
 * GLOBALS USED:
 * totalkeys int
 *------------------------------------------------------------*/
void
keycheck (SegyKeyTable *keywords)
{
    int i;
    int matchfound;
    char string2[STRINGWIDTH];
    char *token;

    /* start a loop for total keys and compare the input with the list */
    /* make a copy of string1. strtok destroys it's input during token search*/
    /* therefore need to keep a copy for each keyword checked */
    strcpy (string2, string1);

    /* clear the match found flag */
    matchfound = 0;
    for (i = 0; i < totalkeys; i++) 
    {
    /* 
     * restore string1.  It will have been destroyed if an 
     * earlier match has occured. 
     */
    strcpy (string1, string2);  

    if (0 == strncmp (string1, keywords[i].segykeyword, 
        strlen (keywords[i].segykeyword) ) )
    {
    /* have found a match! Set the matchfound flag */
    matchfound = 1;
    /* look up the function and implement it. */
    switch (keywords[i].segyfunction)
    {
    case 0:
        break;    /* null case nothing to do */
    case 1:
    {
    /* function 1 keywords have a single parameter 
     * in the input;  assumed to be a number.  */
    /* find the parameter. */
    /* find first token which will be a keyword */
    token = strtok (string1, " ");  
    /* should be a number. */
    token = strtok (NULL, " ");      
    /* parameter found. pointed to by token. */
    /* function 1 calls for the value on the input line to be mulitplied */
    /* by segykeyword parm 1. and then inserted into header. */
    outhead[keywords[i].segyheader - 1] = 
        atof (token) * keywords[i].segyparms[0];
    break;
    }
    case 2:
    {
    /* function 2 is a special function.  It has to deal with the special 
     * case of trace sorting. In this case the parameter on the input 
     * line is not a number  but a char string.  
     * Notice that spaces in the keywords (i.e. AS ACQUIRED) cause 
     * the parsing to fail.  Words must be 'spaceless' */
    token = strtok (string1, " ");      /* pointing to keyword. */
    token = strtok (NULL, " ");      /* token points to input char. */
    if (0 == strcmp ("AS_ACQUIRED", token))
        segyreelheader[keywords[i].segyheader - 1] = 1;
    else if (0 == strcmp ("CDP_GATHER", token))
        segyreelheader[keywords[i].segyheader - 1] = 2;
    else if (0 == strcmp ("CDP_STACK", token))
        segyreelheader[keywords[i].segyheader - 1] = 4;
    else if (0 == strcmp ("COMMON_OFFSET", token))
        segyreelheader[keywords[i].segyheader - 1] = 3;
    else if (0 == strcmp ("COMMON_RECEIVER", token))
        segyreelheader[keywords[i].segyheader - 1] = 1;
    else if (0 == strcmp ("COMMON_SOURCE", token))
        segyreelheader[keywords[i].segyheader - 1] = 1;
    else if (0 == strcmp ("METERS",token))
        segyreelheader[keywords[i].segyheader -1] = 1;
    else if (0 == strcmp ("FEET",token))
        segyreelheader[keywords[i].segyheader -1] = 2;

    break;
    }      /* end case 2 */
    case 3:
    {
    /* 
     * this case requires the text string found on the input
     * line to be copied to the SEGY-REEL header at the line
     * indicated in the segyheader index. to compute this
     * location it is (line#-1)*80
     */
    strncpy ((char *) &segyreelheader[80 * (keywords[i].segyheader - 1)], 
        string1, 80);
    break;
    }      /* end case 3 */
    case 4:
    {
    /* this case, like 2, calls for special string parsing. */
    /* for TRACE_TYPE, see code for allowable inputs. */
    /* pointing to keyword. */
    token = strtok (string1, " "); 
    /* assume its seismic */
    outhead[keywords[i].segyheader - 1] = 1;  
    /* token points to input char. */
    token = strtok (NULL, " "); 
    if (0 == strcmp ("SEISMIC_DATA", token))
        outhead[keywords[i].segyheader - 1] = 1;
    else if (0 == strcmp ("DEAD", token))
        outhead[keywords[i].segyheader - 1] = 2;
    else if (0 == strcmp ("TEST_DATA", token))
        outhead[keywords[i].segyheader - 1] = 3;
    else if (0 == strcmp ("UPHOLE", token))
        outhead[keywords[i].segyheader - 1] = 5;
    /* RADAR_DATA not defined in SEG-Y assume it to be normal seismic */
    else if (0 == strcmp ("RADAR_DATA", token))
        outhead[keywords[i].segyheader - 1] = 1;
    break;
    }      /* end case 4 */
    case 5:
    {
    /* this case calls for the input data to be inserted into the 
     * sepcified header location of parms 2-10. The normal 
     * 'header' location indicates the type of data, 0=int, 
     * 1=long int, 2=floating point. Parm 1 is the multiplier. */
    token = strtok (string1, " ");
    /* do the integer case first */
    if (keywords[i].segyheader == 0) {
        int paramcount = 1;
        int headindex;
        token = strtok (NULL, " ");        /* token points to input char. */
        while (token != NULL && paramcount < 10) {
        headindex = keywords[i].segyparms[paramcount] - 1;
        outhead[headindex] = atof (token) * keywords[i].segyparms[0];
        paramcount++;
        token = strtok (NULL, " ");  /* token points next input char. */
        }
    }
        /* do the long integer case next */
    else if (keywords[i].segyheader == 1) {
        int paramcount = 1;
        int headindex;
        long *outpoint;
        token = strtok (NULL, " ");    /* token points to input char. */
        while (token != NULL && paramcount < 10) {
        /* set outpoint to beginning of WORD of interest */
        /* need to subtract 2 from the location value. */
        headindex = keywords[i].segyparms[paramcount] - 2;
        outpoint = (long *) &outhead[headindex];
        /* outpoint now points to the area of interest and is 
         * typed correctly. Compute the value, cast it and send it in. */
        outpoint[0] = (long) (atof (token) * keywords[i].segyparms[0]);
        paramcount++;
        token = strtok (NULL, " ");  /* token points next input char. */
        }
    }
    /* finally do floating point case */
    else if (keywords[i].segyheader == 2) {
        int paramcount = 1;
        int headindex;
        float *outpoint;
        token = strtok (NULL, " ");    /* token points to input char. */
        while ((token != NULL) && (paramcount < 10))
        {
        /* set outpoint to point to beginning of WORD of interest */
        /* need to subtract 2 from the location value. */
        headindex = keywords[i].segyparms[paramcount] - 2;
        outpoint = (float *) &outhead[headindex];
        /* outpoint now points to the area of interest and is typed 
         * correctly. Compute the value, cast it and put it in 
         * outhead (using outpoint). */
        outpoint[0] = (float) (atof (token) * keywords[i].segyparms[0]);
        paramcount++;
        /*   ieee2ibm(outpoint,0); *//* convert to ibm format if necessary */
        token = strtok (NULL, " ");  /* token points next input char. */
        }
    }
    break;
    }      /* end case 5 */
    case 6: 
    {
    short day, year;
    token=strtok(string1," "); 
    token=strtok(NULL,"/"); 
    day=atoi(token);
    token=strtok(NULL,"/");
    if (0==strcmp("FEB",token) || 0==strcmp("02",token)) day+=31;
    else if(0 == strcmp("MAR",token) || 0== strcmp("03",token)) day+=59;
    else if(0 == strcmp("APR",token) || 0== strcmp("04",token)) day+=90;
    else if(0 == strcmp("MAY",token) || 0== strcmp("05",token)) day+=120;
    else if(0 == strcmp("JUN",token) || 0== strcmp("06",token)) day+=151;
    else if(0 == strcmp("JUL",token) || 0== strcmp("07",token)) day+=181;
    else if(0 == strcmp("AUG",token) || 0== strcmp("08",token)) day+=212;
    else if(0 == strcmp("SEP",token) || 0== strcmp("09",token)) day+=243;
    else if(0 == strcmp("OCT",token) || 0== strcmp("10",token)) day+=273;
    else if(0 == strcmp("NOV",token) || 0== strcmp("11",token)) day+=304;
    else if(0 == strcmp("DEC",token) || 0== strcmp("12",token)) day+=334;
        token=strtok(NULL," ");/* token points to input char. */
    year=atoi(token);
    if(!year%4 && day>59) day+=1;  /* Yikes.  This may break! */
    outhead[keywords[i].segyheader - 2] = year;
    outhead[keywords[i].segyheader - 1] = day;
    break; 
    } 
    default:    /* case where function not found.. should never happen */
    {
    printf ("Function %d not defined.\n", keywords[i].segyfunction);
    break;
    }
    }            /* end switch */
    break;        /* don't go through rest of for() loop, go to next string */
    }              /* end if */
                  /* loop through and see if it can be found again */
    }                /* end of i loop */
    if (!matchfound)      /* did a match occur */
         printf ("No match found for %s\n", string1);
}             /* end of keysegy */
 

int
main (int argc, char *argv[])
{

#define NFILECHAR 32
    char  prefix[NFILECHAR], seg2file[NFILECHAR], 
    segyfile[NFILECHAR], suffix[NFILECHAR], str[NFILECHAR];
    char *digits = "1234567890";
    char stringtermcount, stringterm1, stringterm2;
    char linetermcount, lineterm1, lineterm2;
    char reserved[19];
    unsigned char datatype;
    int i, j, k; 
    short int ssn; 
    short int reversed = 0;
    int curf, lastf;
    short int blockid, revnum, pointerbytecount, numtrace, stringlength;
    short int first = 1;
    size_t l,ln;
    unsigned short int blockleng;
    long tracepointers[MAXTRACES];
    long outbuf[MAXSAMP];
    long *outheadl=NULL;
    unsigned long numsamples, datalength;
    FILE *f1=NULL, *f2=NULL;
    SegyKeyTable keywords[MAXKEYWORDS];

    double dinbuf[MAXSAMP];
    float *finbuf = (float *)dinbuf;
    long *linbuf = (long *)dinbuf;
    short int *iinbuf = (short int *)dinbuf;
    unsigned char *cinbuf = (unsigned char *)dinbuf;

    float scale=1;

    outheadl = (long *) &outhead[0];
    for (i = 0; i < 1800; i++) segyreelheader[i] = 0;

    if (argc < 3 || argc > 4) { 
    printf("Usage: seg2segy first-seg2file number-of-files [shot-number]\n");
    exit(-1);
    }
    sprintf(seg2file,"%s", argv[1]);
    if (strchr(seg2file,'.')==NULL)
    strcat(seg2file, ".dat");
    l = strcspn(seg2file,".");
    strncpy(segyfile, seg2file, l); 
    segyfile[l]='\0';
    strcpy(suffix,seg2file+l);
    l=strcspn(segyfile,digits);
    if (l==strlen(segyfile) 
    || strspn(segyfile+l,digits)!=strlen(segyfile+l)){ 
    printf("file name seg2 %s invalid\n", seg2file);
    exit(-2);
    }
    strncpy(prefix, segyfile, l); prefix[l]='\0';
    curf=atoi(segyfile+l);
    ln=strlen(segyfile+l);
    strcat(segyfile, ".sgy");
    lastf=curf+atoi(argv[2])-1;
    if (argc==4) ssn=atoi(argv[3]); else ssn=1;

    f2 = fopen(segyfile, "wb");
    if (f2 == (FILE *) NULL) {
    fprintf (stderr, "**OUTPUT FILE OPEN FAILURE**\n **ABORTING**\n");
      exit (-3);
    }

    readSegyKeys (keywords);

    /* start the big loop ... */
    for(; curf<=lastf; curf++) {
    strcpy(seg2file,prefix);
    sprintf(str,"%d",curf);
    l=strlen(str);
    while(l<ln) { strcat(seg2file,"0"); l++; }
    strcat(seg2file,str);
    strcat(seg2file,suffix);
    if ((f1=fopen(seg2file,"rb")) == (FILE *)NULL) {
    fprintf (stderr, "\n***ERROR OPENING FILE %s***\n", seg2file);
    fprintf (stderr, "Skipping to next file number.\n");
    continue;    /* go to end of loop, try next file */
    }
    fread (&blockid, 2, 1, f1);
    if (blockid == 0x553a) 
    reversed = 1;
   
    if (blockid != 0x3a55) {
    if (!reversed) {
    fprintf (stderr, "Not SEG-2 data can not continue\n");
    exit (-4);
    }
    }

    fread (&revnum, 2, 1, f1);
    fread (&pointerbytecount, 2, 1, f1);
    fread (&numtrace, 2, 1, f1);
    if (reversed) {
    swapshort (&revnum);
    swapshort (&pointerbytecount);
    swapshort (&numtrace);
    }

    printf ("File %s, Data Format Revision: %d, Number of traces: %d\n", seg2file, revnum, numtrace);
    fread (&stringtermcount, 1, 1, f1);
    fread (&stringterm1, 1, 1, f1);
    fread (&stringterm2, 1, 1, f1);
    fread (&linetermcount, 1, 1, f1);
    fread (&lineterm1, 1, 1, f1);
    fread (&lineterm2, 1, 1, f1);
    fread (reserved, 1, 18, f1);  /* reserved block, not used */

    if (numtrace > (pointerbytecount / 4)) {
    fprintf (stderr, "Number of traces greater than number of trace pointers\n");
    fprintf (stderr, "Number of pointers = %d\n", pointerbytecount / 4);
    fprintf (stderr, "Due to this inconsistency processing must stop\n");
    exit (-5);
    }
    fread (tracepointers, 4, numtrace, f1);
    if (reversed) {
    for (i = 0; i < numtrace; i++)
    swaplong (&tracepointers[i]);
    }

    /* now read file descriptor block.  */
    fread (&stringlength, 2, 1, f1);
    if (reversed)
    swapshort (&stringlength);

    while (0 != stringlength) {
      fread (string1, 1, stringlength - 2, f1);
      keycheck (keywords);
      fread (&stringlength, 2, 1, f1);
      if (reversed) swapshort (&stringlength);
    }
    for (j = 0; j < numtrace; j++) {
      for (i = 0; i < 120; i++)
        outhead[i] = 0;
      printf ("trace-%d-\r", j + 1); fflush(stdout);
      fseek (f1, tracepointers[j], SEEK_SET);
      fread (&blockid, 2, 1, f1);
      if (reversed)
        swapshort (&blockid);
      if (blockid == 0x2244) {
        /* reversed=1; should already know this */
        fprintf (stderr, "Opps, I've blown it here.... (line:%d)\n", __LINE__);
        exit (-6);
      }
      if (blockid != 0x4422) {
        fprintf (stderr, "Not a SEG-2 trace header.  Can not process %x (line %d)\n", blockid, __LINE__);
        exit (-7);
      }
      fread (&blockleng, 2, 1, f1);
      if (reversed)
        swapshort ((short *) &blockleng);
      fread (&datalength, 4, 1, f1);
      if (reversed)
        swaplong ((long *) &datalength);
      fread (&numsamples, 4, 1, f1);
      if (reversed)
       swaplong ((long *) &numsamples);
    if (numsamples >= MAXSAMP){ 
    fprintf(stderr, "Your data contains more samples than I can handle\n");
    exit(-8);
    }
      fread (&datatype, 1, 1, f1);
      fprintf(stderr,"Data type = %d \n", (int) datatype);
      if (datatype > 5 || datatype < 1) {
        fprintf (stderr,"Data type %d not available/valid\n", (int) datatype);
        break;
      }
      outhead[57] = numsamples;
      fread (reserved, 1, 19, f1);
      fread (&stringlength, 2, 1, f1);
      if (reversed)
        swapshort (&stringlength);
      while (0 != stringlength) {
        fread (string1, 1, stringlength - 2, f1);
        keycheck (keywords);
        fread (&stringlength, 2, 1, f1);
        if (reversed)
          swapshort (&stringlength);
      }
    
      fseek (f1, blockleng + tracepointers[j], SEEK_SET);
      switch ((int) datatype)
      {
    case 1:
        fread (iinbuf, 2, (int) numsamples, f1);
        if (reversed) {
        for (i = 0; i < (int) numsamples; i++)
        swapshort (&iinbuf[i]);
        }
        for (k = 0; k < numsamples; k++)
        outbuf[k] = iinbuf[k];
        break;
    case 2:
        fread (linbuf, 4, (int) numsamples, f1);
        if (reversed) {
        for (i = 0; i < (int) numsamples; i++)
        swaplong (&linbuf[i]);
        }
        for (k = 0; k < numsamples; k++)
          outbuf[k] = linbuf[k];
        break;
    case 3:
    {
        unsigned long totalbytes, subpointer;
        unsigned int expo;
        long longdat;
        short int sdata; /*modified version by PM */
        totalbytes = (numsamples * 5) / 2;
        fread (cinbuf, 1, (size_t) totalbytes, f1);
        /*  Original Code SU-36 3rd Party
        for (k = 0; k < (numsamples);) {
        subpointer = (k / 4) * 5;
        expo = (unsigned) iinbuf[subpointer++];
        for (i = 0; i < 4; i++) {
        if (0x8000 & iinbuf[subpointer]) 
        longdat = 0xffff8000;
        else 
        longdat = 0;
        longdat = longdat | ((long) iinbuf[subpointer++] << (0x000f & expo));
        expo >>= 4;
        outbuf[k++] = longdat;
        }
        }
        */
    /*modified version by P.Michaels <pm@cgiss.boisestate.edu> */
    /*fixes sawtooth conversion error on large negative values */
        for (k = 0; k < (numsamples);) {
        subpointer = (k / 4) * 5;
        expo = (unsigned) iinbuf[subpointer++];
        for (i = 0; i < 4; i++) {
                    sdata=iinbuf[subpointer++];
                              if (sdata>0) 
                                   {       
                                    longdat=(long) sdata;
                                    longdat=longdat << (0x000f & expo);
                                   }       
                                else    
                             {       
                                        longdat=(long) -sdata; 
                                    longdat=longdat <<  (0x000f & expo);
                                        longdat = -longdat; 
                                  } /* endif */ 
                        expo >>= 4;
        outbuf[k++] = longdat;
                    } /* next i */
            } /* next k */
        /* end of modifications */
        if (reversed) {
        for (i = 0; i < numsamples; i++)
        swaplong (&outbuf[i]);
        }
    }
    break;
    case 4:
    fprintf(stderr,"Reading type 4/n");
    fread (finbuf, 4, (int) numsamples, f1);
        if (reversed) {
        long *buf = (long *) dinbuf;
        for (i = 0; i < numsamples; i++)
        swaplong (&buf[i]);
        }

        /* scale values */
        for (k = 0; k < numsamples; k++) 
        outbuf[k] = finbuf[k]/scale;

        for (k = 0; k < numsamples; k++) 
        fprintf(stderr,"dataval = %ld \n", outbuf[k]); 

        fprintf(stderr," if dataval = 0 then increase the value of scale, recompile\n");
        break;
    case 5:
    fread (dinbuf, 8, (int) numsamples, f1);
        if (reversed) {
        long *buf = (long *) dinbuf;
        for (i = 0; i < numsamples * 2; i++)
        swaplong (&buf[i]);
        }
        for (k = 0; k < numsamples; k++)
        outbuf[k] = dinbuf[k];

        break;
    }      /* end switch */
    /* set vertical stack traces=1 */

/* 
    if(outhead[15]==0) outhead[15]=1; 
    if(outheadf[59]==0.0) gain=1.; else gain=outheadf[59];
    for(i=0;i<numsamples;i++)
            outbuf[i]*=gain/outhead[15];
    */
        /* assign the original field record number as the current file number */
        if (outheadl[2] == 0) outheadl[2] = (long) curf;
        /* set trace type  as  sesmic data */
        if (outhead[14] == 0) outhead[14] = 1;

        /* set last trace flag (modified segy) */
        if (j == numtrace - 1 && outhead[87] == 0) {
        outhead[87] = 1;
        ssn = ssn + 1;
        }

        /* from rec-station-number and source-station-number (93 and 94) */
        /* distance from source to receiver */
        /* outheadl[9]=(long)(abs(outhead[93]-outhead[92])); */
        /* set group for trace one and roll switch position  */
        outhead[85] = outhead[86] = 
        (int) (1 + labs ((long) outhead[92] - outheadl[3]));

        /* special case, execute on first pass only... */
        if (first == 1) {
        first = 0;
        segyreelheader[1606] = numtrace;
        segyreelheader[1608] = outhead[58];
        segyreelheader[1609] = outhead[58];
        segyreelheader[1610] = numsamples;
        segyreelheader[1611] = numsamples;
        segyreelheader[1612] = 2;

        if (!reversed) /* swap only if we are on a little endian  machine */
        {  
            for (k = 1600; k < 1606; k += 2)
            swaplong ((long *)&segyreelheader[k]);
          for (k = 1606; k < 1630; k++)
            swapshort((short *)&segyreelheader[k]);
        }
        fwrite (segyreelheader, 1, 3600, f2);  /*  create the segy headers */
        }

        if (!reversed) { /* swap only if we are on a little endian  machine */
        /* first swap longs */
        for (k = 0; k < 7; k++)
            swaplong((long *)&outheadl[k]);
        for (k = 9; k < 17; k++)
          swaplong((long *)&outheadl[k]);
        for (k = 18; k < 22; k++)
          swaplong((long *)&outheadl[k]);
        /* now swap the shorts */ 
        for (k = 14; k < 18; k++)
          swapshort((short *)&outhead[k]);
        for (k = 34; k < 36; k++)
          swapshort((short *)&outhead[k]);
        /* for(k=44;k<90;k++)  *//* error: should have gone beyond 95 word */
        for (k = 44; k < 95; k++)
          swapshort((short *)&outhead[k]);
        }
        if (120 != (k = fwrite (outhead, 2, 120, f2))) {      /* write header */
        fprintf (stderr,"\nWrite failure during header write\n");
        exit (-9);
        }
        if (!reversed) {
    for (k = 0; k < numsamples; k++)
        swaplong ((long *)&outbuf[k]);
    }
    
    if ((int) numsamples != (k = fwrite (outbuf, 4, (int) numsamples, f2))) {
    fprintf (stderr,"Write failure during trace write\n");
    exit (-10);
    }

    }      /* end trace loop */
    fclose (f1);
    outhead[87] = 0;    /* reset last trace flag. */
    }        /* end kk loop */
    fclose(f2);
    return 0;
}        /* end main */

以上代码可以顺利将外部磁盘中的SEISMIC BINARY DATA读取到内存中。特别是MATLAB的MAT二进制格式是处理所有数据的基础。

在matlab version 5中,MAT文件由一个128字节的文件头和若干个数据单元组成。每个数据单元有一个8个字节的tag,用于说明数据单元的占用的字节数(不包括tag的8个字节)和数据类型。

文件头header里有124字节的文本描述区域和4个字节的flag。flag中的前2个字节说明version,后两个字节是endian indicator。文本描述区域主要说明MAT文件的版本,创建于哪个平台,创建时间。flag中的version说明的是创建这个MAT文件的matlab的版本。edian indicator包括两个字符M和I。

 
     char mat_data_fhead1[51] = 
           {"MATLAB 5.0 MAT-file, Platform: PCWIN, Created on: "};   
     char mat_data_fhead2[51] =   {"                                                  "};    
     char mat_data_fhead3[4] = {0, 0x01, 0x49, 0x4d};   
     char* datetime = NULL;   
     time_t ltime;   
     tm* today;   
 
     time(ltime);   
     today = localtime(ltime);   
     datetime = asctime(today);   
 
     fwrite(mat_data_fhead1, 1, 50, fp);   
     fwrite(datetime, 1, 24, fp);   
     fwrite(mat_data_fhead2, 1, 50, fp);   
     fwrite(mat_data_fhead3, 1, 4, fp);

关于edian:endian: The ordering of bytes in a multi-byte number.
定义:在计算机系统体系结构中用来描述在多字节数中各个字节的存储顺序。相关概念还有MSB(Most Significant Bit/Byte)和LSB(Least Significant Bit/Byte)。在所有的介绍字节序的文章中都会提到字节序分为两类:Big-Endian和Little-Endian。引用标准的Big-Endian和Little-Endian的定义如下:
a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
c) 网络字节序:TCP/IP各层协议将字节序定义为Big-Endian,因此TCP/IP协议中使用的字节序通常称之为网络字节序。
PS:有些文章中称低位字节为最低有效位,高位字节为最高有效位。

如果edian indicator中的值为MI,则读取MAT数据时应该用IM的顺序。若对于16bit的数据,则要进行两个字节数据的交换。

数据单元的格式

每个数据单元开头都有8个字节的tag用于说明数据单元存储的数据类型和字节数(不包括tag的8个字节)。version5支持多种数据类型。data type中的值为1到14。除了用数值表示某种类型外,还用标识单词联系一种类型。例如data type中存储的是数值1时,代表8bit singed,它的标识单词就为miINT8,方便了用户记忆。值14的标志单词是miMATRIX,代表一种矩阵数据。

数据单元tag中的字节数是每个数据单元不包括8个字节tag的数据字节个数。

接下来的就是存储的数据。数据需要64bit对齐,不够时要补齐到64bit。数据类型是miMATRIX时,数据单元tag中字节数包括矩阵中每个padding的数据个数。其他数据类型时,字节数不包括padding的个数。

当存储的数据不超过4个字节时,还可以采用压缩的数据单元格式。用4个字节存储tag,另外4个字节存储数据。在编程时,tag的前两个字节不为零时,则说明采用的是压缩的数据单元格式。在把数据写入MAT文件中时,压缩的数据单元格式是优先选择的。

datatype值为14的数据类型是:array data,包括了各种类型的array,如数值矩阵,字符矩阵,稀疏矩阵。是一种复合类型结构。字节数包括所有subelement字节数之和。每个subelement都有自己的tag。主要有array flags, dimensions array subelement, array name subelement, real part(pr)subelement, image part subelement。

下图为MAT文件格式的FORTRAN,C等语言的读写程序:

2.python中的obspy及sgyio库的调用

下面以obspy库的调用为例,打开一个sgy文件的命令:

import obspy

t=obspy.read('Model+GathEP-Z.sgy')

tr=t[0]

 print(tr.stats)
         network:
         station:
        location:
         channel:
       starttime: 1970-01-01T00:00:00.000000Z
         endtime: 1970-01-01T00:00:00.485200Z
   sampling_rate: 2500.0
           delta: 0.0004
            npts: 1214
           calib: 1.0
         _format: SEGY
            segy: AttribDict({'trace_header': LazyTraceHeaderAttribDict({'unpacked_header': b'\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x01\xff\xff\xfe\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x9c\xff\x9c\x00\x00\xc3P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\xbe\x01\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'endian': '>', 'sample_interval_in_ms_for_this_trace': 400, 'year_data_recorded': 0})})
>>> tr.plot()

                                                                          单道地震数据显示

对于地震多道剖面数据显示,需要计算偏移距

>>> i=0
>>> for tr in t:
...   i=i+1
...   tr.stats.distance=i*10
...
>>> t.plot(type='section')

>>pip install ipykernel

>>python -m ipykernel install --user --name python33 --display-name python33

 

地震剖面数据显示

读取地震事件的函数为obspy.readevents('*.ndx')

[1]Seismic Data Format

[2]https://pubs.usgs.gov/of/2003/ofr-03-141/ofr_03_141_508.pdf

[3]Seismic Conversion Shareware

[4]Barry, K. M., Cavers, D. A. and Kneale, C. W., 1975, Report on recommended standards for digital tape formats: Geophysics, Soc. of Expl. Geophys., 40, 344-352. Dobrin, M. B., 1960, [5]Geophysical prospecting: McGraw-Hill, pp 71-73. Pullan, S. E., 1990, Recommended standard for seismic (/radar) files in the personal computer environment: Geophysics, Soc. of Expl. Geophys., 55, 1260-1271.

[5]http://www.interpex.com/ftp/ixseg2segy/ixseg2segysetup.exe

[6]https://www.interpex.com/ftp/ixseg2segy/ixseg2segymanual.pdf

[7]https://02cea61.netsolhost.com/Ordering.htm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weiyiwen1982

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值