1. SEG-Y文件格式解析

SEG-Y 是地震勘探领域最通用的道数据交换格式,由 SEG(勘探地球物理学家协会)在 1975 年标准化。它的设计目标很朴素:让不同厂商的采集系统、处理软件和解释平台能够交换同一条地震测线,而不必关心对方的内部存储方式。理解 SEG-Y 的关键,不是记住某个软件怎么点按钮,而是建立一张“字节地图”——知道文件从第 1 个字节到最后一个字节分别放了什么,每个字段占几个字节、用什么编码、代表什么物理量。有了这张地图,后面用 Python 读取道头、批量切分、改写坐标、拼接测线,才不会在偏移量上出错。

一、整体结构:三段头 + 道记录

一个标准 SEG-Y 文件由四部分组成,顺序固定:3200 字节的 EBCDIC 文本头、400 字节的二进制文件头、若干道头、若干道数据。前两部分合称“文件头”,只出现一次;道头和道数据则以“道”为单位交替重复,每一道都是“240 字节道头 + N 个采样点数据”的固定组合。因此文件总长度满足:

文件长度 = 3200 + 400 + 道数 × (240 + 每道采样点数 × 每采样字节数)

这个等式是排查文件是否完整的第一把尺子。如果实际文件长度与按道头推算的长度不一致,通常意味着文件被截断、道数记录错误,或者采样格式字段与实际数据不符。下面这张图给出了 SEG-Y 的字节级布局与各段之间的衔接关系:

SEG-Y 文件字节布局(Rev1 标准) EBCDIC 文本头 字节 1 – 3200(3200 B) 40 行 × 80 字符,人工可读说明 二进制文件头 字节 3201 – 3600(400 B) 道数、采样间隔、采样格式等 道记录(重复 N 次) 每道 = 240 B 道头 + 道数据 N 由二进制头第 3213–3214 字节给出 单道记录展开: 道头 Trace Header 240 字节,字节 1–240 道数据 Trace Data 采样点数 × 每采样字节数(如 4 B IBM 浮点) 下一道道头 紧接上一道数据之后 二进制文件头关键字段(字节号从文件起始计,1 起): 字节位置 字段 类型/长度 含义 3213–3214 道数 int16 文件中的总道数 3217–3218 采样间隔 int16(μs) 时间采样步长,如 2000 = 2 ms 3225–3226 采样格式码 int16 1=IBM浮点,3=int16,5=IEEE浮点

二、EBCDIC 文本头:不是给人“直接看”的

前 3200 字节是 40 行、每行 80 个字符的文本说明,内容包括测线号、采集日期、仪器型号、处理历史等。它使用 EBCDIC 编码而非 ASCII,这是早期 IBM 大型机的遗留。用 Python 直接以文本方式打开会看到乱码,正确做法是按字节读入后转码:

with open("line01.sgy", "rb") as f:
    ebcdic = f.read(3200)
text = ebcdic.decode("cp500")   # cp500 是常用 EBCDIC 代码页
for i in range(0, 3200, 80):
    print(text[i:i+80].rstrip())

需要注意,文本头是“说明性”的,不同处理系统写入的内容格式并不统一,程序不应依赖它做解析,只适合人工核对。真正驱动读取逻辑的是二进制头。

三、二进制文件头:解析的“总控参数”

字节 3201–3600 共 400 字节,全部为大端序(big-endian)整数。它规定了整个文件的全局参数,其中三个字段最关键:道数(3213–3214)、采样间隔(3217–3218,单位微秒)、采样格式码(3225–3226)。采样格式码决定了道数据如何解码,常见取值:1 表示 4 字节 IBM 浮点,2 表示 4 字节定点,3 表示 2 字节补码整数,5 表示 4 字节 IEEE 浮点。很多“读出来全是天文数字”的问题,根源就是把 IBM 浮点当成了 IEEE 浮点。

此外,每道采样点数通常不放在文件头,而是放在道头的 115–116 字节处;文件头的 3221–3222 字节给出的是“每道采样点数”的期望值,二者不一致时应以道头为准并记录异常。

四、道头:240 字节里的“道身份证”

每道开头 240 字节是道头,同样为大端序。它描述这一道自己的属性,是批量处理时最常读写的区域。工程上高频使用的字段包括:

道头字节字段典型用途
1–4道序号校验道顺序
9–12CDP 号抽道集、分选
17–20炮点桩号观测系统核对
21–24检波点桩号观测系统核对
73–76 / 77–80炮点 X / Y 坐标坐标换算与成图
81–84 / 85–88检波点 X / Y 坐标坐标换算与成图
115–116本道采样点数计算道数据长度
117–118本道采样间隔覆盖文件头默认值

坐标字段有一个经典陷阱:SEG-Y 标准规定坐标以“标量”形式存储,道头 71–72 字节给出坐标标量,实际坐标 = 原始整数值 × 标量(标量为正表示乘,为负表示除)。如果忽略标量,坐标可能整体放大或缩小若干倍,成图时测线会“飘”到错误位置。

五、道数据:按格式码解码

道数据紧跟在道头之后,长度 = 采样点数 × 每采样字节数。以格式码 1(IBM 浮点)为例,Python 标准库没有现成解码器,需要按位运算转换:IBM 浮点的符号位、7 位阶码(以 16 为底)和 24 位尾数与 IEEE 754 不同。实践中更稳妥的做法是使用 segyio 或 obspy 等成熟库读取,自己实现时则务必用已知振幅的测试道验证解码正确性。

判断一个 SEG-Y 文件能否被正确解析,最快的自检是:用二进制头道数 × 每道长度 + 3600 是否等于文件实际大小;再用道头采样点数与文件头采样间隔交叉核对。两项都通过,说明字节布局理解无误,后续读取才有意义。

把上述结构串起来看,SEG-Y 的解析本质是一次“按偏移量取字段”的过程:先读 3600 字节文件头拿到全局参数,再以 240 字节为步长定位每一道,读道头得到本道采样点数与坐标信息,最后按格式码解码道数据。掌握了这张字节地图,后续用 Python 批量读取、筛选、改写道头就有了可靠依据。