简介这份资源面向地震勘探与地球物理领域的学习者和工程技术人员聚焦面波数据处理与速度剖面连接这一关键环节提供CCSWSWIN与CCSWSMAP两款软件的配套工具与说明文档可用于浅部地壳结构分析、速度分层建模及多测线剖面拼接等实际场景。压缩包共91个文件约1.8MB以exe可执行程序、htm帮助页面、gif与bmp界面图示为主辅以doc使用说明、sys与vxd驱动文件及少量c、h源码兼顾软件运行、加密狗驱动安装与操作指引。资源已有923人学习下载说明其在同类工具中具备一定参考价值。读者可从中获得面波预处理、相位解缠、频散分析到速度模型构建与剖面连接的完整软件环境配合图文帮助快速理解参数设置与结果解读适合初学者入门及技术人员对照实践。1. 面波处理及剖面连接软件一份能直接跑起来的地震面波工程工具第一次拿到这个资源包时我正被一条测线的面波数据卡住——频散曲线提取出来是散的相邻两个排列的剖面接不上手工在表格里对坐标对到凌晨。这个软件解决的正是这类问题把面波数据的整理、频散分析、剖面拼接串成一条可复现的流程而不是散落在若干脚本和 Excel 里。它适合做浅层地震勘探、岩土波速测试、场地评价的工程人员也适合想二次开发面波处理链路的开发者。下面按「能干什么、怎么跑、怎么改」拆开讲重点放在目录结构、核心处理模块和剖面连接的具体实现上读完你应该能自己把数据喂进去、把结果导出来。2. 工程结构与运行环境从目录到第一条频散曲线2.1 目录布局与模块职责这类面波处理软件通常按「数据层—算法层—界面层—输出层」四块组织拿到包先别急着点运行把目录扫一遍能省掉后面一半的排查时间。典型结构如下project/ ├── main.py # 程序入口负责参数解析与流程调度 ├── config/ │ └── default.yaml # 采样率、道间距、频散参数等默认配置 ├── data/ │ ├── raw/ # 原始 SEG-2 / SAC / txt 记录 │ └── processed/ # 预处理后的中间结果 ├── core/ │ ├── io_reader.py # 多格式地震记录读取 │ ├── preprocess.py # 去直流、滤波、道均衡 │ ├── dispersion.py # 频散曲线提取f-k / 相移法 │ ├── inversion.py # 层状模型反演可选 │ └── profile_join.py # 剖面连接与坐标对齐 ├── ui/ │ └── main_window.py # 图形界面若为 GUI 版本 ├── output/ │ └── reports/ # 频散图、剖面图、文本结果 └── requirements.txtcore是真正要读的部分ui只是壳。我一般先看io_reader.py支持哪些格式再看dispersion.py用的是哪种频散提取方法最后看profile_join.py怎么处理相邻剖面的重叠段——这三处决定了软件能不能接你的实际数据。2.2 环境准备与依赖安装面波处理绕不开数值计算和绘图依赖基本集中在科学计算栈。建议用虚拟环境隔离避免和系统里的旧版 numpy 打架python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install -r requirements.txtrequirements.txt里通常包含numpy、scipy滤波与信号处理、matplotlib频散图与剖面图、pyyaml读配置如果带 GUI 还会有pyqt5或tkinter相关项。装完先跑一次导入自检确认没有版本冲突import numpy, scipy, matplotlib, yaml print(numpy.__version__, scipy.__version__)版本对不上时最常见的是 scipy 的滤波接口签名变化后面避坑章节会细说。2.3 配置文件与第一次运行config/default.yaml是整条流程的「黑匣子」入口采样率、道间距、偏移距、频散扫描范围都在这里。先按你的采集参数改再运行acquisition: sample_rate: 1000 # 采样率 Hz dt: 0.001 # 采样间隔 s channel_spacing: 2.0 # 道间距 m offset: 5.0 # 最小偏移距 m dispersion: fmin: 2.0 # 扫描最低频率 Hz fmax: 50.0 # 扫描最高频率 Hz velocity_min: 50.0 # 相速度下限 m/s velocity_max: 800.0 # 相速度上限 m/s改完执行入口python main.py --config config/default.yaml --input data/raw/line01.dat程序会依次走读取、预处理、频散提取结果落到output/reports/。第一次跑建议拿包里自带的示例数据确认链路通了再换自己的数据否则读文件和算法问题混在一起排查会很痛苦。3. 核心处理链路拆解读取、预处理与频散提取3.1 地震记录读取与道头解析面波数据的麻烦在于格式杂SEG-2、SAC、纯文本都可能遇到。io_reader.py一般用统一接口封装按扩展名分发import numpy as np def read_segy_like(path): 读取简单二进制/文本记录返回 data(道×样点) 与道头信息 if path.endswith(.txt): data np.loadtxt(path) # 约定第一列为时间其余列为各道振幅 traces data[:, 1:].T dt data[1, 0] - data[0, 0] else: # 二进制格式按项目约定解析此处给出占位结构 raw np.fromfile(path, dtypenp.float32) n_channels 24 traces raw.reshape(n_channels, -1) dt 0.001 return traces, {dt: dt, n_channels: traces.shape[0]}这里的关键是traces的维度约定为「道 × 样点」后续所有算法都按这个方向处理。dt从数据本身或配置读取千万别两处各写一个值——我见过因为道头 dt 和配置 dt 不一致导致频散轴整体偏移的案例图看着正常速度全错。3.2 预处理去直流、带通滤波与道均衡原始记录里常有直流偏置和低频漂移直接做频散会污染低频段。预处理按「去均值 → 带通 → 道均衡」顺序走from scipy.signal import butter, filtfilt def preprocess(traces, dt, fmin2.0, fmax100.0): # 1) 去直流 traces traces - traces.mean(axis1, keepdimsTrue) # 2) 零相位带通避免相位畸变影响频散 nyq 0.5 / dt b, a butter(4, [fmin/nyq, fmax/nyq], btypeband) traces filtfilt(b, a, traces, axis1) # 3) 道均衡按各道最大振幅归一压制强能量道 max_amp np.abs(traces).max(axis1, keepdimsTrue) traces traces / (max_amp 1e-12) return tracesfiltfilt是零相位滤波正反各滤一次相位不偏移这对频散提取很重要butter的阶数 4 是经验值阶数太高容易在截止频率附近振铃。道均衡那一步用1e-12防除零别省。3.3 频散曲线提取f-k 变换与峰值拾取频散提取是这类软件的核心。常见做法是频率—波数f-k变换或相移法这里给 f-k 的简化实现def fk_dispersion(traces, dt, dx): n_ch, n_samp traces.shape # 二维 FFT时间轴 - 频率空间轴 - 波数 fk np.fft.fftshift(np.fft.fft2(traces), axes1) freqs np.fft.fftfreq(n_samp, ddt) k np.fft.fftshift(np.fft.fftfreq(n_ch, ddx)) # 相速度 频率 / 波数逐频取能量峰值对应的速度 amp np.abs(fk) curve [] for i, f in enumerate(freqs[:n_samp//2]): if f 0: continue idx np.argmax(amp[i, :]) k_peak k[idx] if abs(k_peak) 1e-9: curve.append((f, f / abs(k_peak))) return np.array(curve)fft2同时变换时间和空间fftshift把零波数移到中间便于取峰。逐频取argmax是最朴素的峰值拾取实际数据里会有多模态工程上一般加能量阈值和连续性约束避免跳到高阶模态。dx是道间距单位要和速度单位一致米和秒配米每秒别混。4. 剖面连接模块相邻测线的坐标对齐与拼接4.1 剖面连接要解决什么问题单条测线处理完只是半成品工程上往往要把多条相邻剖面接成一张连续图。难点不在画图在「对齐」两条测线的起止桩号、道间距、高程基准可能都不一致直接首尾相接会出现错位或重叠段重复计算。profile_join.py的职责就是把这些差异抹平。4.2 坐标系统一与重叠段处理常见做法是先统一到同一桩号坐标系再按重叠区间做加权融合def join_profiles(profiles, overlap_tol0.5): profiles: [(station_array, value_array), ...] 按桩号排序 profiles sorted(profiles, keylambda p: p[0][0]) merged_s, merged_v [], [] for s, v in profiles: if not merged_s: merged_s, merged_v list(s), list(v) continue last_s merged_s[-1] # 找重叠段新剖面起点落在已有剖面范围内 mask s last_s overlap_tol if mask.any(): # 重叠段取均值避免接缝处突变 for si, vi in zip(s[mask], v[mask]): idx min(range(len(merged_s)), keylambda j: abs(merged_s[j]-si)) merged_v[idx] 0.5 * (merged_v[idx] vi) s, v s[~mask], v[~mask] merged_s.extend(s) merged_v.extend(v) return np.array(merged_s), np.array(merged_v)overlap_tol是重叠判定容差单位与桩号一致设太小接缝处会留缝设太大正常相邻段会被误判为重叠。重叠段取均值是最简单的融合策略要求高的话可以按距离加权。这段逻辑看着短但桩号排序、重叠判定、索引对齐三处都容易出错建议先用两条构造数据验证再接真实测线。4.3 拼接结果的校验与出图拼完不能只看图顺眼要落数值校验检查桩号是否单调递增、接缝处相邻点差值是否超过阈值、总长度是否等于各段去重后的并集长度。校验通过再出图import matplotlib.pyplot as plt def plot_profile(station, value, out_path): plt.figure(figsize(10, 4)) plt.plot(station, value, -o, markersize3) plt.xlabel(Station (m)) plt.ylabel(Phase velocity (m/s)) plt.grid(True, alpha0.3) plt.tight_layout() plt.savefig(out_path, dpi150)出图只是最后一步真正决定质量的是前面的对齐和融合。我一般会把接缝位置在图上用竖线标出来方便肉眼复核。5. 避坑与常见问题排查5.1 频散图整体偏移或速度量级不对现象频散曲线形状合理但相速度整体偏大或偏小一个固定倍数。原因多半是道间距dx或采样间隔dt单位不一致比如配置里写米、数据里按厘米存。解决在读入后打印dt和dx实际值与配置逐项比对统一到 SI 单位再跑。5.2 滤波后波形出现振铃或相位畸变现象带通滤波后波形两端出现振荡频散低频段出现虚假能量。原因是用了一阶lfilter或阶数过高前者有相位延迟后者在截止频率附近振铃。解决改用filtfilt零相位滤波阶数控制在 24截止频率留出过渡带。5.3 剖面拼接处出现台阶或重复段现象两条测线接缝处数值突变或某段桩号重复出现。原因桩号未排序、重叠容差设置不当、索引对齐用了最近邻但桩号间隔不均。解决拼接前强制按桩号排序打印重叠区间长度人工确认索引对齐改为插值而非最近邻。5.4 读取二进制格式时报维度错误现象reshape报错或读出的道数明显不对。原因文件头里的道数、样点数与实际数据长度不匹配或字节序大端/小端不对。解决先用np.fromfile读原始字节按文件头字段逐项解析确认dtype的字节序再 reshape。5.5 配置文件改了但程序没生效现象修改default.yaml后结果不变。原因入口脚本里配置路径写死或代码里对某些参数有硬编码默认值覆盖了配置。解决在参数加载处打印最终生效的配置字典确认每一项来源硬编码项统一收敛到配置读取函数。6. 二次开发把处理链路改成自己的批处理工具这套代码最值得改的地方是把「单文件手动跑」变成「整条测线批处理」。我的做法是在main.py外面包一层调度脚本遍历目录下所有原始文件按配置批量跑结果统一命名落盘import os, glob from core.io_reader import read_segy_like from core.preprocess import preprocess from core.dispersion import fk_dispersion from core.profile_join import join_profiles def batch_process(raw_dir, out_dir, cfg): results [] for path in sorted(glob.glob(os.path.join(raw_dir, *.dat))): traces, meta read_segy_like(path) traces preprocess(traces, meta[dt], cfg[fmin], cfg[fmax]) curve fk_dispersion(traces, meta[dt], cfg[dx]) name os.path.splitext(os.path.basename(path))[0] np.savetxt(os.path.join(out_dir, f{name}_disp.txt), curve) results.append((meta[station], curve[:, 1])) return results改造时有三个点值得注意。第一meta里要带上桩号信息否则后面拼接无从对齐第二批处理要加异常捕获和日志单条失败不能中断整批第三输出格式固定成「频率—相速度」两列文本方便后续用其他工具复核。验证方法很简单拿两条已知重叠的测线跑一遍检查拼接后重叠段数值是否落在两条原始曲线之间桩号是否连续。我踩过最深的一个坑是批处理时没统一dt不同文件道头精度不同拼出来的剖面在接缝处速度跳变查了两天才定位到读取环节。从那以后我每次批处理前都强制打印每个文件的dt、dx、道数三件套确认一致再往下走。希望帮到你。本文还有配套的精品资源点击获取