地震数据文件读取——以SEG-Y格式为例
2015-12-19 16:31阅读:
1、引 言
地震勘探是利用地下介质弹性和密度的差异,通过观测和分析大地对人工激发地震波的响应,推断地下岩层的性质和形态的地球物理勘探方法,是钻探前勘测石油与天然气资源的重要手段,在煤田和工程地质勘查、区域地质研究和地壳研究等方面也得到了广泛应用。
近几十年来,随着电子计算机的广泛应用,地震勘探的数据采集和装备得到了极大的改进,数据处理技术和解释方法也得到迅速的发展。野外采集的地震数据通常都需要经过繁琐的室内资料处理才能用于地质解释。
现代采集的地震数据都是以二进制文件的形式存放的,这些文件的处理及显示等工作都可以由一些商业化的软件来完成。但作为一个从事地震资料处理工作的技术人员或学习爱好者,有时会有些想法或者灵感,而这些所谓的大型软件并不能允许你去做某些试验来验证你的想法或实现你的灵感,这时候你就不得不自己动手去兑现自己的想法或灵感了。
那么,问题来了,首先,如何读取地震数据?
2、地震数据文件
地震数据是以各种格式存放的。常见的地震数据格式有SEG-D、SEG-Y、SED-2格式等,而同样的格式,还有微机版、工作站版。简单的说,工作站版和微机版数据格式的区别就是数据读写的方式不同(地震数据处理一般在工作站上进行,而微机平台是我们试验自己想法的私人空间)。野外采集的数据格式一般是工作站版的,当然我们可以通过一些小工具将工作站版的数据转换成微机版的,但是当试验需要频繁地更换数据进行验证时,一个一个地手
动转换数据格式就显得有些繁琐(LOW)笨拙。
第一次接触“读取地震数据文件”这个问题是做本科毕业设计的时候,那时候真是2YOUNG2SIMPLE,所以也是选择了忍一时风平浪静,并没有去死(攻)磕(克)这个“难题”,只是借用了个小工具(SEGY文件分析)把工作站版的数据转换成微机版,然后继续前进,顺(糊)利(弄)地完成了本科毕业(学位)论文。
3、标准“.SEG-Y”文件
SEG-Y格式的地震数据文件,属于典型的流式文件,它的信息和数据都是按字节顺序一个个地存放的,每个字节都有其特定的含义。(既然有规律那就好办了)
这种格式的文件,由文件头部的3600字节(3200字节文本文件头+400字节二进制文件头)以及地震道(240字节道头+地震数据体)组成。
文件头前部的3200字节共分为40行,每行80个字符,但这些字符不是ASCII码,是一种称为EBCDIC的编码(这个我也不知道是什么鬼)。通常这部分可以直接跳过,暂时没发现对数据处理有什么影响。
接下来是400字节的二进制文件头部分,这里有重要的文件信息,比如地震记录的采样率、采样点数、数据类型等等,这些记录信息决定了地震数据体的各种信息,包含有长整型数和短整型数,必须严格“对号入座”才能完整地得到它们所代表的含义。
而400字节二进制文件头后面就是最最重要的地震道记录了,每个地震道由240字节道头和地震数据(长度由采样点数和数据类型决定)组成。
更多关于SEG-Y数据格式的资料可以百度“SEGY”或者上http://www.seg.org/(Society of
Exploration Geophysicist,勘探地球物理学家学会)去搜罗。
4、读取工作站版“.SEG-Y”文件
工作站版(包括IEEE型和IBM型)的存储格式是高字节在前、低字节在后,即BigEndian,微机版则是低字节在前、高字节在后,即LittleEndian。工作站版的16位(短)、32位(长)整型转换成微机版只需交换高、低位。
(感觉我说半天也不如直接送上代码!仅供参考!!!)
以下是把16位整型的工作站版数据(BigEndian)转换成微机版(LittleEndian)的C语言函数:
- short int i16BE2LE(short int
bed)
- {
- union
info
-
{
-
short int
si;
-
char ch[2];
-
};
- union
info td;
- char
cod;
-
td.si=bed;
-
cod=td.ch[0];
-
td.ch[0]=td.ch[1];
-
td.ch[1]=cod;
- return
td.si;
- }
以下是把32位整型的工作站版数据(BigEndian)转换成微机版(LittleEndian)的C语言函数:
- long int i32BE2LE(long int bed)
- {
- union
info
-
{
-
long int
li;
-
char ch[4];
-
};
- union
info td;
- char
cod1,cod2;
-
td.li=bed;
-
cod1=td.ch[0];
-
cod2=td.ch[1];
-
td.ch[0]=td.ch[3];
-
td.ch[1]=td.ch[2];
-
td.ch[2]=cod2;
-
td.ch[3]=cod1;
- return
td.li;
- }
以下是把32位IEEE浮点型(据说IBM版的更麻烦,我也还没来得及驾驭)的工作站版数据(BigEndian)转换成微机版(LittleEndian)的C语言函数:
- float f32BE2LE(float
bed)
- {
-
union info
-
{
-
float
f;
-
char
ch[4];
-
};
-
union info td;
-
char cod1,cod2;
-
td.f=bed;
-
cod1=td.ch[0];
-
cod2=td.ch[1];
-
td.ch[0]=td.ch[3];
-
td.ch[1]=td.ch[2];
-
td.ch[2]=cod2;
-
td.ch[3]=cod1;
-
return td.f;
- }
And,16位整型、32位整型和32位IEEE浮点型的微机版数据转换成工作站版的步骤还是交换高、低字节。在C语言里面,我们可以这么干:
- #define i16LE2BE i16BE2LE
- #define i32LE2BE i32BE2LE
- #define f32LE2BE f32BE2LE
没错,其实就是强迫症犯了,无法阻止自己把程序写规范点。这里的函数名完全可以用ABCDEF代替,你开心就行~~
6、总
结
当初遇到这个问题的时候多么希望有人能够给我指点迷津,然而并没有!幸好后来随着自己知识的积累,做东西的需要,偶然之间就把问题解决了。PERFECT。
鉴于最近有好几个师弟过来问我读取SEG-Y文件的问题,心血来潮就把自己曾经的困惑和解决方法给整理了一下,希望对需要的人有所帮助或启发。(但估计我还是没有把自己想说的东西表达明白了)
如果你遇到了跟我同样的问题,可以给我留言,我会尽我所能帮助你,就像当初希望有人能够帮助我指明方向一样。
GOODBYE &
GOODLUCK