Matplotlib绘制地震图如何设置与Obspy一致的日期时间X轴
问题原因
你当前代码无法实现obspy风格时间轴有两个核心问题:
- 绘图时传入的X值是从0开始的相对秒数数组,但
set_xlim传入的是obspy的UTCDateTime对象,二者数据类型不匹配,会导致轴刻度映射错乱 - matplotlib默认的
DateFormatter会对所有刻度应用统一格式,无法自动为首个刻度单独配置完整日期显示
obspy风格时间轴实现方案
参考效果
- obspy原生绘制效果:

- 你当前matplotlib绘制效果:

实现步骤
- 将X轴数据从相对秒数替换为matplotlib可识别的绝对时间序列,保证坐标值和轴范围类型一致
- 自定义日期格式器,识别首个主刻度位置,单独为其配置完整日期格式,其余刻度应用分/秒格式
- 适配地震图短时长特征,替换不合理的
HourLocator为秒级刻度定位器
修正后代码
首先确保导入依赖:
import numpy as np import matplotlib.pyplot as plt import matplotlib.dates as mdates
替换你原有绘图逻辑中的对应部分:
trz = st[2].copy() tr=trz.trim(starttime=t0, endtime=(t0+float(dur)), nearest_sample=True) tr.filter("bandpass", freqmin=float(flow), freqmax=float(fhigh), corners=2, zerophase=True) # --- 替换原有相对时间t的生成逻辑,生成绝对时间序列 --- t = np.array( [(tr.stats.starttime + i*tr.stats.delta).datetime for i in range(tr.stats.npts)] ) label=(tr.stats.network + '.' + tr.stats.station + '.' + tr.stats.location + '.' + tr.stats.channel) fig, ax = plt.subplots(1,1,figsize=(18,10), dpi=200) ax.plot(t,tr.data, 'r', label=label) ax.set_title('Évènement du '+str(date)+'T'+str(hr)+' station : '+str(sta) + '_' + tr.stats.channel) ax.xaxis.grid(True, which='major', color='g', linestyle='dotted', linewidth=0.3) ax.yaxis.grid(True, which='major', color='g', linestyle='dotted', linewidth=0.3) ax.legend(loc='upper left', ncol=4) # 修正xlim传入类型为datetime,和t的类型匹配 ax.set_xlim(tr.stats.starttime.datetime, tr.stats.endtime.datetime) # --- 自定义格式器,实现首刻度显示完整日期 --- class SeismoTimeFormatter(mdates.DateFormatter): def __init__(self, full_fmt='%Y-%m-%d %H:%M:%S', tick_fmt='%M:%S', *args, **kwargs): super().__init__(tick_fmt, *args, **kwargs) self.full_fmt = full_fmt self.tick_fmt = tick_fmt def __call__(self, x, pos=0): locs = self.axis.get_majorticklocs() # 判定为第一个主刻度时用完整格式 if len(locs) > 0 and abs(x - locs[0]) < 1e-6: self.strftime = self.full_fmt else: self.strftime = self.tick_fmt return super().__call__(x, pos) # --- 配置刻度定位器,根据数据时长调整间隔 --- # 例:每15秒一个主刻度,可根据你的dur时长自行修改interval值 locator = mdates.SecondLocator(interval=15) # 也可使用自动定位器适配不同时长:locator = mdates.AutoDateLocator(minticks=5, maxticks=12) ax.xaxis.set_major_locator(locator) # 应用格式器:首刻度显示年-月-日 时:分:秒,其余刻度显示分:秒 # 若需要其余刻度仅显示秒,将tick_fmt改为'%S'即可 formatter = SeismoTimeFormatter(full_fmt='%Y-%m-%d %H:%M:%S', tick_fmt='%M:%S') ax.xaxis.set_major_formatter(formatter) # 可选:自动旋转x轴标签避免重叠,和obspy默认样式对齐 fig.autofmt_xdate() plt.show()
可调参数说明
- 若需要后续刻度仅显示秒值,将初始化
SeismoTimeFormatter时的tick_fmt参数改为'%S' - 调整
SecondLocator(interval=?)的interval值可以修改主刻度的时间间隔,适配不同时长的地震波形 - 修改
full_fmt参数可以自定义首个刻度的完整日期显示格式
内容的提问来源于stack exchange,提问作者BenjiBoy
相关产品推荐
相关产品推荐

