Source code for specmod.picks.snuffler
"""Snuffler (Pyrocko) marker files."""
from __future__ import annotations
from dataclasses import dataclass
from typing import TYPE_CHECKING
import obspy
from .base import Pick, PickSet, SensorID
if TYPE_CHECKING: # pragma: no cover
from os import PathLike
__all__ = ["SnufflerReader"]
#: First line of every marker file Snuffler writes.
MAGIC = "# Snuffler Markers File Version"
#: Marker symbol to ``(phase, branch, first motion)``.
PHASES = {
"^": ("P", "Pg", "u"),
"v": ("P", "Pg", "d"),
"P": ("P", "Pg", None),
"S": ("S", "Sg", None),
}
#: Weights above this are how the format spells a rejected arrival.
MAX_WEIGHT = 3
[docs]
@dataclass(frozen=True)
class SnufflerReader:
"""Marker files, as saved from Snuffler.
Not an ObsPy format: markers are an editor's working notes rather than an
event, and carry no origin.
"""
@property
def name(self) -> str:
return "snuffler"
@property
def suffixes(self) -> tuple[str, ...]:
return (".picks", ".markers")
def can_read(self, source: str | PathLike[str]) -> bool:
try:
with open(source) as handle:
return handle.readline().startswith(MAGIC)
except (OSError, UnicodeDecodeError):
return False
def read(self, source: str | PathLike[str]) -> list[PickSet]:
with open(source) as handle:
lines = handle.readlines()[1:]
picks = []
for line in lines:
fields = line.split()
if not fields or fields[0] != "phase:":
# Snuffler also writes plain time markers, which name no phase.
continue
identity = fields[4].replace("..", ".--.").split(".")
phase, branch, motion = PHASES[fields[8]]
weight = int(fields[3])
if weight > MAX_WEIGHT:
continue
picks.append(
Pick(
sensor=SensorID.parse(
".".join(
(
identity[0],
identity[1],
identity[2] if len(identity) > 2 else "--",
)
)
),
phase=phase,
time=obspy.UTCDateTime("T".join(fields[1:3])),
raw_phase=branch,
polarity=motion,
weight=float(weight),
channel=identity[3] if len(identity) > 3 else None,
# A marker file is what an analyst saved out of Snuffler.
automatic=False,
reviewed=True,
)
)
return [PickSet(picks=tuple(picks))]