Skip to content

pysmo

Pysmo protocol classes and their minimal implementations.

The pysmo base namespace provides protocol classes used as type hints and a minimal reference implementation ("Mini class") for each protocol. The protocols define common seismological data structures such as locations, seismic events, stations, and seismograms.

Each Mini class is a concrete attrs class that implements exactly the attributes required by its protocol. Mini classes are named by prefixing "Mini" to the protocol name (e.g. MiniSeismogram implements the Seismogram protocol).

Classes, functions, and other tools that operate on pysmo types are provided by the pysmo.classes, pysmo.functions, and pysmo.tools subpackages.

Modules:

Name Description
classes

Concrete classes compatible with pysmo types.

functions

Building-block functions for pysmo types.

lib

Internal utilities, validators, defaults, and I/O used by pysmo.

tools

Topic-specific tools that operate on pysmo types.

typing

Constrained type aliases used in pysmo.

Classes:

Name Description
Seismogram

Protocol class to define the Seismogram type.

Station

Protocol class to define the Station type.

Event

Protocol class to define the Event type.

Location

Protocol class to define the Location type.

LocationWithDepth

Protocol class to define the LocationWithDepth type.

Response

Protocol class to define the Response type.

StagedResponse

Protocol class to define a Response with digital decimation stages.

ResponseStage

Protocol class to define one digital (FIR/IIR) decimation stage.

MiniSeismogram

Minimal class for use with the Seismogram type.

MiniStation

Minimal class for use with the Station type.

MiniEvent

Minimal class for use with the Event type.

MiniLocation

Minimal class for use with the Location type.

MiniLocationWithDepth

Minimal class for use with the LocationWithDepth type.

MiniResponse

Minimal implementation of the Response type.

MiniStagedResponse

Minimal implementation of the StagedResponse type.

MiniResponseStage

Minimal implementation of the ResponseStage type.

Seismogram

Bases: Protocol

Protocol class to define the Seismogram type.

Examples:

Usage for a function that takes a Seismogram compatible class instance as argument and returns the begin time in isoformat:

>>> from pysmo import Seismogram
>>> from pysmo.classes import SAC  # SAC is a class that "speaks" Seismogram
>>>
>>> def example_function(seis_in: Seismogram) -> str:
...     return seis_in.begin_time.isoformat()
...
>>> sac = SAC.from_file("example.sac")
>>> seismogram = sac.seismogram
>>> example_function(seismogram)
'2010-02-27T06:44:06.069538+00:00'
>>>

Attributes:

Name Type Description
begin_time Timestamp

Seismogram begin time.

data ndarray

Seismogram data.

delta Timedelta

The sampling interval.

end_time Timestamp

Seismogram end time.

Source code in src/pysmo/_types/seismogram.py
@runtime_checkable
class Seismogram(Protocol):
    """Protocol class to define the `Seismogram` type.

    Examples:
        Usage for a function that takes a Seismogram compatible class instance as
        argument and returns the begin time in isoformat:

        ```python
        >>> from pysmo import Seismogram
        >>> from pysmo.classes import SAC  # SAC is a class that "speaks" Seismogram
        >>>
        >>> def example_function(seis_in: Seismogram) -> str:
        ...     return seis_in.begin_time.isoformat()
        ...
        >>> sac = SAC.from_file("example.sac")
        >>> seismogram = sac.seismogram
        >>> example_function(seismogram)
        '2010-02-27T06:44:06.069538+00:00'
        >>>
        ```
    """

    begin_time: pd.Timestamp
    """Seismogram begin time."""

    data: np.ndarray
    """Seismogram data."""

    delta: pd.Timedelta
    """The sampling interval.

    Should be a positive `pd.Timedelta` instance.
    """

    @property
    def end_time(self) -> pd.Timestamp:
        """Seismogram end time."""
        ...

begin_time instance-attribute

begin_time: Timestamp

Seismogram begin time.

data instance-attribute

data: ndarray

Seismogram data.

delta instance-attribute

delta: Timedelta

The sampling interval.

Should be a positive pd.Timedelta instance.

end_time property

end_time: Timestamp

Seismogram end time.

Station

Bases: Location, Protocol

Protocol class to define the Station type.

Attributes:

Name Type Description
latitude float

Latitude in degrees.

longitude float

Longitude in degrees.

name str

Station name or identifier.

network str

Network name or identifier.

location str

Location ID.

channel str

Channel code.

elevation int | float | None

Station elevation in metres.

Source code in src/pysmo/_types/station.py
@runtime_checkable
class Station(Location, Protocol):
    """Protocol class to define the `Station` type."""

    name: str
    """Station name or identifier.

    A 1-5 character identifier for the station recording the data.
    """

    network: str
    """Network name or identifier.

    A 1-2 character code identifying the network/owner of the data.
    """

    location: str
    """Location ID.

    A two character code used to uniquely identify different data streams
    at a single station.
    """

    channel: str
    """Channel code.

    A three character combination used to identify:

    1. Band and general sample rate.
    2. Instrument type.
    3. Orientation of the sensor.
    """

    elevation: int | float | None
    """Station elevation in metres."""

latitude instance-attribute

latitude: float

Latitude in degrees.

longitude instance-attribute

longitude: float

Longitude in degrees.

name instance-attribute

name: str

Station name or identifier.

A 1-5 character identifier for the station recording the data.

network instance-attribute

network: str

Network name or identifier.

A 1-2 character code identifying the network/owner of the data.

location instance-attribute

location: str

Location ID.

A two character code used to uniquely identify different data streams at a single station.

channel instance-attribute

channel: str

Channel code.

A three character combination used to identify:

  1. Band and general sample rate.
  2. Instrument type.
  3. Orientation of the sensor.

elevation instance-attribute

elevation: int | float | None

Station elevation in metres.

Event

Bases: LocationWithDepth, Protocol

Protocol class to define the Event type.

Attributes:

Name Type Description
latitude float

Latitude in degrees.

longitude float

Longitude in degrees.

depth float

Location depth in metres (positive downward from the surface).

time Timestamp

Event origin time.

Source code in src/pysmo/_types/event.py
@runtime_checkable
class Event(LocationWithDepth, Protocol):
    """Protocol class to define the `Event` type."""

    time: pd.Timestamp
    """Event origin time."""

latitude instance-attribute

latitude: float

Latitude in degrees.

longitude instance-attribute

longitude: float

Longitude in degrees.

depth instance-attribute

depth: float

Location depth in metres (positive downward from the surface).

time instance-attribute

time: Timestamp

Event origin time.

Location

Bases: Protocol

Protocol class to define the Location type.

Attributes:

Name Type Description
latitude float

Latitude in degrees.

longitude float

Longitude in degrees.

Source code in src/pysmo/_types/location.py
@runtime_checkable
class Location(Protocol):
    """Protocol class to define the `Location` type."""

    latitude: float
    """Latitude in degrees."""

    longitude: float
    """Longitude in degrees."""

latitude instance-attribute

latitude: float

Latitude in degrees.

longitude instance-attribute

longitude: float

Longitude in degrees.

LocationWithDepth

Bases: Location, Protocol

Protocol class to define the LocationWithDepth type.

Attributes:

Name Type Description
latitude float

Latitude in degrees.

longitude float

Longitude in degrees.

depth float

Location depth in metres (positive downward from the surface).

Source code in src/pysmo/_types/location_with_depth.py
@runtime_checkable
class LocationWithDepth(Location, Protocol):
    """Protocol class to define the `LocationWithDepth` type."""

    depth: float
    """Location depth in metres (positive downward from the surface)."""

latitude instance-attribute

latitude: float

Latitude in degrees.

longitude instance-attribute

longitude: float

Longitude in degrees.

depth instance-attribute

depth: float

Location depth in metres (positive downward from the surface).

Response

Bases: Protocol

Protocol class to define the Response type.

Represents an analog instrument response (Laplace domain), equivalent to a SAC PZ file: poles/zeros plus the total system sensitivity.

Attributes:

Name Type Description
poles list[complex]

Response poles, in radians/second (SAC PZ / LAPLACE (RADIANS/SECOND) convention).

zeros list[complex]

Response zeros, in radians/second.

overall_sensitivity NonZeroNumber

Scale factor combined with poles/zeros to reconstruct the full,

reference_sensitivity NonZeroNumber | None

Total system sensitivity (counts per physical unit) at the response's

input_units str

Physical units produced by removing this response (e.g. "M/S", "M/S**2").

Source code in src/pysmo/_types/response.py
@runtime_checkable
class Response(Protocol):
    """Protocol class to define the `Response` type.

    Represents an analog instrument response (Laplace domain), equivalent to
    a SAC PZ file: poles/zeros plus the total system sensitivity.
    """

    poles: list[complex]
    """Response poles, in radians/second (SAC PZ / `LAPLACE (RADIANS/SECOND)` convention)."""

    zeros: list[complex]
    """Response zeros, in radians/second."""

    overall_sensitivity: NonZeroNumber
    """Scale factor combined with `poles`/`zeros` to reconstruct the full,
    frequency-dependent transfer function `H(f)`.

    Equivalent to `CONSTANT` in a SAC PZ file (`A0 * sensitivity`, the
    analog stage's normalisation factor times the reference-frequency
    sensitivity), or FDSN StationXML's `NormalizationFactor *
    InstrumentSensitivity`. This is *not* the instrument's plain flat-band
    gain — see [`reference_sensitivity`][pysmo.Response.reference_sensitivity]
    for that — so dividing raw data by `overall_sensitivity` directly
    (rather than combining it with `poles`/`zeros`, or using
    `reference_sensitivity` instead) mis-scales the result by the `A0`
    factor, often several orders of magnitude.

    Negative values are permitted (but not zero): a negative `CONSTANT`/
    `NormalizationFactor` is how a reversed-polarity channel is recorded in
    the wild, not an error.
    """

    reference_sensitivity: NonZeroNumber | None
    """Total system sensitivity (counts per physical unit) at the response's
    own reference/normalisation frequency, with no `A0` normalisation folded
    in.

    Equivalent to SAC PZ's `SENSITIVITY` header value, or FDSN StationXML's
    `InstrumentSensitivity/Value`. This — not `overall_sensitivity`, which
    has `A0` folded in — is the correct divisor for a flat, zero-phase
    approximation of the response (e.g.
    [`remove_response`][pysmo.tools.signal.remove_response]'s
    sensitivity-only path). `None` if unavailable (e.g. a SAC PZ file
    without a `SENSITIVITY` header): callers needing it should raise rather
    than silently substituting `overall_sensitivity`. As with
    `overall_sensitivity`, a negative value indicates reversed polarity
    rather than an error; zero is not permitted.
    """

    input_units: str
    """Physical units produced by removing this response (e.g. `"M/S"`, `"M/S**2"`).

    Informational only: not validated against a fixed set of units, and not
    read by [`remove_response`][pysmo.tools.signal.remove_response] or
    [`integrate`][pysmo.tools.signal.integrate]/
    [`differentiate`][pysmo.tools.signal.differentiate] — callers are
    responsible for interpreting it themselves.
    """

poles instance-attribute

poles: list[complex]

Response poles, in radians/second (SAC PZ / LAPLACE (RADIANS/SECOND) convention).

zeros instance-attribute

zeros: list[complex]

Response zeros, in radians/second.

overall_sensitivity instance-attribute

overall_sensitivity: NonZeroNumber

Scale factor combined with poles/zeros to reconstruct the full, frequency-dependent transfer function H(f).

Equivalent to CONSTANT in a SAC PZ file (A0 * sensitivity, the analog stage's normalisation factor times the reference-frequency sensitivity), or FDSN StationXML's NormalizationFactor * InstrumentSensitivity. This is not the instrument's plain flat-band gain — see reference_sensitivity for that — so dividing raw data by overall_sensitivity directly (rather than combining it with poles/zeros, or using reference_sensitivity instead) mis-scales the result by the A0 factor, often several orders of magnitude.

Negative values are permitted (but not zero): a negative CONSTANT/ NormalizationFactor is how a reversed-polarity channel is recorded in the wild, not an error.

reference_sensitivity instance-attribute

reference_sensitivity: NonZeroNumber | None

Total system sensitivity (counts per physical unit) at the response's own reference/normalisation frequency, with no A0 normalisation folded in.

Equivalent to SAC PZ's SENSITIVITY header value, or FDSN StationXML's InstrumentSensitivity/Value. This — not overall_sensitivity, which has A0 folded in — is the correct divisor for a flat, zero-phase approximation of the response (e.g. remove_response's sensitivity-only path). None if unavailable (e.g. a SAC PZ file without a SENSITIVITY header): callers needing it should raise rather than silently substituting overall_sensitivity. As with overall_sensitivity, a negative value indicates reversed polarity rather than an error; zero is not permitted.

input_units instance-attribute

input_units: str

Physical units produced by removing this response (e.g. "M/S", "M/S**2").

Informational only: not validated against a fixed set of units, and not read by remove_response or integrate/ differentiate — callers are responsible for interpreting it themselves.

StagedResponse

Bases: Response, Protocol

Protocol class to define a Response with digital decimation stages.

Extends Response with the digital FIR/IIR stages of the instrument's full signal chain, in stage (signal) order.

Attributes:

Name Type Description
poles list[complex]

Response poles, in radians/second (SAC PZ / LAPLACE (RADIANS/SECOND) convention).

zeros list[complex]

Response zeros, in radians/second.

overall_sensitivity NonZeroNumber

Scale factor combined with poles/zeros to reconstruct the full,

reference_sensitivity NonZeroNumber | None

Total system sensitivity (counts per physical unit) at the response's

input_units str

Physical units produced by removing this response (e.g. "M/S", "M/S**2").

stages list[ResponseStage]

Digital decimation stages, in signal order (stage 1 = closest to the

Source code in src/pysmo/_types/response.py
@runtime_checkable
class StagedResponse(Response, Protocol):
    """Protocol class to define a `Response` with digital decimation stages.

    Extends `Response` with the digital FIR/IIR stages of the instrument's
    full signal chain, in stage (signal) order.
    """

    stages: list[ResponseStage]
    """Digital decimation stages, in signal order (stage 1 = closest to the
    analog sensor)."""

poles instance-attribute

poles: list[complex]

Response poles, in radians/second (SAC PZ / LAPLACE (RADIANS/SECOND) convention).

zeros instance-attribute

zeros: list[complex]

Response zeros, in radians/second.

overall_sensitivity instance-attribute

overall_sensitivity: NonZeroNumber

Scale factor combined with poles/zeros to reconstruct the full, frequency-dependent transfer function H(f).

Equivalent to CONSTANT in a SAC PZ file (A0 * sensitivity, the analog stage's normalisation factor times the reference-frequency sensitivity), or FDSN StationXML's NormalizationFactor * InstrumentSensitivity. This is not the instrument's plain flat-band gain — see reference_sensitivity for that — so dividing raw data by overall_sensitivity directly (rather than combining it with poles/zeros, or using reference_sensitivity instead) mis-scales the result by the A0 factor, often several orders of magnitude.

Negative values are permitted (but not zero): a negative CONSTANT/ NormalizationFactor is how a reversed-polarity channel is recorded in the wild, not an error.

reference_sensitivity instance-attribute

reference_sensitivity: NonZeroNumber | None

Total system sensitivity (counts per physical unit) at the response's own reference/normalisation frequency, with no A0 normalisation folded in.

Equivalent to SAC PZ's SENSITIVITY header value, or FDSN StationXML's InstrumentSensitivity/Value. This — not overall_sensitivity, which has A0 folded in — is the correct divisor for a flat, zero-phase approximation of the response (e.g. remove_response's sensitivity-only path). None if unavailable (e.g. a SAC PZ file without a SENSITIVITY header): callers needing it should raise rather than silently substituting overall_sensitivity. As with overall_sensitivity, a negative value indicates reversed polarity rather than an error; zero is not permitted.

input_units instance-attribute

input_units: str

Physical units produced by removing this response (e.g. "M/S", "M/S**2").

Informational only: not validated against a fixed set of units, and not read by remove_response or integrate/ differentiate — callers are responsible for interpreting it themselves.

stages instance-attribute

Digital decimation stages, in signal order (stage 1 = closest to the analog sensor).

ResponseStage

Bases: Protocol

Protocol class to define one digital (FIR/IIR) decimation stage.

Attributes:

Name Type Description
input_sample_rate PositiveNumber

Sample rate (Hz) this stage's filter coefficients operate at.

decimation_factor int

Integer decimation factor applied by this stage.

numerator list[float]

Feedforward ("b") filter coefficients.

denominator list[float]

Feedback ("a") filter coefficients. [1.0] for a pure FIR stage.

correction float

Time correction (seconds) already applied to the recorded data to

Source code in src/pysmo/_types/response.py
@runtime_checkable
class ResponseStage(Protocol):
    """Protocol class to define one digital (FIR/IIR) decimation stage."""

    input_sample_rate: PositiveNumber
    """Sample rate (Hz) this stage's filter coefficients operate at."""

    decimation_factor: int
    """Integer decimation factor applied by this stage."""

    numerator: list[float]
    """Feedforward ("b") filter coefficients."""

    denominator: list[float]
    """Feedback ("a") filter coefficients. `[1.0]` for a pure FIR stage."""

    correction: float
    """Time correction (seconds) already applied to the recorded data to
    cancel this stage's own filter delay.

    Equivalent to FDSN StationXML's `Decimation/Correction` (SEED Blockette
    57 field 8). Real digitisers timestamp their output as if this stage
    had zero delay, by shifting the data earlier by this amount; evaluating
    `numerator`/`denominator` alone (e.g. via `scipy.signal.freqz`) instead
    reproduces the filter's own, uncorrected delay. `0.0` (the default,
    correct for a stage with no such correction, e.g. a symmetric FIR
    stage where the coefficients themselves carry no net delay) leaves the
    coefficient-derived transfer function unchanged."""

input_sample_rate instance-attribute

input_sample_rate: PositiveNumber

Sample rate (Hz) this stage's filter coefficients operate at.

decimation_factor instance-attribute

decimation_factor: int

Integer decimation factor applied by this stage.

numerator instance-attribute

numerator: list[float]

Feedforward ("b") filter coefficients.

denominator instance-attribute

denominator: list[float]

Feedback ("a") filter coefficients. [1.0] for a pure FIR stage.

correction instance-attribute

correction: float

Time correction (seconds) already applied to the recorded data to cancel this stage's own filter delay.

Equivalent to FDSN StationXML's Decimation/Correction (SEED Blockette 57 field 8). Real digitisers timestamp their output as if this stage had zero delay, by shifting the data earlier by this amount; evaluating numerator/denominator alone (e.g. via scipy.signal.freqz) instead reproduces the filter's own, uncorrected delay. 0.0 (the default, correct for a stage with no such correction, e.g. a symmetric FIR stage where the coefficients themselves carry no net delay) leaves the coefficient-derived transfer function unchanged.

MiniSeismogram

Bases: SeismogramEndtimeMixin

Minimal class for use with the Seismogram type.

Examples:

>>> from pysmo import MiniSeismogram, Seismogram
>>> import pandas as pd
>>> from datetime import timezone
>>> import numpy as np
>>> now = pd.Timestamp.now(timezone.utc)
>>> delta = pd.Timedelta(seconds=0.1)
>>> seismogram = MiniSeismogram(begin_time=now, delta=delta, data=np.random.rand(100))
>>> isinstance(seismogram, Seismogram)
True
>>>

Attributes:

Name Type Description
end_time Timestamp

Seismogram end time.

begin_time UtcTimestamp

Seismogram begin time.

delta PositiveTimedelta

Seismogram sampling interval.

data ndarray

Seismogram data.

Source code in src/pysmo/_types/seismogram.py
@define(kw_only=True, slots=True)
class MiniSeismogram(SeismogramEndtimeMixin):
    """Minimal class for use with the [`Seismogram`][pysmo.Seismogram] type.

    Examples:
        ```python
        >>> from pysmo import MiniSeismogram, Seismogram
        >>> import pandas as pd
        >>> from datetime import timezone
        >>> import numpy as np
        >>> now = pd.Timestamp.now(timezone.utc)
        >>> delta = pd.Timedelta(seconds=0.1)
        >>> seismogram = MiniSeismogram(begin_time=now, delta=delta, data=np.random.rand(100))
        >>> isinstance(seismogram, Seismogram)
        True
        >>>
        ```
    """

    begin_time: UtcTimestamp = field(
        default=SeismogramDefaults.begin_time,
        converter=convert_to_utc_timestamp,
        on_setattr=setters.convert,
    )
    """Seismogram begin time."""

    delta: PositiveTimedelta = field(
        default=SeismogramDefaults.delta,
        converter=convert_to_timedelta,
        validator=[
            validators.instance_of(pd.Timedelta),
            validators.gt(pd.Timedelta(0)),
        ],
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Seismogram sampling interval."""

    data: np.ndarray = field(
        factory=lambda: np.array([]),
        converter=convert_to_ndarray,
        validator=validators.instance_of(np.ndarray),
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Seismogram data."""

end_time property

end_time: Timestamp

Seismogram end time.

begin_time class-attribute instance-attribute

begin_time: UtcTimestamp = field(
    default=SeismogramDefaults.begin_time,
    converter=convert_to_utc_timestamp,
    on_setattr=setters.convert,
)

Seismogram begin time.

delta class-attribute instance-attribute

delta: PositiveTimedelta = field(
    default=SeismogramDefaults.delta,
    converter=convert_to_timedelta,
    validator=[
        validators.instance_of(pd.Timedelta),
        validators.gt(pd.Timedelta(0)),
    ],
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Seismogram sampling interval.

data class-attribute instance-attribute

data: ndarray = field(
    factory=lambda: np.array([]),
    converter=convert_to_ndarray,
    validator=validators.instance_of(np.ndarray),
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Seismogram data.

MiniStation

Minimal class for use with the Station type.

Examples:

>>> from pysmo import MiniStation, Station, Location
>>> station = MiniStation(latitude=-21.680301, longitude=-46.732601, name="CACB", network="BL", channel="BHZ", location="00")
>>> isinstance(station, Station)
True
>>> isinstance(station, Location)
True
>>>

Attributes:

Name Type Description
name str

Station name.

network str

Network name.

location str

Location ID.

channel str

Channel code.

latitude float

Station latitude from -90 to 90 degrees.

longitude float

Station longitude from -180 to 180 degrees.

elevation float | None

Station elevation.

Source code in src/pysmo/_types/station.py
@define(kw_only=True, slots=True)
class MiniStation:
    """Minimal class for use with the [`Station`][pysmo.Station] type.

    Examples:
        ```python
        >>> from pysmo import MiniStation, Station, Location
        >>> station = MiniStation(latitude=-21.680301, longitude=-46.732601, name="CACB", network="BL", channel="BHZ", location="00")
        >>> isinstance(station, Station)
        True
        >>> isinstance(station, Location)
        True
        >>>
        ```
    """

    name: str = field(
        validator=[validators.min_len(1), validators.max_len(5)],
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Station name.

    See [`Station.name`][pysmo.Station.name] for more details.
    """

    network: str = field(
        validator=[validators.min_len(1), validators.max_len(2)],
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Network name.

    See [`Station.network`][pysmo.Station.network] for more details.
    """

    location: str = field(
        default="  ",
        validator=[validators.min_len(2), validators.max_len(2)],
        converter=_pad_string,
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Location ID.

    See [`Station.location`][pysmo.Station.location] for more details.
    """

    channel: str = field(
        validator=[validators.min_len(3), validators.max_len(3)],
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Channel code.

    See [`Station.channel`][pysmo.Station.channel] for more details.
    """

    latitude: float = field(
        converter=float,
        validator=[validators.ge(-90), validators.le(90)],
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Station latitude from -90 to 90 degrees."""

    longitude: float = field(
        converter=float,
        validator=[validators.gt(-180), validators.le(180)],
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Station longitude from -180 to 180 degrees."""

    elevation: float | None = field(
        default=None,
        converter=converters.optional(float),
        validator=validators.optional(validators.instance_of(float)),
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Station elevation."""

name class-attribute instance-attribute

name: str = field(
    validator=[
        validators.min_len(1),
        validators.max_len(5),
    ],
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Station name.

See Station.name for more details.

network class-attribute instance-attribute

network: str = field(
    validator=[
        validators.min_len(1),
        validators.max_len(2),
    ],
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Network name.

See Station.network for more details.

location class-attribute instance-attribute

location: str = field(
    default="  ",
    validator=[
        validators.min_len(2),
        validators.max_len(2),
    ],
    converter=_pad_string,
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Location ID.

See Station.location for more details.

channel class-attribute instance-attribute

channel: str = field(
    validator=[
        validators.min_len(3),
        validators.max_len(3),
    ],
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Channel code.

See Station.channel for more details.

latitude class-attribute instance-attribute

latitude: float = field(
    converter=float,
    validator=[validators.ge(-90), validators.le(90)],
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Station latitude from -90 to 90 degrees.

longitude class-attribute instance-attribute

longitude: float = field(
    converter=float,
    validator=[validators.gt(-180), validators.le(180)],
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Station longitude from -180 to 180 degrees.

elevation class-attribute instance-attribute

elevation: float | None = field(
    default=None,
    converter=converters.optional(float),
    validator=validators.optional(
        validators.instance_of(float)
    ),
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Station elevation.

MiniEvent

Minimal class for use with the Event type.

Examples:

>>> from pysmo import MiniEvent, Event, LocationWithDepth, Location
>>> import pandas as pd
>>> from datetime import timezone
>>> now = pd.Timestamp.now(timezone.utc)
>>> event = MiniEvent(latitude=-24.68, longitude=-26.73, depth=15234.0, time=now)
>>> isinstance(event, Event)
True
>>> isinstance(event, Location)
True
>>> isinstance(event, LocationWithDepth)
True
>>>

Attributes:

Name Type Description
time UtcTimestamp

Event origin time.

latitude float

Event latitude from -90 to 90 degrees.

longitude float

Event longitude from -180 to 180 degrees.

depth float

Event depth in metres (positive downward from the surface).

Source code in src/pysmo/_types/event.py
@define(kw_only=True, slots=True)
class MiniEvent:
    """Minimal class for use with the [`Event`][pysmo.Event] type.

    Examples:
        ```python
        >>> from pysmo import MiniEvent, Event, LocationWithDepth, Location
        >>> import pandas as pd
        >>> from datetime import timezone
        >>> now = pd.Timestamp.now(timezone.utc)
        >>> event = MiniEvent(latitude=-24.68, longitude=-26.73, depth=15234.0, time=now)
        >>> isinstance(event, Event)
        True
        >>> isinstance(event, Location)
        True
        >>> isinstance(event, LocationWithDepth)
        True
        >>>
        ```
    """

    time: UtcTimestamp = field(
        converter=convert_to_utc_timestamp,
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Event origin time."""

    latitude: float = field(
        converter=float,
        validator=[validators.ge(-90), validators.le(90)],
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Event latitude from -90 to 90 degrees."""

    longitude: float = field(
        converter=float,
        validator=[validators.gt(-180), validators.le(180)],
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Event longitude from -180 to 180 degrees."""

    depth: float = field(
        converter=float, on_setattr=setters.pipe(setters.convert, setters.validate)
    )
    """Event depth in metres (positive downward from the surface)."""

time class-attribute instance-attribute

Event origin time.

latitude class-attribute instance-attribute

latitude: float = field(
    converter=float,
    validator=[validators.ge(-90), validators.le(90)],
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Event latitude from -90 to 90 degrees.

longitude class-attribute instance-attribute

longitude: float = field(
    converter=float,
    validator=[validators.gt(-180), validators.le(180)],
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Event longitude from -180 to 180 degrees.

depth class-attribute instance-attribute

depth: float = field(
    converter=float,
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Event depth in metres (positive downward from the surface).

MiniLocation

Minimal class for use with the Location type.

Examples:

>>> from pysmo import MiniLocation, Location
>>> location = MiniLocation(latitude=41.8781, longitude=-87.6298)
>>> isinstance(location, Location)
True
>>>

Attributes:

Name Type Description
latitude float

Latitude from -90 to 90 degrees.

longitude float

Longitude from -180 to 180 degrees.

Source code in src/pysmo/_types/location.py
@define(kw_only=True, slots=True)
class MiniLocation:
    """Minimal class for use with the [`Location`][pysmo.Location] type.

    Examples:
        ```python
        >>> from pysmo import MiniLocation, Location
        >>> location = MiniLocation(latitude=41.8781, longitude=-87.6298)
        >>> isinstance(location, Location)
        True
        >>>
        ```
    """

    latitude: float = field(
        converter=float,
        validator=[validators.ge(-90), validators.le(90)],
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Latitude from -90 to 90 degrees."""

    longitude: float = field(
        converter=float,
        validator=[validators.gt(-180), validators.le(180)],
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Longitude from -180 to 180 degrees."""

latitude class-attribute instance-attribute

latitude: float = field(
    converter=float,
    validator=[validators.ge(-90), validators.le(90)],
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Latitude from -90 to 90 degrees.

longitude class-attribute instance-attribute

longitude: float = field(
    converter=float,
    validator=[validators.gt(-180), validators.le(180)],
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Longitude from -180 to 180 degrees.

MiniLocationWithDepth

Minimal class for use with the LocationWithDepth type.

Examples:

>>> from pysmo import MiniLocationWithDepth, LocationWithDepth, Location
>>> hypo = MiniLocationWithDepth(latitude=-24.68, longitude=-26.73, depth=15234.0)
>>> isinstance(hypo, LocationWithDepth)
True
>>> isinstance(hypo, Location)
True
>>>

Attributes:

Name Type Description
latitude float

Location latitude from -90 to 90 degrees.

longitude float

Location longitude from -180 to 180 degrees.

depth float

Location depth in metres (positive downward from the surface).

Source code in src/pysmo/_types/location_with_depth.py
@define(kw_only=True, slots=True)
class MiniLocationWithDepth:
    """Minimal class for use with the [`LocationWithDepth`][pysmo.LocationWithDepth] type.

    Examples:
        ```python
        >>> from pysmo import MiniLocationWithDepth, LocationWithDepth, Location
        >>> hypo = MiniLocationWithDepth(latitude=-24.68, longitude=-26.73, depth=15234.0)
        >>> isinstance(hypo, LocationWithDepth)
        True
        >>> isinstance(hypo, Location)
        True
        >>>
        ```
    """

    latitude: float = field(
        converter=float,
        validator=[validators.ge(-90), validators.le(90)],
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Location latitude from -90 to 90 degrees."""

    longitude: float = field(
        converter=float,
        validator=[validators.gt(-180), validators.le(180)],
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Location longitude from -180 to 180 degrees."""

    depth: float = field(
        converter=float, on_setattr=setters.pipe(setters.convert, setters.validate)
    )
    """Location depth in metres (positive downward from the surface)."""

latitude class-attribute instance-attribute

latitude: float = field(
    converter=float,
    validator=[validators.ge(-90), validators.le(90)],
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Location latitude from -90 to 90 degrees.

longitude class-attribute instance-attribute

longitude: float = field(
    converter=float,
    validator=[validators.gt(-180), validators.le(180)],
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Location longitude from -180 to 180 degrees.

depth class-attribute instance-attribute

depth: float = field(
    converter=float,
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Location depth in metres (positive downward from the surface).

MiniResponse

Minimal implementation of the Response type.

Examples:

>>> from pysmo import MiniResponse, Response
>>> response = MiniResponse(
...     poles=[-0.037 + 0.037j, -0.037 - 0.037j],
...     zeros=[0j, 0j],
...     overall_sensitivity=3.4e9,
...     input_units="M/S",
... )
>>> isinstance(response, Response)
True
>>>

Attributes:

Name Type Description
poles list[complex]

Response poles.

zeros list[complex]

Response zeros.

overall_sensitivity NonZeroNumber

Scale factor combined with poles/zeros to reconstruct H(f).

reference_sensitivity NonZeroNumber | None

Total system sensitivity at the reference frequency, A0 excluded.

input_units str

Physical units produced by removing this response.

Source code in src/pysmo/_types/response.py
@define(kw_only=True, slots=True)
class MiniResponse:
    """Minimal implementation of the [`Response`][pysmo.Response] type.

    Examples:
        ```python
        >>> from pysmo import MiniResponse, Response
        >>> response = MiniResponse(
        ...     poles=[-0.037 + 0.037j, -0.037 - 0.037j],
        ...     zeros=[0j, 0j],
        ...     overall_sensitivity=3.4e9,
        ...     input_units="M/S",
        ... )
        >>> isinstance(response, Response)
        True
        >>>
        ```
    """

    poles: list[complex] = field(
        converter=_convert_complex_list,
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Response poles.

    See [`Response.poles`][pysmo.Response.poles] for more details.
    """

    zeros: list[complex] = field(
        converter=_convert_complex_list,
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Response zeros.

    See [`Response.zeros`][pysmo.Response.zeros] for more details.
    """

    overall_sensitivity: NonZeroNumber = field(
        converter=float,
        validator=validate_nonzero,
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Scale factor combined with `poles`/`zeros` to reconstruct `H(f)`.

    See [`Response.overall_sensitivity`][pysmo.Response.overall_sensitivity]
    for more details.
    """

    reference_sensitivity: NonZeroNumber | None = field(
        default=None,
        converter=_convert_optional_float,
        validator=validators.optional(validate_nonzero),
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Total system sensitivity at the reference frequency, `A0` excluded.

    See
    [`Response.reference_sensitivity`][pysmo.Response.reference_sensitivity]
    for more details.
    """

    input_units: str = field(
        validator=validators.instance_of(str),
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Physical units produced by removing this response.

    See [`Response.input_units`][pysmo.Response.input_units] for more details.
    """

poles class-attribute instance-attribute

poles: list[complex] = field(
    converter=_convert_complex_list,
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Response poles.

See Response.poles for more details.

zeros class-attribute instance-attribute

zeros: list[complex] = field(
    converter=_convert_complex_list,
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Response zeros.

See Response.zeros for more details.

overall_sensitivity class-attribute instance-attribute

overall_sensitivity: NonZeroNumber = field(
    converter=float,
    validator=validate_nonzero,
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Scale factor combined with poles/zeros to reconstruct H(f).

See Response.overall_sensitivity for more details.

reference_sensitivity class-attribute instance-attribute

reference_sensitivity: NonZeroNumber | None = field(
    default=None,
    converter=_convert_optional_float,
    validator=validators.optional(validate_nonzero),
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Total system sensitivity at the reference frequency, A0 excluded.

See Response.reference_sensitivity for more details.

input_units class-attribute instance-attribute

input_units: str = field(
    validator=validators.instance_of(str),
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Physical units produced by removing this response.

See Response.input_units for more details.

MiniStagedResponse

Bases: MiniResponse

Minimal implementation of the StagedResponse type.

Examples:

>>> from pysmo import MiniStagedResponse, StagedResponse, Response
>>> response = MiniStagedResponse(
...     poles=[-0.037 + 0.037j, -0.037 - 0.037j],
...     zeros=[0j, 0j],
...     overall_sensitivity=3.4e9,
...     input_units="M/S",
... )
>>> isinstance(response, StagedResponse)
True
>>> isinstance(response, Response)
True
>>>

Attributes:

Name Type Description
poles list[complex]

Response poles.

zeros list[complex]

Response zeros.

overall_sensitivity NonZeroNumber

Scale factor combined with poles/zeros to reconstruct H(f).

reference_sensitivity NonZeroNumber | None

Total system sensitivity at the reference frequency, A0 excluded.

input_units str

Physical units produced by removing this response.

stages list[ResponseStage]

Digital decimation stages, in signal order.

Source code in src/pysmo/_types/response.py
@define(kw_only=True, slots=True)
class MiniStagedResponse(MiniResponse):
    """Minimal implementation of the [`StagedResponse`][pysmo.StagedResponse] type.

    Examples:
        ```python
        >>> from pysmo import MiniStagedResponse, StagedResponse, Response
        >>> response = MiniStagedResponse(
        ...     poles=[-0.037 + 0.037j, -0.037 - 0.037j],
        ...     zeros=[0j, 0j],
        ...     overall_sensitivity=3.4e9,
        ...     input_units="M/S",
        ... )
        >>> isinstance(response, StagedResponse)
        True
        >>> isinstance(response, Response)
        True
        >>>
        ```
    """

    stages: list[ResponseStage] = field(
        factory=list,
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Digital decimation stages, in signal order.

    See [`StagedResponse.stages`][pysmo.StagedResponse.stages] for more details.
    """

poles class-attribute instance-attribute

poles: list[complex] = field(
    converter=_convert_complex_list,
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Response poles.

See Response.poles for more details.

zeros class-attribute instance-attribute

zeros: list[complex] = field(
    converter=_convert_complex_list,
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Response zeros.

See Response.zeros for more details.

overall_sensitivity class-attribute instance-attribute

overall_sensitivity: NonZeroNumber = field(
    converter=float,
    validator=validate_nonzero,
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Scale factor combined with poles/zeros to reconstruct H(f).

See Response.overall_sensitivity for more details.

reference_sensitivity class-attribute instance-attribute

reference_sensitivity: NonZeroNumber | None = field(
    default=None,
    converter=_convert_optional_float,
    validator=validators.optional(validate_nonzero),
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Total system sensitivity at the reference frequency, A0 excluded.

See Response.reference_sensitivity for more details.

input_units class-attribute instance-attribute

input_units: str = field(
    validator=validators.instance_of(str),
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Physical units produced by removing this response.

See Response.input_units for more details.

stages class-attribute instance-attribute

stages: list[ResponseStage] = field(
    factory=list,
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Digital decimation stages, in signal order.

See StagedResponse.stages for more details.

MiniResponseStage

Minimal implementation of the ResponseStage type.

Examples:

>>> from pysmo import MiniResponseStage, ResponseStage
>>> stage = MiniResponseStage(
...     input_sample_rate=40.0,
...     decimation_factor=1,
...     numerator=[0.5, 0.5],
... )
>>> isinstance(stage, ResponseStage)
True
>>> stage.denominator
[1.0]
>>>

Attributes:

Name Type Description
input_sample_rate PositiveNumber

Sample rate this stage's filter coefficients operate at.

decimation_factor int

Integer decimation factor applied by this stage.

numerator list[float]

Feedforward ("b") filter coefficients.

denominator list[float]

Feedback ("a") filter coefficients.

correction float

Time correction (seconds) already applied to cancel this stage's own

Source code in src/pysmo/_types/response.py
@define(kw_only=True, slots=True)
class MiniResponseStage:
    """Minimal implementation of the [`ResponseStage`][pysmo.ResponseStage] type.

    Examples:
        ```python
        >>> from pysmo import MiniResponseStage, ResponseStage
        >>> stage = MiniResponseStage(
        ...     input_sample_rate=40.0,
        ...     decimation_factor=1,
        ...     numerator=[0.5, 0.5],
        ... )
        >>> isinstance(stage, ResponseStage)
        True
        >>> stage.denominator
        [1.0]
        >>>
        ```
    """

    input_sample_rate: PositiveNumber = field(
        converter=float,
        validator=validators.gt(0),
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Sample rate this stage's filter coefficients operate at.

    See [`ResponseStage.input_sample_rate`][pysmo.ResponseStage.input_sample_rate]
    for more details.
    """

    decimation_factor: int = field(
        converter=int,
        validator=validators.gt(0),
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Integer decimation factor applied by this stage.

    See [`ResponseStage.decimation_factor`][pysmo.ResponseStage.decimation_factor]
    for more details.
    """

    numerator: list[float] = field(
        converter=_convert_float_list,
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Feedforward ("b") filter coefficients.

    See [`ResponseStage.numerator`][pysmo.ResponseStage.numerator] for more details.
    """

    denominator: list[float] = field(
        factory=lambda: [1.0],
        converter=_convert_float_list,
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Feedback ("a") filter coefficients.

    See [`ResponseStage.denominator`][pysmo.ResponseStage.denominator] for more details.
    """

    correction: float = field(
        default=0.0,
        converter=float,
        on_setattr=setters.pipe(setters.convert, setters.validate),
    )
    """Time correction (seconds) already applied to cancel this stage's own
    filter delay.

    See [`ResponseStage.correction`][pysmo.ResponseStage.correction] for
    more details.
    """

input_sample_rate class-attribute instance-attribute

input_sample_rate: PositiveNumber = field(
    converter=float,
    validator=validators.gt(0),
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Sample rate this stage's filter coefficients operate at.

See ResponseStage.input_sample_rate for more details.

decimation_factor class-attribute instance-attribute

decimation_factor: int = field(
    converter=int,
    validator=validators.gt(0),
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Integer decimation factor applied by this stage.

See ResponseStage.decimation_factor for more details.

numerator class-attribute instance-attribute

numerator: list[float] = field(
    converter=_convert_float_list,
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Feedforward ("b") filter coefficients.

See ResponseStage.numerator for more details.

denominator class-attribute instance-attribute

denominator: list[float] = field(
    factory=lambda: [1.0],
    converter=_convert_float_list,
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Feedback ("a") filter coefficients.

See ResponseStage.denominator for more details.

correction class-attribute instance-attribute

correction: float = field(
    default=0.0,
    converter=float,
    on_setattr=setters.pipe(
        setters.convert, setters.validate
    ),
)

Time correction (seconds) already applied to cancel this stage's own filter delay.

See ResponseStage.correction for more details.