Use PhaseNet arrival picks (optional)
The base spatial-vtk package does not require PhaseNet. PhaseNet is not included in the package prerequisites or installed with spatial-vtk because it requires a separate machine-learning environment and substantial dependencies. You can calculate metrics, run waveform quality control (QC), and follow the tutorials without installing it.
Use PhaseNet if you want to identify P- and S-wave arrivals automatically. You can run it through spatial-vtk or import picks from a separate PhaseNet run. If you already have picks, skip to Use existing PhaseNet outputs.
Install PhaseNet
The spatial-vtk integration uses the TensorFlow implementation from
AI4EPS/PhaseNet. Install it in a separate
Conda environment so its dependencies do not affect your spatial-vtk environment.
The package named phasenet on PyPI uses a different interface; installing it
with pip install phasenet does not set up this integration.
Install Miniconda and Git if they are not already available.
In a terminal, download PhaseNet and open its directory:
git clone https://github.com/AI4EPS/PhaseNet.git cd PhaseNet
Create and activate the PhaseNet environment:
conda env create -f env.yaml conda activate phasenet
On a Mac with Apple silicon, use
env_mac.yamlinstead ofenv.yaml. See the PhaseNet installation instructions for platform-specific requirements.Check that the prediction command starts, then display the paths you will need in spatial-vtk:
python phasenet/predict.py --help python -c "import sys; from pathlib import Path; print(sys.executable); print(Path('phasenet/predict.py').resolve()); print(Path('model/190703-214543').resolve())"
The three paths identify the Python interpreter, prediction script, and bundled pretrained model. If the help command fails, resolve the PhaseNet installation problem before continuing.
Connect PhaseNet to spatial-vtk
Return to your spatial-vtk environment. Install waveform support there if you have not already done so:
python -m pip install "spatial-vtk[waveforms]"
In your Python script or notebook, set the three absolute paths from the installation step. Replace the example paths with your own:
import shlex phasenet_python = "/absolute/path/to/phasenet-env/bin/python" phasenet_script = "/absolute/path/to/PhaseNet/phasenet/predict.py" model_dir = "/absolute/path/to/PhaseNet/model/190703-214543" phasenet_command = shlex.join([phasenet_python, phasenet_script])
spatial-vtk runs this command in the separate PhaseNet environment. You do not need to install TensorFlow in your spatial-vtk environment.
Prepare one waveform group per event, station, and waveform source. Use broadband east, north, and vertical (E/N/Z) traces at 100 Hz with matching start times and lengths. Align and resample your traces before this step. Run picking before rotating to R/T/Z or applying the metric passbands or the 1 Hz spectral lowpass.
The example below uses a three-component MiniSEED file. Replace its path, identifiers, and event origin with those for your data:
from obspy import read stream = read("data/event_001_station_ABC.mseed") groups = [{ "event_id": "event_001", "station": "ABC", "waveform_source": "observed", "relative_time_origin": "2026-01-01T00:00:00Z", "components": { component: stream.select(component=component)[0] for component in ("E", "N", "Z") }, }]
Use event and station identifiers that match your event-station records. Set
waveform_sourcetoobservedorsyntheticas appropriate. Always supply the event origin: QC uses pick times measured in seconds since that origin, which may differ from the waveform start time.Run PhaseNet and save the arrival catalog:
from spatial_vtk.metrics.calculate import build_phasenet_arrival_pick_catalog catalog_path = build_phasenet_arrival_pick_catalog( groups, phasenet_command=phasenet_command, model_dir=model_dir, work_dir="outputs/phasenet", output_catalog="outputs/arrival_picks.csv", min_p_prob=0.5, min_s_prob=0.5, )
The function prepares the input files, runs PhaseNet, and keeps the highest-probability pick for each phase and waveform group. The probability thresholds shown here are examples; choose them for your dataset and review the resulting picks. Use
overwrite=Truewhen deliberately replacing an existing catalog and its prepared inputs.
Use the picks in waveform QC
Arrival picking is a preparation step before waveform QC. Pass the saved catalog to your existing QC call:
from spatial_vtk.qc.build.workflow import build_waveform_qc_summary
qc = build_waveform_qc_summary(
event_station_records,
arrival_pick_catalog=catalog_path,
onset_phase="P",
min_onset_pick_probability=0.5,
)
Here, event_station_records is the same table or file you already use for
waveform QC. Retain any source, component, preprocessing, and passband settings
from your existing call.
QC uses an accepted P pick to position its noise and signal windows. If a pick
is missing or fails the QC plausibility check, QC uses its waveform-envelope
onset estimate. You can select S picks with onset_phase="S". The catalog
contains station-level picks (component="ALL"), which can be used across
the station’s components.
Continue with your usual QC review and metric workflow. PhaseNet does not run automatically when you calculate PGA, PGV, PGD, PSA, or FAS, and supplying picks does not change their filtering settings. See the Quality Control API and Metrics API for the function parameters.
Use existing PhaseNet outputs
You do not need to install or run PhaseNet in your spatial-vtk environment to use picks generated elsewhere. Convert the output once, then pass the resulting catalog to QC as shown above.
Convert a PhaseNet CSV
Keep the PhaseNet CSV and a record of the event, station, waveform source, waveform start, sampling rate, and event origin for each input file. The CSV must contain
file_name,phase_type,phase_score, and eitherphase_time(an absolute timestamp) orphase_index(a sample index). Use one pick per row.Create a metadata record for each input file. Match
file_nameexactly to its value in the PhaseNet CSV. This example describes one file; add a record for every file in your dataset:from spatial_vtk.metrics.calculate.phasenet_adapter import ( PhaseNetInputRecord, normalize_phasenet_output, ) from spatial_vtk.metrics.calculate import write_arrival_pick_catalog records = [PhaseNetInputRecord( file_name="event_001_station_ABC.mseed", event_id="event_001", station="ABC", waveform_source="observed", components=("E", "N", "Z"), sampling_rate=100.0, time_anchor="2025-12-31T23:59:50Z", relative_time_origin="2026-01-01T00:00:00Z", )]
Convert and save the picks:
picks = normalize_phasenet_output( "results/picks.csv", records, min_p_prob=0.5, min_s_prob=0.5, ) catalog_path = write_arrival_pick_catalog( picks, "outputs/arrival_picks.csv" )
The converter calculates seconds since the event origin and retains the highest-probability pick per phase and input file. For sample-index outputs, it uses the sampling rate and waveform start time. For example, sample 1500 at 100 Hz is 15 seconds after the waveform starts; if the waveform starts 10 seconds before the event, the catalog pick time is 5 seconds.
Pass
catalog_pathtobuild_waveform_qc_summaryusing the example in Use the picks in waveform QC. This conversion and QC path does not call PhaseNet.
Load a catalog you have already converted
If your workflow already produces a spatial-vtk arrival catalog, load its CSV or Parquet file directly:
from spatial_vtk.metrics.calculate import load_arrival_pick_catalog
picks = load_arrival_pick_catalog("outputs/arrival_picks.csv")
Pass picks as arrival_pick_catalog in your QC call. Use these columns
when converting another output format yourself:
Column |
Value |
|---|---|
|
Identifiers matching your event-station records. |
|
|
|
|
|
Absolute pick timestamp, preferably in UTC. |
|
Numeric seconds since the event origin; required for QC to use the pick. |
|
Numeric pick confidence used by the probability filter. |
|
|
|
|
Loading a catalog does not convert raw PhaseNet columns or calculate relative pick times. Use the converter above for those steps.