Files
SkillCompiler/data/skills-bench/tasks/seismic-phase-picking/oracle/solve.sh
T
2026-09-04 14:58:42 +08:00

202 lines
5.6 KiBLFS
Bash

#!/bin/bash
set -e
pip install --no-cache-dir seisbench==0.10.2
python3 << 'EOF'
import os
from pathlib import Path
from glob import glob
import numpy as np
import obspy
import pandas as pd
import seisbench.models as sbm
from obspy import Stream, Trace, UTCDateTime
def load_npz_inputs(npz_dir: str | Path) -> dict[str, obspy.Stream]:
npz_dir = Path(npz_dir)
npz_files = sorted(glob(str(npz_dir / "*.npz")))
required_fields = ["data", "dt", "start_time", "network", "station", "channels"]
streams = {}
for npz_file in npz_files:
filename = os.path.basename(npz_file)
data = np.load(npz_file, allow_pickle=False)
missing_fields = [field for field in required_fields if field not in data]
if missing_fields:
print(f"Skipping {filename}: missing required fields {missing_fields}")
continue
waveform = data["data"] * 1e10 # (12000, 3)
dt = float(data["dt"])
sampling_rate = 1.0 / dt
network = str(data["network"])
station = str(data["station"])
channels = str(data["channels"])
start_time_str = str(data["start_time"])
if "," in channels:
channel_list = channels.split(",")
else:
channel_list = [f"HH{c}" for c in "ENZ"]
try:
start_time = UTCDateTime(start_time_str)
except Exception:
start_time = UTCDateTime(0)
stream = Stream()
for i, ch in enumerate(channel_list):
if i < waveform.shape[1]:
tr = Trace(data=waveform[:, i].astype(np.float64))
tr.stats.network = network
tr.stats.station = station
tr.stats.channel = ch if len(ch) >= 2 else f"HH{ch}"
tr.stats.sampling_rate = sampling_rate
tr.stats.starttime = start_time
stream.append(tr)
streams[filename] = stream
print(f"Loaded {filename}: {len(stream)} traces")
return streams
def load_denoiser(device: str = None) -> sbm.DeepDenoiser:
denoiser = sbm.DeepDenoiser.from_pretrained("original")
if device:
denoiser.to(device)
else:
denoiser.to_preferred_device()
return denoiser
def load_models(model_names: list[str] = None, device: str = None) -> dict:
if model_names is None:
model_names = ["phasenet", "eqtransformer", "gpd"]
models = {}
for name in model_names:
name_lower = name.lower()
if name_lower == "phasenet":
model = sbm.PhaseNet.from_pretrained("original")
elif name_lower == "eqtransformer":
model = sbm.EQTransformer.from_pretrained("original")
elif name_lower == "gpd":
model = sbm.GPD.from_pretrained("stead")
else:
print(f"Unknown model: {name}, skipping")
continue
if device:
model.to(device)
else:
model.to_preferred_device()
models[name_lower] = model
return models
def run_inference(
streams: dict[str, obspy.Stream],
models: dict,
output_csv: str | Path = None,
denoiser: sbm.DeepDenoiser = None,
) -> dict:
all_results = {}
for model_name, model in models.items():
print(f"\n{'='*60}")
print(f"Running inference with {model_name}")
if denoiser:
print("(with DeepDenoiser preprocessing)")
print(f"{'='*60}")
all_picks = []
for filename, stream in streams.items():
sampling_rate = stream[0].stats.sampling_rate
try:
if denoiser:
input_stream = denoiser.annotate(stream)
else:
input_stream = stream
outputs = model.classify(input_stream)
picks = outputs.picks
start_time = stream[0].stats.starttime
for pick in picks:
pick_idx = int((pick.peak_time - start_time) * sampling_rate)
all_picks.append({
"file_name": filename,
"phase": pick.phase,
"pick_idx": pick_idx,
"probability": pick.peak_value,
})
file_p_picks = [p for p in all_picks if p["file_name"] == filename and p["phase"] == "P"]
file_s_picks = [p for p in all_picks if p["file_name"] == filename and p["phase"] == "S"]
print(f" {filename}: P picks: {len(file_p_picks)}, S picks: {len(file_s_picks)}")
except Exception as e:
print(f" Error processing {filename}: {e}")
continue
all_results[model_name] = all_picks
# one row per pick
if output_csv and all_picks:
picks_df = pd.DataFrame(all_picks)
picks_df.to_csv(output_csv, index=False)
print(f"\nSaved {len(picks_df)} picks to {output_csv}")
return all_results
def main():
npz_inputs_dir = Path("/root/data")
output_csv = Path("/root/results.csv")
print("="*60)
print("SeisBench Phase Picking Inference")
print("="*60)
print("\n1. Loading NPZ input data...")
streams = load_npz_inputs(npz_inputs_dir)
print(f"Loaded {len(streams)} samples")
if not streams:
print("No data loaded. Exiting.")
return None
print("\n2. Loading SeisBench models...")
models = load_models(["phasenet"])
denoiser = load_denoiser()
print("\n3. Running inference...")
results = run_inference(streams, models, output_csv, denoiser=None)
print("\n" + "="*60)
print(f"Results saved to: {output_csv}")
return results
main()
EOF