You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Matplotlib绘制地震图如何设置与Obspy一致的日期时间X轴

问题原因

你当前代码无法实现obspy风格时间轴有两个核心问题:

  • 绘图时传入的X值是从0开始的相对秒数数组,但set_xlim传入的是obspy的UTCDateTime对象,二者数据类型不匹配,会导致轴刻度映射错乱
  • matplotlib默认的DateFormatter会对所有刻度应用统一格式,无法自动为首个刻度单独配置完整日期显示
obspy风格时间轴实现方案

参考效果

  • obspy原生绘制效果:
    obspy绘制效果
  • 你当前matplotlib绘制效果:
    matplotlib绘制效果

实现步骤

  1. 将X轴数据从相对秒数替换为matplotlib可识别的绝对时间序列,保证坐标值和轴范围类型一致
  2. 自定义日期格式器,识别首个主刻度位置,单独为其配置完整日期格式,其余刻度应用分/秒格式
  3. 适配地震图短时长特征,替换不合理的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 23:48:26