在地球物理研究中,许多老旧台站和教学实验仍采用ASCII文本保存地震波形,每一行可能是等间隔采样的时间位移对,也可能是固定宽度的多通道记录。用Python配合Matplotlib处理这类数据,核心在于先把字符串准确解析成数值数组,再根据采样率还原时间轴,最后选择折线图或图像来呈现。下面以常见的两列空格分隔数据为例,展示完整流程。

ASCII地震数据的读取与清洗
ASCII地震文件往往带有表头注释,以井号或字母开头,真正的数据行才是浮点数。如果直接用numpy的loadtxt读取,遇到非数值行会报错,因此要先逐行判断。可以打开文件,用startswith过滤掉注释,再把剩余行按空白切分,转成float后追加到列表。这种写法比正则更直观,也方便处理偶尔出现的连续空格。
另一种情况是固定格式的宽度记录,比如每帧八十个字符、每四个字符一个采样。此时应该用字符串切片而非split,否则错位会导致数值完全错误。清洗阶段还要处理缺失值,有些台站会用9999或-12345表示断记,需要替换成nan,避免后续绘图出现垂直直线误导判断。下面代码演示了通用读取函数。
def read_ascii_seismic(path):
rows = []
with open(path, 'r') as f:
for line in f:
line = line.strip()
if not line or line[0] in '#%':
continue
parts = line.split()
try:
vals = [float(x) for x in parts]
except ValueError:
continue
if 9999.0 in vals:
vals = [float('nan') if v == 9999.0 else v for v in vals]
rows.append(vals)
return rows
data = read_ascii_seismic('seismic.txt')
print(len(data), 'rows loaded')
当数据量达到几十万行时,纯Python循环会偏慢,可改用numpy的genfromtxt并指定comments参数跳过表头,它内部用C实现,速度提升明显。但要注意genfromtxt对不规则列数容忍度低,若某些行少一两列,会填充nan或报错,所以前期用简单脚本统计每行列数是必要的健康检查。
用Matplotlib绘制时间序列曲线
拿到二维列表后,通常第一列是时间或序号,第二列是振幅。若只有序号,需要除以采样率得到秒。Matplotlib的plot函数适合画单道波形,它能自动处理nan,在断记处断开线条。设置figsize和dpi可让导出图片清晰,xlabel写时间秒、ylabel写加速度或位移,符合论文习惯。
多台站对比时,用subplot堆叠多个坐标轴更直观。可以用共享x轴避免重复标注,突出不同方位的到时差。下面示例把前两道画成上下两张图,并标出疑似P波位置。实际分析中还可叠加filter后的曲线,用不同颜色区分原始与去趋势结果。
import matplotlib.pyplot as plt
import numpy as np
arr = np.array(data)
t = arr[:, 0] / 100.0 # 假设100Hz采样
amp = arr[:, 1]
fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True, figsize=(10, 6))
ax1.plot(t, amp, color='black', linewidth=0.6)
ax1.set_ylabel('Channel 1')
ax2.plot(t, arr[:, 2], color='gray', linewidth=0.6)
ax2.set_ylabel('Channel 2')
ax2.set_xlabel('Time (s)')
ax1.axvline(12.4, color='red', linestyle='--')
plt.tight_layout()
plt.savefig('waveform.png', dpi=150)
折线图虽然精细,但在长时间记录里像素密集,肉眼难辨频带变化。此时可改用specgram画频谱图,或者把连续段重采样后做图像。要注意plot默认连线会在nan处断掉,如果希望断记区域留白而不是跳线,需手动切片分段绘制,否则可能看到斜跨屏幕的假信号。
将多道ASCII数据转为剖面图像
当ASCII文件包含几十个通道、每个通道等长度时,可把数据整理成二维矩阵,用imshow展示伪彩色剖面。行代表通道深度或距离,列代表时间,颜色映射用seismic或gray,能一眼看出同相轴倾斜,也就是震相随距离延迟。这种方法比逐条线看更高效,常用于初至拾取前的快速浏览。
矩阵构造时要注意转置方向,Matplotlib的imshow默认原点在左上,而地震剖面通常时间向下增加,因此要设origin='upper'并调整extent参数,让y轴显示真实时间。若ASCII里通道顺序和台站位置不对应,还需按坐标排序,否则剖面会空间错乱。下面代码把前三列通道拼成图像。
matrix = np.array(data)[:, 1:4].T # 3通道,转置为通道×时间
plt.imshow(matrix, aspect='auto', cmap='seismic',
extent=[0, matrix.shape[1]/100.0, matrix.shape[0], 0])
plt.colorbar(label='Amplitude')
plt.xlabel('Time (s)')
plt.ylabel('Channel index')
plt.title('Seismic section from ASCII')
plt.show()
剖面图像虽快,却丢失了精确数值,所以正式处理仍要结合折线图定位。如果ASCII数据带有经纬度表头,还可把剖面映射到地图底图上,用basemap或cartopy叠加,但这已超出基础Matplotlib范围。掌握文本解析与两种绘图方式的切换,就能覆盖多数教学与巡检场景,不必依赖商业软件导入。
PythonMatplotlibascii_seismic_data修改时间:2026-08-17 19:02:30