Skip to content

pysmo.tools.web

Tools for fetching seismological data from web services.

Thin wrappers around FDSN web services (EarthScope's, except fetch_quakeml, which targets USGS since EarthScope retired its event service). fetch_stationxml, fetch_station_inventory, fetch_sacpz, fetch_geocsvseismogram, fetch_sac, fetch_mseed, and fetch_quakeml return raw, unparsed responses, mostly a lower-level counterpart to a class's own parsing entry point (e.g. SAC.fetch, QuakeML.all_from_bytes), useful on their own for saving a raw response to disk and deferring parsing to later, without another network request.

Predicted arrival times, used to window these fetches, are computed locally by pysmo.tools.traveltime with no web service involved.

Type Aliases:

Name Description
QuakeMLOrderBy

Allowed orderby values for fetch_quakeml.

Functions:

Name Description
fetch_geocsvseismogram

Fetch raw GeoCSV waveform bytes for a station/channel and time window.

fetch_mseed

Fetch raw miniSEED waveform bytes for a station/channel and time window.

fetch_quakeml

Fetch raw QuakeML 1.2 event metadata bytes from the USGS fdsnws-event service.

fetch_sac

Fetch a raw SAC zip archive for a station/channel and time window.

fetch_sacpz

Fetch raw SAC PZ response metadata text for a station/channel.

fetch_station_inventory

Fetch raw FDSN StationXML inventory bytes from EarthScope's fdsnws-station.

fetch_stationxml

Fetch raw StationXML response metadata bytes for a station/channel.

QuakeMLOrderBy

QuakeMLOrderBy = Literal[
    "time", "time-asc", "magnitude", "magnitude-asc"
]

Allowed orderby values for fetch_quakeml.

fetch_geocsvseismogram

fetch_geocsvseismogram(
    *,
    station: Station,
    starttime: Timestamp,
    endtime: Timestamp
) -> bytes

Fetch raw GeoCSV waveform bytes for a station/channel and time window.

A lower-level counterpart to GeoCsvSeismogram.fetch: returns the waveform unparsed and uninterpreted. Save it to disk to defer parsing to later (offline, without another network request) via GeoCsvSeismogram.from_text.

Parameters:

Name Type Description Default
station Station

Any object satisfying the Station protocol. Provides the network, station code, location, and channel for the request.

required
starttime Timestamp

Start of the requested time window (UTC).

required
endtime Timestamp

End of the requested time window (UTC).

required

Returns:

Type Description
bytes

Raw GeoCSV document bytes.

Raises:

Type Description
ResponseError

If the dataselect web service returns an HTTP error.

Examples:

>>> import pandas as pd
>>> from pathlib import Path
>>> from pysmo import MiniStation
>>> from pysmo.tools.web import fetch_geocsvseismogram
>>> station = MiniStation(
...     name="ANMO", network="IU", location="00", channel="LHZ",
...     latitude=34.945981, longitude=-106.457133,
... )
>>> data = fetch_geocsvseismogram(
...     station=station,
...     starttime=pd.Timestamp("2010-02-27T06:44:00Z"),
...     endtime=pd.Timestamp("2010-02-27T06:54:00Z"),
... )
>>> _ = Path("ANMO.geocsv").write_bytes(data)
>>>
Source code in src/pysmo/tools/web.py
def fetch_geocsvseismogram(
    *, station: Station, starttime: pd.Timestamp, endtime: pd.Timestamp
) -> bytes:
    """Fetch raw GeoCSV waveform bytes for a station/channel and time window.

    A lower-level counterpart to
    [`GeoCsvSeismogram.fetch`][pysmo.classes.GeoCsvSeismogram.fetch]:
    returns the waveform unparsed and uninterpreted. Save it to disk to
    defer parsing to later (offline, without another network request)
    via [`GeoCsvSeismogram.from_text`][pysmo.classes.GeoCsvSeismogram.from_text].

    Args:
        station: Any object satisfying the [`Station`][pysmo.Station]
            protocol. Provides the network, station code, location, and
            channel for the request.
        starttime: Start of the requested time window (UTC).
        endtime: End of the requested time window (UTC).

    Returns:
        Raw GeoCSV document bytes.

    Raises:
        urllib3.exceptions.ResponseError: If the dataselect web service
            returns an HTTP error.

    Examples:
        <!-- skip: start if(not run_real_web_requests) -->
        ```python
        >>> import pandas as pd
        >>> from pathlib import Path
        >>> from pysmo import MiniStation
        >>> from pysmo.tools.web import fetch_geocsvseismogram
        >>> station = MiniStation(
        ...     name="ANMO", network="IU", location="00", channel="LHZ",
        ...     latitude=34.945981, longitude=-106.457133,
        ... )
        >>> data = fetch_geocsvseismogram(
        ...     station=station,
        ...     starttime=pd.Timestamp("2010-02-27T06:44:00Z"),
        ...     endtime=pd.Timestamp("2010-02-27T06:54:00Z"),
        ... )
        >>> _ = Path("ANMO.geocsv").write_bytes(data)
        >>>
        ```
        <!-- skip: end -->
    """
    return _fetch_dataselect(
        station=station,
        starttime=starttime,
        endtime=endtime,
        response_format="geocsv",
    )

fetch_mseed

fetch_mseed(
    *,
    station: Station,
    starttime: Timestamp,
    endtime: Timestamp
) -> bytes

Fetch raw miniSEED waveform bytes for a station/channel and time window.

A lower-level counterpart to MSeed.fetch: returns the miniSEED body returned by the dataselect web service unparsed and uninterpreted. Save it to disk to defer parsing to later (offline, without another network request) via MSeed.from_bytes or MSeed.all_from_bytes.

Parameters:

Name Type Description Default
station Station

Any object satisfying the Station protocol. Provides the network, station code, location, and channel for the request.

required
starttime Timestamp

Start of the requested time window (UTC).

required
endtime Timestamp

End of the requested time window (UTC).

required

Returns:

Type Description
bytes

Raw miniSEED bytes, as returned by the dataselect web service. An

bytes

empty bytes object if the service reports no data for the window.

Raises:

Type Description
ResponseError

If the dataselect web service returns an HTTP error.

Examples:

>>> import pandas as pd
>>> from pathlib import Path
>>> from pysmo import MiniStation
>>> from pysmo.tools.web import fetch_mseed
>>> station = MiniStation(
...     name="ANMO", network="IU", location="00", channel="LHZ",
...     latitude=34.945981, longitude=-106.457133,
... )
>>> data = fetch_mseed(
...     station=station,
...     starttime=pd.Timestamp("2010-02-27T06:44:00Z"),
...     endtime=pd.Timestamp("2010-02-27T06:54:00Z"),
... )
>>> _ = Path("ANMO.mseed").write_bytes(data)
>>>
Source code in src/pysmo/tools/web.py
def fetch_mseed(
    *, station: Station, starttime: pd.Timestamp, endtime: pd.Timestamp
) -> bytes:
    """Fetch raw miniSEED waveform bytes for a station/channel and time window.

    A lower-level counterpart to [`MSeed.fetch`][pysmo.classes.MSeed.fetch]:
    returns the miniSEED body returned by the dataselect web service
    unparsed and uninterpreted. Save it to disk to defer parsing to later (offline, without another
    network request) via
    [`MSeed.from_bytes`][pysmo.classes.MSeed.from_bytes] or
    [`MSeed.all_from_bytes`][pysmo.classes.MSeed.all_from_bytes].

    Args:
        station: Any object satisfying the [`Station`][pysmo.Station]
            protocol. Provides the network, station code, location, and
            channel for the request.
        starttime: Start of the requested time window (UTC).
        endtime: End of the requested time window (UTC).

    Returns:
        Raw miniSEED bytes, as returned by the dataselect web service. An
        empty `bytes` object if the service reports no data for the window.

    Raises:
        urllib3.exceptions.ResponseError: If the dataselect web service
            returns an HTTP error.

    Examples:
        <!-- skip: start if(not run_real_web_requests) -->
        ```python
        >>> import pandas as pd
        >>> from pathlib import Path
        >>> from pysmo import MiniStation
        >>> from pysmo.tools.web import fetch_mseed
        >>> station = MiniStation(
        ...     name="ANMO", network="IU", location="00", channel="LHZ",
        ...     latitude=34.945981, longitude=-106.457133,
        ... )
        >>> data = fetch_mseed(
        ...     station=station,
        ...     starttime=pd.Timestamp("2010-02-27T06:44:00Z"),
        ...     endtime=pd.Timestamp("2010-02-27T06:54:00Z"),
        ... )
        >>> _ = Path("ANMO.mseed").write_bytes(data)
        >>>
        ```
        <!-- skip: end -->
    """
    return _fetch_dataselect(
        station=station,
        starttime=starttime,
        endtime=endtime,
        response_format="miniseed",
    )

fetch_quakeml

fetch_quakeml(
    *,
    starttime: Timestamp | None = None,
    endtime: Timestamp | None = None,
    updatedafter: Timestamp | None = None,
    minlatitude: float | None = None,
    maxlatitude: float | None = None,
    minlongitude: float | None = None,
    maxlongitude: float | None = None,
    latitude: float | None = None,
    longitude: float | None = None,
    minradius: float | None = None,
    maxradius: float | None = None,
    mindepth_km: float | None = None,
    maxdepth_km: float | None = None,
    minmagnitude: float | None = None,
    maxmagnitude: float | None = None,
    magnitudetype: str | None = None,
    eventtype: str | None = None,
    eventid: str | None = None,
    limit: int | None = None,
    offset: int | None = None,
    orderby: QuakeMLOrderBy | None = None,
    catalog: str | None = None,
    contributor: str | None = None
) -> bytes

Fetch raw QuakeML 1.2 event metadata bytes from the USGS fdsnws-event service.

A lower-level counterpart to QuakeML.all_from_query: returns the QuakeML document unparsed. All parameters are optional; fetch_quakeml() with no arguments is a valid "everything" request, bounded only by the service's own limits.

Parameters:

Name Type Description Default
starttime Timestamp | None

Keep events at or after this origin time (UTC).

None
endtime Timestamp | None

Keep events at or before this origin time (UTC).

None
updatedafter Timestamp | None

Keep events modified after this time (UTC).

None
minlatitude float | None

Southern edge of a bounding box, in degrees.

None
maxlatitude float | None

Northern edge of a bounding box, in degrees.

None
minlongitude float | None

Western edge of a bounding box, in degrees.

None
maxlongitude float | None

Eastern edge of a bounding box, in degrees.

None
latitude float | None

Centre latitude for a radial search, in degrees.

None
longitude float | None

Centre longitude for a radial search, in degrees.

None
minradius float | None

Inner radius for a radial search, in degrees.

None
maxradius float | None

Outer radius for a radial search, in degrees.

None
mindepth_km float | None

Minimum event depth, in kilometres (the fdsnws-event filter unit; the parsed QuakeML.depth is in metres).

None
maxdepth_km float | None

Maximum event depth, in kilometres.

None
minmagnitude float | None

Minimum event magnitude.

None
maxmagnitude float | None

Maximum event magnitude.

None
magnitudetype str | None

Magnitude type to filter on (e.g. "Mw").

None
eventtype str | None

QuakeML event type, or a comma-separated list of them.

None
eventid str | None

Select a single event by the service's event id.

None
limit int | None

Maximum number of events to return.

None
offset int | None

Return events starting from this 1-based position.

None
orderby QuakeMLOrderBy | None

Sort order, one of "time", "time-asc", "magnitude", "magnitude-asc".

None
catalog str | None

Restrict to a named catalog.

None
contributor str | None

Restrict to a named contributor.

None

Returns:

Type Description
bytes

Raw QuakeML 1.2 document bytes.

Raises:

Type Description
ResponseError

If the event web service returns an HTTP error, including a 404 when no event matches.

Examples:

>>> import pandas as pd
>>> from pathlib import Path
>>> from pysmo.tools.web import fetch_quakeml
>>> xml = fetch_quakeml(
...     starttime=pd.Timestamp("2010-02-27T00:00:00Z"),
...     endtime=pd.Timestamp("2010-02-28T00:00:00Z"),
...     minmagnitude=8.0,
... )
>>> _ = Path("maule.quakeml").write_bytes(xml)
>>>
Source code in src/pysmo/tools/web.py
def fetch_quakeml(
    *,
    starttime: pd.Timestamp | None = None,
    endtime: pd.Timestamp | None = None,
    updatedafter: pd.Timestamp | None = None,
    minlatitude: float | None = None,
    maxlatitude: float | None = None,
    minlongitude: float | None = None,
    maxlongitude: float | None = None,
    latitude: float | None = None,
    longitude: float | None = None,
    minradius: float | None = None,
    maxradius: float | None = None,
    mindepth_km: float | None = None,
    maxdepth_km: float | None = None,
    minmagnitude: float | None = None,
    maxmagnitude: float | None = None,
    magnitudetype: str | None = None,
    eventtype: str | None = None,
    eventid: str | None = None,
    limit: int | None = None,
    offset: int | None = None,
    orderby: QuakeMLOrderBy | None = None,
    catalog: str | None = None,
    contributor: str | None = None,
) -> bytes:
    """Fetch raw QuakeML 1.2 event metadata bytes from the USGS fdsnws-event service.

    A lower-level counterpart to
    [`QuakeML.all_from_query`][pysmo.classes.QuakeML.all_from_query]: returns
    the QuakeML document unparsed. All parameters are optional;
    `fetch_quakeml()` with no arguments is a valid "everything" request,
    bounded only by the service's own limits.

    Args:
        starttime: Keep events at or after this origin time (UTC).
        endtime: Keep events at or before this origin time (UTC).
        updatedafter: Keep events modified after this time (UTC).
        minlatitude: Southern edge of a bounding box, in degrees.
        maxlatitude: Northern edge of a bounding box, in degrees.
        minlongitude: Western edge of a bounding box, in degrees.
        maxlongitude: Eastern edge of a bounding box, in degrees.
        latitude: Centre latitude for a radial search, in degrees.
        longitude: Centre longitude for a radial search, in degrees.
        minradius: Inner radius for a radial search, in degrees.
        maxradius: Outer radius for a radial search, in degrees.
        mindepth_km: Minimum event depth, in **kilometres** (the
            fdsnws-event filter unit; the parsed
            [`QuakeML.depth`][pysmo.classes.QuakeML] is in metres).
        maxdepth_km: Maximum event depth, in **kilometres**.
        minmagnitude: Minimum event magnitude.
        maxmagnitude: Maximum event magnitude.
        magnitudetype: Magnitude type to filter on (e.g. `"Mw"`).
        eventtype: QuakeML event type, or a comma-separated list of them.
        eventid: Select a single event by the service's event id.
        limit: Maximum number of events to return.
        offset: Return events starting from this 1-based position.
        orderby: Sort order, one of `"time"`, `"time-asc"`, `"magnitude"`,
            `"magnitude-asc"`.
        catalog: Restrict to a named catalog.
        contributor: Restrict to a named contributor.

    Returns:
        Raw QuakeML 1.2 document bytes.

    Raises:
        urllib3.exceptions.ResponseError: If the event web service returns
            an HTTP error, including a 404 when no event matches.

    Examples:
        <!-- skip: start if(not run_real_web_requests) -->
        ```python
        >>> import pandas as pd
        >>> from pathlib import Path
        >>> from pysmo.tools.web import fetch_quakeml
        >>> xml = fetch_quakeml(
        ...     starttime=pd.Timestamp("2010-02-27T00:00:00Z"),
        ...     endtime=pd.Timestamp("2010-02-28T00:00:00Z"),
        ...     minmagnitude=8.0,
        ... )
        >>> _ = Path("maule.quakeml").write_bytes(xml)
        >>>
        ```
        <!-- skip: end -->
    """
    params: dict[str, Any] = {"format": "xml", "nodata": "404"}
    params["starttime"] = _isoformat_or_none(starttime)
    params["endtime"] = _isoformat_or_none(endtime)
    params["updatedafter"] = _isoformat_or_none(updatedafter)
    params.update(
        {
            "minlatitude": minlatitude,
            "maxlatitude": maxlatitude,
            "minlongitude": minlongitude,
            "maxlongitude": maxlongitude,
            "latitude": latitude,
            "longitude": longitude,
            "minradius": minradius,
            "maxradius": maxradius,
            "mindepth": mindepth_km,
            "maxdepth": maxdepth_km,
            "minmagnitude": minmagnitude,
            "maxmagnitude": maxmagnitude,
            "magnitudetype": magnitudetype,
            "eventtype": eventtype,
            "eventid": eventid,
            "limit": limit,
            "offset": offset,
            "orderby": orderby,
            "catalog": catalog,
            "contributor": contributor,
        }
    )
    return http_get(
        _ServiceDefaults.event_url,
        {name: value for name, value in params.items() if value is not None},
        timeout_seconds=_ServiceDefaults.timeout_seconds,
        request_retries=_ServiceDefaults.request_retries,
        retry_delay_seconds=_ServiceDefaults.retry_delay_seconds,
    )

fetch_sac

fetch_sac(
    *,
    station: Station,
    starttime: Timestamp,
    endtime: Timestamp
) -> bytes

Fetch a raw SAC zip archive for a station/channel and time window.

A lower-level counterpart to SAC.fetch: returns the zip archive returned by the dataselect web service unparsed and uninterpreted, without extracting or reading any of its members. Save it to disk to defer parsing to later (offline, without another network request) via SAC.from_zip or SAC.all_from_zip.

Parameters:

Name Type Description Default
station Station

Any object satisfying the Station protocol. Provides the network, station code, location, and channel for the request.

required
starttime Timestamp

Start of the requested time window (UTC).

required
endtime Timestamp

End of the requested time window (UTC).

required

Returns:

Type Description
bytes

Raw zip archive bytes, as returned by the dataselect web service.

Raises:

Type Description
ResponseError

If the dataselect web service returns an HTTP error.

Examples:

>>> import pandas as pd
>>> from pathlib import Path
>>> from pysmo import MiniStation
>>> from pysmo.tools.web import fetch_sac
>>> station = MiniStation(
...     name="ANMO", network="IU", location="00", channel="LHZ",
...     latitude=34.945981, longitude=-106.457133,
... )
>>> data = fetch_sac(
...     station=station,
...     starttime=pd.Timestamp("2010-02-27T06:44:00Z"),
...     endtime=pd.Timestamp("2010-02-27T06:54:00Z"),
... )
>>> _ = Path("ANMO.sac.zip").write_bytes(data)
>>>
Source code in src/pysmo/tools/web.py
def fetch_sac(
    *, station: Station, starttime: pd.Timestamp, endtime: pd.Timestamp
) -> bytes:
    """Fetch a raw SAC zip archive for a station/channel and time window.

    A lower-level counterpart to [`SAC.fetch`][pysmo.classes.SAC.fetch]:
    returns the zip archive returned by the dataselect web service
    unparsed and uninterpreted, without extracting or reading any of its
    members. Save it to disk to defer parsing to later (offline, without another
    network request) via
    [`SAC.from_zip`][pysmo.classes.SAC.from_zip] or
    [`SAC.all_from_zip`][pysmo.classes.SAC.all_from_zip].

    Args:
        station: Any object satisfying the [`Station`][pysmo.Station]
            protocol. Provides the network, station code, location, and
            channel for the request.
        starttime: Start of the requested time window (UTC).
        endtime: End of the requested time window (UTC).

    Returns:
        Raw zip archive bytes, as returned by the dataselect web service.

    Raises:
        urllib3.exceptions.ResponseError: If the dataselect web service
            returns an HTTP error.

    Examples:
        <!-- skip: start if(not run_real_web_requests) -->
        ```python
        >>> import pandas as pd
        >>> from pathlib import Path
        >>> from pysmo import MiniStation
        >>> from pysmo.tools.web import fetch_sac
        >>> station = MiniStation(
        ...     name="ANMO", network="IU", location="00", channel="LHZ",
        ...     latitude=34.945981, longitude=-106.457133,
        ... )
        >>> data = fetch_sac(
        ...     station=station,
        ...     starttime=pd.Timestamp("2010-02-27T06:44:00Z"),
        ...     endtime=pd.Timestamp("2010-02-27T06:54:00Z"),
        ... )
        >>> _ = Path("ANMO.sac.zip").write_bytes(data)
        >>>
        ```
        <!-- skip: end -->
    """
    return _fetch_dataselect(
        station=station,
        starttime=starttime,
        endtime=endtime,
        response_format="sac.zip",
    )

fetch_sacpz

fetch_sacpz(
    *, station: Station, time: Timestamp | None = None
) -> str

Fetch raw SAC PZ response metadata text for a station/channel.

Fetched from fdsnws-station with level=response&format=sacpz, EarthScope's designated replacement for the irisws-sacpz service.

A lower-level counterpart to SacPZ.fetch: returns the response metadata unparsed and uninterpreted. Save it to disk to defer parsing to later (offline, without another network request) via SacPZ.from_text or SacPZ.all_from_text.

Parameters:

Name Type Description Default
station Station

Any object satisfying the Station protocol. Provides the network, station code, location, and channel for the request.

required
time Timestamp | None

Timestamp used to select the response epoch server-side, so exactly one epoch is returned. If None, the web service defaults to the currently-open epoch.

None

Returns:

Type Description
str

Raw SAC PZ text.

Raises:

Type Description
ResponseError

If the web service returns an HTTP error.

Examples:

>>> from pathlib import Path
>>> from pysmo import MiniStation
>>> from pysmo.tools.web import fetch_sacpz
>>> station = MiniStation(
...     name="ANMO", network="IU", location="00", channel="BHZ",
...     latitude=34.945981, longitude=-106.457133,
... )
>>> text = fetch_sacpz(station=station)
>>> _ = Path("ANMO.pz").write_text(text)
>>>
Source code in src/pysmo/tools/web.py
def fetch_sacpz(*, station: Station, time: pd.Timestamp | None = None) -> str:
    """Fetch raw SAC PZ response metadata text for a station/channel.

    Fetched from `fdsnws-station` with `level=response&format=sacpz`,
    EarthScope's designated replacement for the `irisws-sacpz` service.

    A lower-level counterpart to
    [`SacPZ.fetch`][pysmo.classes.SacPZ.fetch]: returns the response
    metadata unparsed and uninterpreted. Save it to disk to defer parsing
    to later (offline, without another network request) via
    [`SacPZ.from_text`][pysmo.classes.SacPZ.from_text] or
    [`SacPZ.all_from_text`][pysmo.classes.SacPZ.all_from_text].

    Args:
        station: Any object satisfying the [`Station`][pysmo.Station]
            protocol. Provides the network, station code, location, and
            channel for the request.
        time: Timestamp used to select the response epoch server-side, so
            exactly one epoch is returned. If `None`, the web service
            defaults to the currently-open epoch.

    Returns:
        Raw SAC PZ text.

    Raises:
        urllib3.exceptions.ResponseError: If the web service returns an HTTP
            error.

    Examples:
        <!-- skip: start if(not run_real_web_requests) -->
        ```python
        >>> from pathlib import Path
        >>> from pysmo import MiniStation
        >>> from pysmo.tools.web import fetch_sacpz
        >>> station = MiniStation(
        ...     name="ANMO", network="IU", location="00", channel="BHZ",
        ...     latitude=34.945981, longitude=-106.457133,
        ... )
        >>> text = fetch_sacpz(station=station)
        >>> _ = Path("ANMO.pz").write_text(text)
        >>>
        ```
        <!-- skip: end -->
    """
    params: dict[str, Any] = {
        "net": station.network,
        "sta": station.name,
        "loc": station.location,
        "cha": station.channel,
        "level": "response",
        "format": "sacpz",
    }
    if time is not None:
        params["time"] = convert_to_utc_timestamp(time).isoformat()
    return http_get(
        _ServiceDefaults.station_url,
        params,
        timeout_seconds=_ServiceDefaults.timeout_seconds,
        request_retries=_ServiceDefaults.request_retries,
        retry_delay_seconds=_ServiceDefaults.retry_delay_seconds,
    ).decode("utf-8")

fetch_station_inventory

fetch_station_inventory(
    *,
    network: str,
    station: str = "*",
    location: str = "*",
    channel: str,
    starttime: Timestamp | None = None,
    endtime: Timestamp | None = None,
    updatedafter: Timestamp | None = None,
    minlatitude: float | None = None,
    maxlatitude: float | None = None,
    minlongitude: float | None = None,
    maxlongitude: float | None = None,
    latitude: float | None = None,
    longitude: float | None = None,
    minradius: float | None = None,
    maxradius: float | None = None,
    includerestricted: bool | None = None,
    matchtimeseries: bool | None = None
) -> bytes

Fetch raw FDSN StationXML inventory bytes from EarthScope's fdsnws-station.

A bulk, query-style counterpart to fetch_stationxml (which is single-station and level=response). Returns a level=channel document covering every <Channel> epoch matching the query; parse it with StationXML.all_from_bytes and narrow in memory (the results carry no response).

network and channel are required (a query without them attempts to download the entire global inventory); station and location default to the FDSN "any" wildcard. Selection strings are sent verbatim, so the service's native comma-lists and * / ? wildcards work (network="IU,II", channel="BH?").

Parameters:

Name Type Description Default
network str

Network code(s); comma-list and * / ? wildcards allowed.

required
station str

Station code(s), defaulting to all.

'*'
location str

Location code(s), defaulting to all.

'*'
channel str

Channel code(s); comma-list and wildcards allowed.

required
starttime Timestamp | None

Keep metadata epochs intersecting at or after this time (UTC). Does not collapse to one epoch per channel.

None
endtime Timestamp | None

Keep metadata epochs intersecting at or before this time (UTC).

None
updatedafter Timestamp | None

Keep metadata modified after this time (UTC).

None
minlatitude float | None

Southern edge of a bounding box, in degrees.

None
maxlatitude float | None

Northern edge of a bounding box, in degrees.

None
minlongitude float | None

Western edge of a bounding box, in degrees.

None
maxlongitude float | None

Eastern edge of a bounding box, in degrees.

None
latitude float | None

Centre latitude for a radial search, in degrees.

None
longitude float | None

Centre longitude for a radial search, in degrees.

None
minradius float | None

Inner radius for a radial search, in degrees.

None
maxradius float | None

Outer radius for a radial search, in degrees.

None
includerestricted bool | None

Include metadata for restricted stations (service default is True).

None
matchtimeseries bool | None

Limit to metadata with recoverable timeseries data (service default is False; data-centre-dependent, can be slow).

None

Returns:

Type Description
bytes

Raw StationXML document bytes.

Raises:

Type Description
ResponseError

If the station web service returns an HTTP error, including a 404 when nothing matches.

Examples:

>>> from pathlib import Path
>>> from pysmo.tools.web import fetch_station_inventory
>>> xml = fetch_station_inventory(network="IU", station="ANMO", channel="BHZ")
>>> _ = Path("iu_anmo.xml").write_bytes(xml)
>>>
Source code in src/pysmo/tools/web.py
def fetch_station_inventory(
    *,
    network: str,
    station: str = "*",
    location: str = "*",
    channel: str,
    starttime: pd.Timestamp | None = None,
    endtime: pd.Timestamp | None = None,
    updatedafter: pd.Timestamp | None = None,
    minlatitude: float | None = None,
    maxlatitude: float | None = None,
    minlongitude: float | None = None,
    maxlongitude: float | None = None,
    latitude: float | None = None,
    longitude: float | None = None,
    minradius: float | None = None,
    maxradius: float | None = None,
    includerestricted: bool | None = None,
    matchtimeseries: bool | None = None,
) -> bytes:
    """Fetch raw FDSN StationXML inventory bytes from EarthScope's fdsnws-station.

    A bulk, query-style counterpart to
    [`fetch_stationxml`][pysmo.tools.web.fetch_stationxml] (which is
    single-station and `level=response`). Returns a `level=channel`
    document covering every `<Channel>` epoch matching the query; parse it
    with [`StationXML.all_from_bytes`][pysmo.classes.StationXML.all_from_bytes]
    and narrow in memory (the results carry no `response`).

    `network` and `channel` are required (a query without them attempts to
    download the entire global inventory); `station` and `location` default
    to the FDSN "any" wildcard. Selection strings are sent verbatim, so the
    service's native comma-lists and `*` / `?` wildcards work
    (`network="IU,II"`, `channel="BH?"`).

    Args:
        network: Network code(s); comma-list and `*` / `?` wildcards allowed.
        station: Station code(s), defaulting to all.
        location: Location code(s), defaulting to all.
        channel: Channel code(s); comma-list and wildcards allowed.
        starttime: Keep metadata epochs intersecting at or after this time
            (UTC). Does not collapse to one epoch per channel.
        endtime: Keep metadata epochs intersecting at or before this time (UTC).
        updatedafter: Keep metadata modified after this time (UTC).
        minlatitude: Southern edge of a bounding box, in degrees.
        maxlatitude: Northern edge of a bounding box, in degrees.
        minlongitude: Western edge of a bounding box, in degrees.
        maxlongitude: Eastern edge of a bounding box, in degrees.
        latitude: Centre latitude for a radial search, in degrees.
        longitude: Centre longitude for a radial search, in degrees.
        minradius: Inner radius for a radial search, in degrees.
        maxradius: Outer radius for a radial search, in degrees.
        includerestricted: Include metadata for restricted stations
            (service default is `True`).
        matchtimeseries: Limit to metadata with recoverable timeseries data
            (service default is `False`; data-centre-dependent, can be slow).

    Returns:
        Raw StationXML document bytes.

    Raises:
        urllib3.exceptions.ResponseError: If the station web service returns
            an HTTP error, including a 404 when nothing matches.

    Examples:
        <!-- skip: start if(not run_real_web_requests) -->
        ```python
        >>> from pathlib import Path
        >>> from pysmo.tools.web import fetch_station_inventory
        >>> xml = fetch_station_inventory(network="IU", station="ANMO", channel="BHZ")
        >>> _ = Path("iu_anmo.xml").write_bytes(xml)
        >>>
        ```
        <!-- skip: end -->
    """
    params: dict[str, Any] = {
        "format": "xml",
        "nodata": "404",
        "level": "channel",
        "net": network,
        "sta": station,
        "loc": location,
        "cha": channel,
    }
    params["starttime"] = _isoformat_or_none(starttime)
    params["endtime"] = _isoformat_or_none(endtime)
    params["updatedafter"] = _isoformat_or_none(updatedafter)
    params.update(
        {
            "minlatitude": minlatitude,
            "maxlatitude": maxlatitude,
            "minlongitude": minlongitude,
            "maxlongitude": maxlongitude,
            "latitude": latitude,
            "longitude": longitude,
            "minradius": minradius,
            "maxradius": maxradius,
        }
    )
    for name, value in (
        ("includerestricted", includerestricted),
        ("matchtimeseries", matchtimeseries),
    ):
        if value is not None:
            params[name] = "true" if value else "false"
    return http_get(
        _ServiceDefaults.station_url,
        {name: value for name, value in params.items() if value is not None},
        timeout_seconds=_ServiceDefaults.timeout_seconds,
        request_retries=_ServiceDefaults.request_retries,
        retry_delay_seconds=_ServiceDefaults.retry_delay_seconds,
    )

fetch_stationxml

fetch_stationxml(*, station: Station) -> bytes

Fetch raw StationXML response metadata bytes for a station/channel.

A lower-level counterpart to StationXML.fetch: returns the StationXML document unparsed and uninterpreted, covering every response epoch on record for the requested channel. Save it to disk to defer parsing to later (offline, without another network request) via StationXML.from_bytes or StationXML.all_from_bytes.

Parameters:

Name Type Description Default
station Station

Any object satisfying the Station protocol. Provides the network, station code, location, and channel for the request.

required

Returns:

Type Description
bytes

Raw StationXML document bytes.

Raises:

Type Description
ResponseError

If the station web service returns an HTTP error.

Examples:

>>> from pathlib import Path
>>> from pysmo import MiniStation
>>> from pysmo.tools.web import fetch_stationxml
>>> station = MiniStation(
...     name="ANMO", network="IU", location="00", channel="BHZ",
...     latitude=34.945981, longitude=-106.457133,
... )
>>> xml = fetch_stationxml(station=station)
>>> _ = Path("ANMO.xml").write_bytes(xml)
>>>
Source code in src/pysmo/tools/web.py
def fetch_stationxml(*, station: Station) -> bytes:
    """Fetch raw StationXML response metadata bytes for a station/channel.

    A lower-level counterpart to
    [`StationXML.fetch`][pysmo.classes.StationXML.fetch]: returns the
    StationXML document unparsed and uninterpreted, covering every response
    epoch on record for the requested channel. Save it to disk to defer
    parsing to later (offline, without another network request) via
    [`StationXML.from_bytes`][pysmo.classes.StationXML.from_bytes] or
    [`StationXML.all_from_bytes`][pysmo.classes.StationXML.all_from_bytes].

    Args:
        station: Any object satisfying the [`Station`][pysmo.Station]
            protocol. Provides the network, station code, location, and
            channel for the request.

    Returns:
        Raw StationXML document bytes.

    Raises:
        urllib3.exceptions.ResponseError: If the station web service returns
            an HTTP error.

    Examples:
        <!-- skip: start if(not run_real_web_requests) -->
        ```python
        >>> from pathlib import Path
        >>> from pysmo import MiniStation
        >>> from pysmo.tools.web import fetch_stationxml
        >>> station = MiniStation(
        ...     name="ANMO", network="IU", location="00", channel="BHZ",
        ...     latitude=34.945981, longitude=-106.457133,
        ... )
        >>> xml = fetch_stationxml(station=station)
        >>> _ = Path("ANMO.xml").write_bytes(xml)
        >>>
        ```
        <!-- skip: end -->
    """
    return http_get(
        _ServiceDefaults.station_url,
        {
            "net": station.network,
            "sta": station.name,
            "loc": station.location,
            "cha": station.channel,
            "level": "response",
        },
        timeout_seconds=_ServiceDefaults.timeout_seconds,
        request_retries=_ServiceDefaults.request_retries,
        retry_delay_seconds=_ServiceDefaults.retry_delay_seconds,
    )