分析地震目录#

  • 本节贡献者: 田冬冬姚家园

  • 最近更新日期: 2022-07-31

  • 预计花费时间: 15 分钟


在获取地震目录之后,通常还需要对地震目录做一些简单的绘图和分析。这一节演示如何 绘制最简单的地震深度直方图、地震震级直方图以及震级-频次关系图。

首先,需要把地震目录准备好。这里我们选择下载 2000–2010 年间震级大于 4.8 级, 震源深度大于 50 km 的地震。这一地震目录中共计约 7000 个地震:

from obspy.clients.fdsn import Client

client = Client("USGS")
cat = client.get_events(
    starttime="2000-01-01",
    endtime="2010-01-01",
    minmagnitude=4.8,
    mindepth=50,
)
print(cat)
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[1], line 1
----> 1 from obspy.clients.fdsn import Client
      3 client = Client("USGS")
      4 cat = client.get_events(
      5     starttime="2000-01-01",
      6     endtime="2010-01-01",
      7     minmagnitude=4.8,
      8     mindepth=50,
      9 )

File ~/micromamba/envs/seismo-learn/lib/python3.13/site-packages/obspy/__init__.py:44
     41     msg = ('pkg_resources is deprecated as an API')
     42     warnings.filterwarnings(
     43         'ignore', message=msg, category=DeprecationWarning, module='obspy')
---> 44     from obspy.core.utcdatetime import UTCDateTime  # NOQA
     45 from obspy.core.util import _get_version_string
     46 __version__ = _get_version_string(abbrev=10)

File ~/micromamba/envs/seismo-learn/lib/python3.13/site-packages/obspy/core/__init__.py:120
     12 """
     13 obspy.core - Core classes of ObsPy
     14 ==================================
   (...)    117 .. _NumPy: http://www.numpy.org
    118 """
    119 # don't change order
--> 120 from obspy.core.utcdatetime import UTCDateTime  # NOQA
    121 from obspy.core.util.attribdict import AttribDict  # NOQA
    122 from obspy.core.trace import Stats, Trace  # NOQA

File ~/micromamba/envs/seismo-learn/lib/python3.13/site-packages/obspy/core/utcdatetime.py:21
     18 import warnings
     20 import numpy as np
---> 21 from obspy.core.util.deprecation_helpers import ObsPyDeprecationWarning
     24 # based on https://www.myintervals.com/blog/2009/05/20/iso-8601, w/ week 53 fix
     25 _ISO8601_REGEX = re.compile(r"""
     26     ^
     27     ([\+-]?\d{4}(?!\d{2}\b))
   (...)     40     $
     41     """, re.VERBOSE)

File ~/micromamba/envs/seismo-learn/lib/python3.13/site-packages/obspy/core/util/__init__.py:22
     20 # import order matters - NamedTemporaryFile must be one of the first!
     21 from obspy.core.util.attribdict import AttribDict
---> 22 from obspy.core.util.base import (ALL_MODULES, DEFAULT_MODULES,
     23                                   NATIVE_BYTEORDER, NETWORK_MODULES,
     24                                   NamedTemporaryFile, _read_from_plugin,
     25                                   create_empty_data_chunk, get_example_file,
     26                                   get_script_dir_name, MATPLOTLIB_VERSION,
     27                                   SCIPY_VERSION, NUMPY_VERSION,
     28                                   CARTOPY_VERSION, CatchAndAssertWarnings)
     29 from obspy.core.util.misc import (BAND_CODE, CatchOutput, complexify_string,
     30                                   guess_delta, score_at_percentile,
     31                                   to_int_or_zero, SuppressOutput)
     32 from obspy.core.util.obspy_types import (ComplexWithUncertainties, Enum,
     33                                          FloatWithUncertainties)

File ~/micromamba/envs/seismo-learn/lib/python3.13/site-packages/obspy/core/util/base.py:26
     23 from pathlib import PurePath
     25 import numpy as np
---> 26 import pkg_resources
     27 from pkg_resources import get_entry_info, iter_entry_points
     29 from obspy.core.util.misc import to_int_or_zero, buffered_load_entry_point

ModuleNotFoundError: No module named 'pkg_resources'

为了进一步对数据做处理以及绘图,我们还需要导入 NumPyMatplotlib 模块:

import matplotlib.pyplot as plt
import numpy as np

地震深度分布直方图#

为了绘制地震深度直方图,我们先从地震目录中提取出地震深度信息,并保存到数组 depth 中。 需要注意的是,ObsPy 的地震目录中地震深度的单位为 m,所以需要除以 1000.0 将深度单位 转换为 km。

depth = np.array([event.origins[0].depth / 1000 for event in cat])

我们可以使用 Matplotlib 的 hist() 函数绘制直方图: 这里我们设置的直方的最小值为 50,最大值 700,间隔为 10,同时设置了 Y 轴以对数方式显示。 从图中可以明显看到地震深度随着深度的变化:

fig, ax = plt.subplots()
ax.hist(depth, bins=np.arange(50, 700, 10), log=True)
ax.set_xlabel("Depth (km)")
ax.set_ylabel("Number of earthquakes")
plt.show()

地震震级直方图#

同理,从地震目录中提取出地震震级信息,保存到数组 mag 中并绘图。从图中可以明显看到, 震级越小地震数目越多:

mag = np.array([event.magnitudes[0].mag for event in cat])

fig, ax = plt.subplots()
ax.hist(mag, bins=np.arange(4.5, 8, 0.1))
ax.set_xlabel("Magnitude")
ax.set_ylabel("Number of earthquakes")
plt.show()

地震震级-频度关系#

地震震级-频度关系应符合 Gutenberg–Richter 定律。为了绘制地震震级-频度关系, 首先需要计算得到 GR 定律里的 \(N\),即大于等于某个特定震级 \(M\) 的地震数目。 这里,我们选择 \(M\) 的取值范围为 4.0 到 8.0,间隔为 0.1。计算 \(N\) 的方法有很多,下面的 方法使用了 Python 的列表表达式以及 numpy.sum() 函数来实现:

mw = np.arange(4.0, 8.0, 0.1)
counts = np.array([(mag >= m).sum() for m in mw])

绘图脚本如下,注意图中 Y 轴是对数坐标。从图中可以明显看到 \(\log_{10}N\)\(M\) 在 4.8 - 7.6 级 之间存在线性关系。由于我们使用的地震目录里只有 4.8 级以上的地震,所以在 4.7 级以下偏离了线性关系,而大地震由于数目太少也偏离了线性关系。

fig, ax = plt.subplots()
ax.semilogy(mw, counts, "o")
ax.set_xlabel("Magnitude")
ax.set_ylabel("Cumulative Number of earthquakes")
plt.show()

更进一步,我们可以对 4.8-7.6 级之间的数据进行线性拟合,得到 GR 定律中的系数 \(a\)\(b\)。 这里我们采用 numpy.logical_and 函数找到数组 mw 中所有满足条件的元素的索引, 并使用 NumPy 的布尔索引功能筛选出满足条件的震级 mw[idx] 和对应的 counts[idx],再 使用 numpy.polyfit() 函数拟合一元一次多项式,最后绘图:

idx = np.logical_and(mw >= 4.8, mw <= 7.5)
# fitting y = p[0] * x + p[1]
p = np.polyfit(mw[idx], np.log10(counts[idx]), 1)
N_pred = 10 ** (mw * p[0] + p[1])

fig, ax = plt.subplots()
ax.semilogy(mw, counts, "o")
ax.semilogy(mw, N_pred, color="red", label=rf"$\log_{{10}} N={p[1]:.2f}{p[0]:.2f}M$")
ax.legend()
ax.set_xlabel("Magnitude")
ax.set_ylabel("Cumulative Number of earthquakes")
plt.show()