Skip to main content

PickerXL is a large deep learning model to measure arrival times from noisy seismic signals.

Project description

PickerXL

A large deep learning model to measure arrival times from noisy seismic signals. The model was developed by Chengping Chai, Derek Rose, Scott Stewart, Nathan Martindale, Mark Adams, Lisa Linville, Christopher Stanley, Anibely Torres Polanco and Philip Bingham.

Introduction

This model is trained on STEAD (Mousavi et al., 2019) for Primary (P) and Secondary (S) wave arrival picking. The model was trained using earthquake data at local distances (0-350 km). The model uses 57 s long three-component seismograms sampled at 100 Hz as input. The required channel order is East, North, and Vertical. The output of the model are probability channels corresponding to P wave, S wave, and noise. These probabilities can be used to compute P- and S-wave arrival times.

Picker.predict_probability() returns a NumPy array with shape (batch, 3, n_samples). If an input trace is longer than 5700 samples, PickerXL segments it internally, applies the model window by window, and stitches the probabilities back to the original sample length.

Picker.predict_arrivals() applies obspy.signal.trigger.trigger_onset() to the P and S probability channels. It returns NaN-padded arrays of trigger picks, where each row corresponds to one input sample and each column corresponds to one detected trigger.

Installation

Creating a virtual environment is highly encouraged.

pip install pickerxl

To run the bundled HDF5 and plotting examples, install the optional example dependencies too:

pip install "pickerxl[examples]"

To install only for CPU (e.g., macOS), you may use the following commands.

pip3 install torch torchvision torchaudio
pip3 install pickerxl

Example Usage

from pickerxl.pickerxl import Picker
import numpy as np
import h5py
model = Picker()
fid = h5py.File("example_waveforms.h5", "r")
data_group = fid["data"]
example_data = []
true_p_index = []
true_s_index = []
for akey in data_group.keys():
    dataset = data_group[akey]
    example_data.append(dataset[...])
    true_p_index.append(float(dataset.attrs["p_arrival_sample"]))
    true_s_index.append(float(dataset.attrs["s_arrival_sample"]))
fid.close()
preds = model.predict_probability(example_data)
p_index, s_index = model.predict_arrivals(example_data)
# `preds` has shape (batch, 3, n_samples).
# Input channels must be ordered as East, North, Vertical.
# `p_index` and `s_index` are NaN-padded arrays of trigger picks.
print("True P-wave arrival index:", true_p_index)
print("Predicted P-wave arrival index:", p_index)
print("True S-wave arrival index:", true_s_index)
print("Predicted S-wave arrival index:", s_index)

To return trigger peak probabilities together with the trigger indices:

p_index, s_index, p_prob, s_prob = model.predict_arrivals(
    example_data,
    return_probabilities=True,
)

MiniSEED Example

The repository includes a MiniSEED example at tests/example_waveform.mseed. The test script preprocesses the stream before applying PickerXL by:

  1. merging traces and interpolating gaps,
  2. removing the mean,
  3. removing the linear trend,
  4. resampling to 100 Hz,
  5. applying a 1-45 Hz bandpass filter.

The waveform passed to PickerXL must be stacked in East, North, Vertical order. In the test script, MiniSEED traces are explicitly sorted by E, N, and Z before stacking.

Example:

from obspy import read
import numpy as np
from pickerxl.pickerxl import Picker

stream = read("tests/example_waveform.mseed")
stream.merge(method=1, fill_value="interpolate")
stream.detrend("demean")
stream.detrend("linear")
stream.resample(100.0)
stream.filter("bandpass", freqmin=1.0, freqmax=45.0, corners=4, zerophase=True)

channel_order = ("E", "N", "Z")
component_map = {}
sorted_traces = sorted(
    stream,
    key=lambda trace: channel_order.index(trace.stats.channel[-1].upper())
    if trace.stats.channel[-1].upper() in channel_order
    else len(channel_order),
)
for trace in sorted_traces:
    component = trace.stats.channel[-1].upper()
    if component in channel_order and component not in component_map:
        component_map[component] = trace

ordered_components = tuple(sorted(component_map, key=channel_order.index))
npts = min(component_map[component].stats.npts for component in ordered_components)
waveform = np.stack(
    [
        component_map[component].data[:npts].astype(np.float32)
        for component in ordered_components
    ]
)
# The stacked waveform is ordered as East, North, Vertical.

model = Picker()
preds = model.predict_probability(waveform)
p_index, s_index = model.predict_arrivals(waveform)
print("MiniSEED prediction shape:", preds.shape)
print("MiniSEED P-wave trigger indices:", p_index[0])
print("MiniSEED S-wave trigger indices:", s_index[0])

Test the Package

First, go to the top directory of the package. Then run:

cd tests
python run_tests.py

example image

The test script also reads tests/example_waveform.mseed, applies the preprocessing steps above, and saves a MiniSEED plot to tests/example_waveform_mseed.jpg.

Known Limitations

  • The model may have a less-than-optimal performance for earthquake data outside of a source-receiver distance range of 10–110 km and a magnitude range of 0–4.5 because of biases in the training data.
  • The model may produce false detections when applied to continuous seismic data.
  • The model may not perform well for earthquake data at larger distances or for non-earthquake sources.

Reference

Chengping Chai, Derek Rose, Scott Stewart, Nathan Martindale, Mark Adams, Lisa Linville, Christopher Stanley, Anibely Torres Polanco, Philip Bingham; PickerXL, A Large Deep Learning Model to Measure Arrival Times from Noisy Seismic Signals. Seismological Research Letters 2025; 96 (4):2394-2404. doi: https://doi.org/10.1785/0220240353

License

GNU GENERAL PUBLIC LICENSE version 3

Credit

The architecture of the deep learning model was adapted from SeisBench (Woollam et al., 2022).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pickerxl-0.2.5.tar.gz (16.4 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pickerxl-0.2.5-py3-none-any.whl (15.8 MB view details)

Uploaded Python 3

File details

Details for the file pickerxl-0.2.5.tar.gz.

File metadata

  • Download URL: pickerxl-0.2.5.tar.gz
  • Upload date:
  • Size: 16.4 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for pickerxl-0.2.5.tar.gz
Algorithm Hash digest
SHA256 b4f7ce97f8464e0ec9de0c05c03db349aadbe6da52a5a1cb1c9b8184e0c1a547
MD5 bb442dab7294f012f206369abd075786
BLAKE2b-256 e75d8cc6bda195f8fec03d927259ad4c18810351bc19cea714c186aced77a96b

See more details on using hashes here.

File details

Details for the file pickerxl-0.2.5-py3-none-any.whl.

File metadata

  • Download URL: pickerxl-0.2.5-py3-none-any.whl
  • Upload date:
  • Size: 15.8 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for pickerxl-0.2.5-py3-none-any.whl
Algorithm Hash digest
SHA256 6a9ee6723d9f2d05baaee55cf2308097df4b7ed10bcf4da92fe535025326836a
MD5 67900107de636cab849b3f3123ea95ee
BLAKE2b-256 b7766457b127d5c3fe2b3624499b9849341cf8f6757edde53e7b5fac187a6401

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page