gprMax 3.0仿真结果可视化全攻略:在PyCharm里用Matplotlib绘制A扫、B扫及堆叠波形图
gprMax 3.0仿真结果可视化全攻略在PyCharm里用Matplotlib绘制A扫、B扫及堆叠波形图当你完成gprMax的电磁仿真后面对一堆.out格式的二进制数据文件是否曾感到无从下手这些数据蕴含着丰富的电磁波传播信息但只有通过专业的可视化处理才能转化为直观的雷达图像。本文将带你深入探索如何利用PyCharm和Matplotlib将冰冷的仿真数据转化为具有科研价值的波形图。1. 理解gprMax输出数据的基本结构在开始绘图之前我们需要先理解gprMax生成的输出数据格式。gprMax 3.0默认会生成.out格式的二进制文件其中包含了接收天线记录的电磁场分量随时间变化的完整数据。典型的输出数据结构包含以下关键信息时间步长(dt)决定了时间轴的分辨率接收天线编号(rxnumber)多天线仿真时区分不同天线场分量(rxcomponent)通常为Ez(垂直电场)或Ex(水平电场)实际采样数据(outputdata)二维数组包含各时间点的场值# 典型的数据读取代码示例 from tools.outputfiles_merge import get_output_data filename simulation.out rxnumber 1 rxcomponent Ez outputdata, dt get_output_data(filename, rxnumber, rxcomponent)提示使用get_output_data函数时确保文件路径正确否则会抛出FileNotFoundError。2. A-Scan波形图的绘制与优化A-Scan(振幅-时间图)是最基础的雷达数据显示形式它展示了单道接收信号随时间变化的波形。gprMax内置了plot_Ascan模块但我们完全可以自定义更专业的可视化效果。2.1 基础A-Scan绘制import matplotlib.pyplot as plt import numpy as np # 创建时间轴 time_axis np.arange(0, outputdata.shape[0]*dt, dt) * 1e9 # 转换为纳秒 plt.figure(figsize(10, 6)) plt.plot(time_axis, outputdata[:, 0], b-, linewidth1.5) plt.xlabel(Time (ns), fontsize12) plt.ylabel(Amplitude (V/m), fontsize12) plt.title(A-Scan Waveform, fontsize14) plt.grid(True, linestyle--, alpha0.6) plt.show()2.2 高级定制技巧为了使A-Scan图更具可读性和发表质量我们可以进行多项优化坐标轴优化添加次要刻度线设置科学计数法显示调整标签字体和大小波形增强标记首达波和反射波添加峰值标注使用填充效果突出正负半周plt.figure(figsize(12, 6)) ax plt.subplot(111) # 绘制填充波形 ax.fill_between(time_axis, 0, outputdata[:, 0], whereoutputdata[:, 0]0, facecolorred, interpolateTrue, alpha0.7) ax.fill_between(time_axis, 0, outputdata[:, 0], whereoutputdata[:, 0]0, facecolorblue, interpolateTrue, alpha0.7) # 标记典型波形特征 max_idx np.argmax(outputdata[:, 0]) ax.annotate(Direct Wave, xy(time_axis[max_idx], outputdata[max_idx, 0]), xytext(50, 30), textcoordsoffset points, arrowpropsdict(arrowstyle-)) # 设置双坐标轴 ax.set_xlabel(Time (ns), fontsize12) ax.set_ylabel(Amplitude (V/m), fontsize12) ax.secondary_yaxis(right).set_ylabel(Normalized Amplitude) ax.grid(True, linestyle:, alpha0.5) plt.tight_layout()3. B-Scan剖面图的专业呈现B-Scan(距离-时间图)是探地雷达最常用的显示方式它将多个A-Scan按测线位置排列形成二维剖面图像。3.1 基础B-Scan绘制gprMax提供了plot_Bscan模块但默认设置可能不符合发表要求。以下是自定义B-Scan的实现方法plt.figure(figsize(12, 8)) plt.imshow(outputdata.T, aspectauto, cmapseismic, extent[0, outputdata.shape[1], outputdata.shape[0]*dt*1e9, 0]) plt.colorbar(labelAmplitude (V/m)) plt.xlabel(Trace Number, fontsize12) plt.ylabel(Time (ns), fontsize12) plt.title(B-Scan Radar Profile, fontsize14) plt.show()3.2 高级B-Scan处理技术数据预处理背景去除(减去平均道)增益补偿(时变增益函数)带通滤波显示优化自定义颜色映射动态范围调整添加地形线from scipy import signal # 背景去除 mean_trace np.mean(outputdata, axis1) processed_data outputdata - mean_trace[:, np.newaxis] # 时变增益 gain np.linspace(1, 5, processed_data.shape[0]) processed_data processed_data * gain[:, np.newaxis] # 创建自定义颜色映射 from matplotlib.colors import LinearSegmentedColormap colors [(0, 0, 0.5), (0, 0, 1), (1, 1, 1), (1, 0, 0), (0.5, 0, 0)] cmap LinearSegmentedColormap.from_list(custom, colors, N256) # 绘制处理后的B-Scan plt.figure(figsize(14, 6)) plt.imshow(processed_data, aspectauto, cmapcmap, vmin-0.5, vmax0.5, extent[0, processed_data.shape[1], processed_data.shape[0]*dt*1e9, 0]) plt.colorbar(labelProcessed Amplitude) plt.xlabel(Trace Position (m), fontsize12) plt.ylabel(Two-way Travel Time (ns), fontsize12) plt.title(Processed B-Scan with Gain Compensation, fontsize14) plt.tight_layout()4. 堆叠波形图的创意实现堆叠波形(Wiggle Plot)结合了A-Scan和B-Scan的特点既能显示波形细节又能反映剖面变化是地震和雷达解释中常用的显示方式。4.1 基础堆叠波形plt.figure(figsize(12, 8)) space_signal np.max(np.abs(outputdata)) * 2.5 # 自动确定道间距 for i in range(outputdata.shape[1]): plt.plot(outputdata[:, i]/np.max(np.abs(outputdata[:, i])) * space_signal i * space_signal, np.arange(outputdata.shape[0]) * dt * 1e9, k-, linewidth0.5) plt.fill_betweenx(np.arange(outputdata.shape[0]) * dt * 1e9, i * space_signal, outputdata[:, i]/np.max(np.abs(outputdata[:, i])) * space_signal i * space_signal, whereoutputdata[:, i] 0, colork, alpha0.5) plt.xlim(-space_signal, outputdata.shape[1] * space_signal) plt.ylim(outputdata.shape[0] * dt * 1e9, 0) plt.xlabel(Trace Number, fontsize12) plt.ylabel(Time (ns), fontsize12) plt.title(Wiggle Display of Radar Traces, fontsize14) plt.grid(True, axisy, linestyle--, alpha0.5) plt.show()4.2 高级堆叠波形技巧可变道间距根据信号强度动态调整颜色编码用颜色表示振幅大小叠加B-Scan在波形下方显示灰度或彩色剖面# 创建带颜色编码的堆叠波形 plt.figure(figsize(14, 8)) ax plt.subplot(111) # 计算归一化数据 norm_data outputdata / np.max(np.abs(outputdata)) # 绘制每道波形 for i in range(norm_data.shape[1]): x norm_data[:, i] * space_signal i * space_signal y np.arange(norm_data.shape[0]) * dt * 1e9 # 根据振幅值设置线段颜色 points np.array([x, y]).T.reshape(-1, 1, 2) segments np.concatenate([points[:-1], points[1:]], axis1) from matplotlib.collections import LineCollection lc LineCollection(segments, cmapseismic, normplt.Normalize(-1, 1)) lc.set_array(norm_data[:, i]) lc.set_linewidth(1.5) line ax.add_collection(lc) # 填充正半周 ax.fill_betweenx(y, i * space_signal, x, wherex i * space_signal, colorred, alpha0.3) # 添加颜色条 plt.colorbar(line, axax, labelNormalized Amplitude) # 设置坐标轴 ax.set_xlim(-space_signal, norm_data.shape[1] * space_signal) ax.set_ylim(norm_data.shape[0] * dt * 1e9, 0) ax.set_xlabel(Trace Number, fontsize12) ax.set_ylabel(Time (ns), fontsize12) ax.set_title(Color-coded Wiggle Plot with Amplitude Fill, fontsize14) ax.grid(True, axisy, linestyle:, alpha0.5) plt.tight_layout()5. 出版级图表导出与批量处理完成可视化设计后我们需要将图表导出为适合发表的格式并考虑批量处理多个数据文件的场景。5.1 高质量图表导出设置# 设置导出参数 export_config { dpi: 600, # 分辨率 format: pdf, # 格式(pdf/svg/png/jpeg) bbox_inches: tight, # 去除白边 transparent: False, # 背景透明 facecolor: white, # 背景颜色 metadata: { Title: Radar Profile, Author: Your Name, Keywords: GPR, Radar, gprMax } } # 导出当前图形 plt.savefig(radar_profile.pdf, **export_config)5.2 批量处理与自动化对于需要处理大量仿真结果的场景我们可以创建自动化脚本import os from pathlib import Path def process_gprmax_output(output_folder, save_folder): 批量处理gprMax输出文件并保存可视化结果 Path(save_folder).mkdir(exist_okTrue) for file in Path(output_folder).glob(*.out): # 读取数据 outputdata, dt get_output_data(str(file), 1, Ez) # 创建三种可视化 fig, (ax1, ax2, ax3) plt.subplots(3, 1, figsize(12, 18)) # A-Scan ax1.plot(np.arange(outputdata.shape[0]) * dt * 1e9, outputdata[:, 0], b-) ax1.set_title(fA-Scan for {file.stem}) # B-Scan ax2.imshow(outputdata.T, aspectauto, cmapseismic, extent[0, outputdata.shape[1], outputdata.shape[0]*dt*1e9, 0]) ax2.set_title(fB-Scan for {file.stem}) # Wiggle Plot for i in range(outputdata.shape[1]): ax3.plot(outputdata[:, i] i * 0.1, np.arange(outputdata.shape[0]) * dt * 1e9, k-, linewidth0.5) ax3.set_title(fWiggle Plot for {file.stem}) # 保存结果 plt.tight_layout() plt.savefig(Path(save_folder) / f{file.stem}_plots.pdf) plt.close() # 使用示例 process_gprmax_output(simulation_results, visualization_outputs)注意批量处理时建议使用try-except捕获可能的异常避免因单个文件问题中断整个处理流程。