pysmo.classes
Concrete classes compatible with pysmo types.
The pysmo.classes module provides classes that implement one or more
pysmo protocol types. These classes can be used directly with any
pysmo function or tool that operates on pysmo types.
Each class is designed with the protocol(s) it implements in mind, not to
reproduce its native format's full specification. The scope isn't strictly
limited to protocol attributes — pysmo.classes.StationXML, for
example, also carries epoch bookkeeping (start_date/end_date) and a
nested instrument response — but the protocol is the organising goal, not
fidelity to the format. Reconstructing a complete file for every supported
format is explicitly not a goal: where a class supports writing, the
guarantee is only that the output round-trips through that same class's own
reader, not that it satisfies the format's full external specification.
Classes:
| Name | Description |
|---|---|
GeoCsvSeismogram |
Import/export class for seismograms in the GeoCSV timeseries format. |
MSeed |
Import/export class for one contiguous miniSEED trace segment. |
QuakeML |
Import class for FDSN QuakeML event metadata. |
SAC |
Access and modify data stored in SAC files. |
SacEvent |
Helper class for SAC event attributes. |
SacPZ |
Import class for SAC PZ (pole-zero) files. |
SacSeismogram |
Helper class for SAC seismogram attributes. |
SacStation |
Helper class for SAC station attributes. |
SacTimestamps |
Helper class to access times stored in SAC headers as |
StationXML |
Import class for FDSN StationXML station metadata. |
Functions:
| Name | Description |
|---|---|
resolve_epochs |
Collapse station epochs to the one per NSLC valid at a given time. |
GeoCsvSeismogram
Bases: SeismogramEndtimeMixin
Import/export class for seismograms in the GeoCSV timeseries format.
Reads a waveform from the timeseries flavour of
GeoCSV and exposes
it as a Seismogram-compatible object.
This class is intended as a data-ingestion step. Once loaded, use
clone_to_mini to convert the
waveform to a MiniSeismogram, which can then
be passed to copy_from_mini to
populate another object such as a SAC instance.
Use write to serialise the
instance back to a GeoCSV 2.0 file, or pysmo.lib.io.write_geocsv
to write one or more Seismogram-compatible objects in a single call.
Examples:
>>> from pysmo.classes import GeoCsvSeismogram
>>> text = '''\
... # dataset: GeoCSV 2.0
... # delimiter: ,
... # field_unit: UTC, Counts
... # field_type: datetime, INTEGER
... # SID: IU_ANMO_00_LHZ
... # sample_count: 3
... # sample_rate_hz: 1.0
... # start_time: 2010-02-27T06:30:00Z
... Time, Sample
... 2010-02-27T06:30:00Z, -47297
... 2010-02-27T06:30:01Z, -47298
... 2010-02-27T06:30:02Z, -47299'''
>>> seismogram = GeoCsvSeismogram.from_text(text)
>>> seismogram.sourceid
'IU_ANMO_00_LHZ'
>>> seismogram.data
array([-47297., -47298., -47299.])
>>> seismogram.end_time
Timestamp('2010-02-27 06:30:02+0000', tz='UTC')
>>> import pathlib
>>> seismogram.write("out.geocsv"); recovered = GeoCsvSeismogram.from_text(pathlib.Path("out.geocsv").read_text())
>>> recovered.sourceid
'IU_ANMO_00_LHZ'
>>>
Methods:
| Name | Description |
|---|---|
fetch |
Fetch and parse a seismogram from the EarthScope FDSN dataselect web service, for an absolute time window. |
from_text |
Create a new instance from a GeoCSV text body. |
write |
Write this seismogram to a GeoCSV 2.0 file. |
Attributes:
| Name | Type | Description |
|---|---|---|
begin_time |
UtcTimestamp
|
Seismogram begin time. |
data |
NDArray[floating]
|
Seismogram data. |
delta |
PositiveTimedelta
|
Seismogram sampling interval. |
sample_count |
int
|
Number of samples, always equal to |
sourceid |
str
|
FDSN Source Identifier as carried in the GeoCSV |
Source code in src/pysmo/classes/_geocsv.py
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | |
begin_time
class-attribute
instance-attribute
begin_time: UtcTimestamp = field(
converter=convert_to_utc_timestamp,
on_setattr=setters.convert,
)
Seismogram begin time.
data
class-attribute
instance-attribute
data: NDArray[floating] = field(
converter=convert_to_ndarray,
validator=validators.instance_of(np.ndarray),
on_setattr=setters.pipe(
setters.convert, setters.validate
),
eq=cmp_using(eq=np.array_equal),
)
Seismogram data.
delta
class-attribute
instance-attribute
delta: PositiveTimedelta = field(
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.
sourceid
class-attribute
instance-attribute
sourceid: str = field(
validator=validators.instance_of(str),
on_setattr=setters.validate,
)
FDSN Source Identifier as carried in the GeoCSV SID header.
Stored verbatim as parsed, e.g. IU_ANMO_00_LHZ — no FDSN: URN
prefix, and the channel is not split into band/source/subsource. This
differs from MSeed.sourceid, which
keeps the full URN form. This is parse-time metadata: it describes the
GeoCSV data the instance was created from and is not updated when other
attributes change.
fetch
classmethod
Fetch and parse a seismogram from the EarthScope FDSN dataselect web service, for an absolute time window.
For a window relative to a predicted phase arrival instead, compute
the window yourself (e.g. with
pysmo.tools.traveltime.travel_times, which shows exactly this
in its own Examples) and pass the resulting starttime/endtime
here.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
station
|
Station
|
Any object satisfying the |
required |
starttime
|
Timestamp
|
Start of the requested time window (UTC). |
required |
endtime
|
Timestamp
|
End of the requested time window (UTC). |
required |
Returns:
| Type | Description |
|---|---|
Self
|
A new GeoCsvSeismogram instance. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no waveform data is returned for the given window, or the returned segments cannot be merged into a continuous trace (data gaps, differing channels or sample rates). |
ResponseError
|
If the dataselect web service returns an HTTP error. |
Examples:
>>> import pandas as pd
>>> from pysmo import MiniStation
>>> from pysmo.classes import GeoCsvSeismogram
>>> station = MiniStation(
... name="ANMO", network="IU", location="00", channel="LHZ",
... latitude=34.945981, longitude=-106.457133,
... )
>>> seismogram = GeoCsvSeismogram.fetch(
... station=station,
... starttime=pd.Timestamp("2010-02-27T06:44:00Z"),
... endtime=pd.Timestamp("2010-02-27T06:54:00Z"),
... )
>>>
Source code in src/pysmo/classes/_geocsv.py
from_text
classmethod
Create a new instance from a GeoCSV text body.
The text may contain several timeseries datasets (the EarthScope dataselect service returns one dataset per contiguous segment); they are merged into a single continuous waveform.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
text
|
str
|
GeoCSV text containing one or more timeseries datasets. |
required |
Returns:
| Type | Description |
|---|---|
Self
|
A new GeoCsvSeismogram instance. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the text contains no GeoCSV datasets, a dataset is not a valid timeseries, or the datasets cannot be merged into a continuous waveform (data gaps, differing channels or sample rates). |
Source code in src/pysmo/classes/_geocsv.py
write
Write this seismogram to a GeoCSV 2.0 file.
Serialises the instance as a single GeoCSV 2.0 timeseries dataset.
To write several seismograms into one multi-dataset file use
pysmo.lib.io.write_geocsv directly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
Destination file path. The file is written in UTF-8 text mode and any existing content is overwritten. |
required |
Examples:
>>> import pathlib
>>> from pysmo.classes import GeoCsvSeismogram
>>> text = '''\
... # dataset: GeoCSV 2.0
... # delimiter: ,
... # field_unit: UTC, Counts
... # field_type: datetime, INTEGER
... # SID: IU_ANMO_00_LHZ
... # sample_count: 3
... # sample_rate_hz: 1.0
... # start_time: 2010-02-27T06:30:00Z
... Time, Sample
... 2010-02-27T06:30:00Z, -47297
... 2010-02-27T06:30:01Z, -47298
... 2010-02-27T06:30:02Z, -47299'''
>>> seismogram = GeoCsvSeismogram.from_text(text)
>>> seismogram.write("out.geocsv"); recovered = GeoCsvSeismogram.from_text(
... pathlib.Path("out.geocsv").read_text()
... )
>>> recovered.sourceid == seismogram.sourceid
True
>>>
Source code in src/pysmo/classes/_geocsv.py
MSeed
Bases: SeismogramEndtimeMixin
Import/export class for one contiguous miniSEED trace segment.
Wraps EarthScope's pymseed and exposes a single regularly-sampled
segment as a Seismogram-compatible object. The
pymseed trace-list hierarchy is flattened at read time: each
contiguous segment becomes one MSeed.
miniSEED carries no station coordinates and no event data — only
channel identity, timing and samples. MSeed exposes the network,
station, location and channel codes as read-only properties derived
from sourceid (an MSeed is a StationCode at
runtime), but not Station. sourceid is the single
authoritative identity value; to relabel, set it directly. For a
Station, build a MiniStation (or fetch a
StationXML) separately and combine.
Use from_file /
from_bytes to read a single
segment, their all_* counterparts to read every segment, and
fetch to read directly from the
EarthScope dataselect web service. Use
write to serialise back to a miniSEED
file, or pysmo.lib.io.write_mseed to write several segments in a
single call.
Examples:
>>> from pysmo.classes import MSeed
>>> seismogram = MSeed.from_file("example.mseed")
>>> seismogram.sourceid
'FDSN:IU_ANMO_00_B_H_Z'
>>> seismogram.network, seismogram.name, seismogram.location, seismogram.channel
('IU', 'ANMO', '00', 'BHZ')
>>>
Methods:
| Name | Description |
|---|---|
all_from_bytes |
Create one instance per contiguous segment in miniSEED bytes. |
all_from_file |
Create one instance per contiguous segment in a miniSEED file. |
fetch |
Fetch and parse a seismogram from the EarthScope FDSN dataselect web service, for an absolute time window. |
from_bytes |
Create a new instance from miniSEED bytes holding exactly one contiguous segment. |
from_file |
Create a new instance from a miniSEED file holding exactly one contiguous segment. |
write |
Write this seismogram to a miniSEED file. |
Attributes:
| Name | Type | Description |
|---|---|---|
begin_time |
UtcTimestamp
|
Seismogram begin time. |
channel |
str
|
Channel code, derived from |
data |
NDArray[floating]
|
Seismogram data, always |
delta |
PositiveTimedelta
|
Seismogram sampling interval. |
location |
str
|
Location code, derived from |
name |
str
|
Station code, derived from |
network |
str
|
Network code, derived from |
publication_version |
int
|
miniSEED publication (quality) version this segment was read from. |
sample_count |
int
|
Number of samples, always equal to |
sourceid |
str
|
FDSN Source Identifier this segment was read from. |
Source code in src/pysmo/classes/_mseed.py
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 | |
begin_time
class-attribute
instance-attribute
begin_time: UtcTimestamp = field(
converter=convert_to_utc_timestamp,
on_setattr=setters.convert,
)
Seismogram begin time.
data
class-attribute
instance-attribute
data: NDArray[floating] = field(
converter=_convert_mseed_data,
validator=validators.instance_of(np.ndarray),
on_setattr=setters.pipe(
setters.convert, setters.validate
),
eq=cmp_using(eq=np.array_equal),
)
Seismogram data, always float64.
delta
class-attribute
instance-attribute
delta: PositiveTimedelta = field(
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.
publication_version
class-attribute
instance-attribute
miniSEED publication (quality) version this segment was read from.
sourceid
class-attribute
instance-attribute
sourceid: str = field(
validator=validators.instance_of(str),
on_setattr=setters.validate,
)
FDSN Source Identifier this segment was read from.
The full URN form as carried in miniSEED and returned by pymseed,
e.g. FDSN:IU_ANMO_00_B_H_Z — the FDSN: prefix is kept and the
channel is split into band/source/subsource. This differs from
GeoCsvSeismogram.sourceid,
which keeps the shorter GeoCSV SID header form. This is parse-time
metadata and is not updated when other attributes change.
all_from_bytes
classmethod
Create one instance per contiguous segment in miniSEED bytes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
bytes
|
Raw miniSEED bytes. |
required |
Returns:
| Type | Description |
|---|---|
list[Self]
|
One MSeed instance per contiguous segment, grouped by source |
list[Self]
|
identifier and ordered by time within each. Empty if the data |
list[Self]
|
holds no segments. |
Raises:
| Type | Description |
|---|---|
MiniSEEDError
|
If the data cannot be read as miniSEED. |
Source code in src/pysmo/classes/_mseed.py
all_from_file
classmethod
Create one instance per contiguous segment in a miniSEED file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str | PathLike[str]
|
Path to the miniSEED file to read. |
required |
Returns:
| Type | Description |
|---|---|
list[Self]
|
One MSeed instance per contiguous segment, grouped by source |
list[Self]
|
identifier and ordered by time within each. Empty if the file |
list[Self]
|
holds no data. |
Raises:
| Type | Description |
|---|---|
MiniSEEDError
|
If the file cannot be read as miniSEED. |
Source code in src/pysmo/classes/_mseed.py
fetch
classmethod
Fetch and parse a seismogram from the EarthScope FDSN dataselect web service, for an absolute time window.
For a window relative to a predicted phase arrival instead, compute
the window yourself (e.g. with
pysmo.tools.traveltime.travel_times, which shows exactly this
in its own Examples) and pass the resulting starttime/endtime
here.
To fetch once and interpret later (e.g. offline, or without
repeating the network request), use
pysmo.tools.web.fetch_mseed and
from_bytes /
all_from_bytes directly
instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
station
|
Station
|
Any object satisfying the |
required |
starttime
|
Timestamp
|
Start of the requested time window (UTC). |
required |
endtime
|
Timestamp
|
End of the requested time window (UTC). |
required |
Returns:
| Type | Description |
|---|---|
Self
|
A new MSeed instance. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no waveform data is returned for the given window, or more than one contiguous segment is returned (a data gap, or a wildcarded channel/location code matching more than one channel). |
ResponseError
|
If the dataselect web service returns an HTTP error. |
Examples:
>>> import pandas as pd
>>> from pysmo import MiniStation
>>> from pysmo.classes import MSeed
>>> station = MiniStation(
... name="ANMO", network="IU", location="00", channel="LHZ",
... latitude=34.945981, longitude=-106.457133,
... )
>>> seismogram = MSeed.fetch(
... station=station,
... starttime=pd.Timestamp("2010-02-27T06:44:00Z"),
... endtime=pd.Timestamp("2010-02-27T06:54:00Z"),
... )
>>>
Source code in src/pysmo/classes/_mseed.py
from_bytes
classmethod
Create a new instance from miniSEED bytes holding exactly one contiguous segment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
bytes
|
Raw miniSEED bytes. |
required |
Returns:
| Type | Description |
|---|---|
Self
|
A new MSeed instance. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the data holds zero, or more than one, contiguous segment (a data gap, or more than one channel). |
MiniSEEDError
|
If the data cannot be read as miniSEED. |
Source code in src/pysmo/classes/_mseed.py
from_file
classmethod
Create a new instance from a miniSEED file holding exactly one contiguous segment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str | PathLike[str]
|
Path to the miniSEED file to read. |
required |
Returns:
| Type | Description |
|---|---|
Self
|
A new MSeed instance. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the file holds zero, or more than one, contiguous segment (a data gap, or more than one channel). |
MiniSEEDError
|
If the file cannot be read as miniSEED. |
Source code in src/pysmo/classes/_mseed.py
write
Write this seismogram to a miniSEED file.
Samples are written as float64 (uncompressed) and the
publication version is set to 1 — sourceid and timing are
preserved, publication_version is not. For STEIM integer
compression, or to write several seismograms into one file, use
pysmo.lib.io.write_mseed directly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
Destination file path. Any existing content is overwritten. |
required |
Source code in src/pysmo/classes/_mseed.py
QuakeML
Import class for FDSN QuakeML event metadata.
Reads the hypocentre and origin time of a seismic event from a
QuakeML 1.2 document (as returned by any fdsnws-event service) and
exposes it as an Event-compatible object. A QuakeML
document commonly describes many events;
from_bytes narrows to one,
all_from_bytes returns every
event found.
Only the preferred origin's hypocentre and time are read. Focal mechanisms, picks, arrivals, origin uncertainties and competing origin/magnitude solutions in the document are not represented.
An object satisfying the full Station or
Event protocol for another data source is built
separately (e.g. a MiniEvent, or via
clone_to_mini); QuakeML does not
fabricate one.
Examples:
>>> from pysmo.classes import QuakeML
>>> xml = b'''<?xml version="1.0"?>
... <q:quakeml xmlns="http://quakeml.org/xmlns/bed/1.2"
... xmlns:q="http://quakeml.org/xmlns/quakeml/1.2">
... <eventParameters publicID="smi:example/catalogue">
... <event publicID="smi:example/event/1">
... <description><text>Example</text></description>
... <origin publicID="smi:example/origin/1">
... <time><value>2010-02-27T06:34:11.53Z</value></time>
... <latitude><value>-36.122</value></latitude>
... <longitude><value>-72.898</value></longitude>
... <depth><value>22900</value></depth>
... </origin>
... <magnitude publicID="smi:example/magnitude/1">
... <mag><value>8.8</value></mag>
... <type>Mw</type>
... </magnitude>
... <type>earthquake</type>
... </event>
... </eventParameters>
... </q:quakeml>'''
>>> event = QuakeML.from_bytes(xml)
>>> event.latitude, event.longitude, event.depth
(-36.122, -72.898, 22900.0)
>>> event.magnitude, event.magnitude_type
(8.8, 'Mw')
>>> event.public_id
'smi:example/event/1'
>>>
Methods:
| Name | Description |
|---|---|
all_from_bytes |
Create one instance per |
all_from_query |
Fetch and parse a catalogue of events from the USGS fdsnws-event service. |
fetch |
Fetch and parse a single event from the USGS fdsnws-event service. |
from_bytes |
Create a new instance from a QuakeML document, narrowing to one event. |
Attributes:
| Name | Type | Description |
|---|---|---|
depth |
float
|
Hypocentre depth in metres, positive downwards, as recorded in the |
description |
str | None
|
First |
event_type |
str | None
|
QuakeML |
latitude |
float
|
Event latitude from -90 to 90 degrees. |
longitude |
float
|
Event longitude from -180 to 180 degrees (-180 is stored as +180). |
magnitude |
float | None
|
Preferred magnitude value, or |
magnitude_type |
str | None
|
Preferred magnitude type (e.g. |
public_id |
str
|
QuakeML |
time |
UtcTimestamp
|
Event origin time. |
Source code in src/pysmo/classes/_quakeml.py
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 | |
depth
class-attribute
instance-attribute
depth: float = field(
converter=float,
on_setattr=setters.pipe(
setters.convert, setters.validate
),
)
Hypocentre depth in metres, positive downwards, as recorded in the
source catalogue — relative to sea level; may be negative for events
above sea level. (The datum detail lives here, not on
Event.depth, because it is format-specific.)
description
class-attribute
instance-attribute
First event/description/text (e.g. a Flinn-Engdahl region or event
name), or None.
event_type
class-attribute
instance-attribute
QuakeML event/type (e.g. "earthquake", "explosion"), or None.
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=convert_to_longitude,
validator=[validators.gt(-180), validators.le(180)],
on_setattr=setters.pipe(
setters.convert, setters.validate
),
)
Event longitude from -180 to 180 degrees (-180 is stored as +180).
magnitude
class-attribute
instance-attribute
magnitude: float | None = field(
default=None, converter=converters.optional(float)
)
Preferred magnitude value, or None if the document has none.
magnitude_type
class-attribute
instance-attribute
Preferred magnitude type (e.g. "Mw"), or None.
public_id
class-attribute
instance-attribute
public_id: str = field(
validator=validators.instance_of(str),
on_setattr=setters.validate,
)
QuakeML publicID of the event this instance was parsed from,
preserved verbatim. It is a dependable unique key for records from one
catalogue, but not a canonical per-earthquake key across a catalogue
merged from several sources (each agency assigns its own). Parse-time
provenance: not updated when other attributes change.
time
class-attribute
instance-attribute
time: UtcTimestamp = field(
converter=convert_to_utc_timestamp,
on_setattr=setters.pipe(
setters.convert, setters.validate
),
)
Event origin time.
all_from_bytes
classmethod
Create one instance per <event> in a QuakeML document.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
xml
|
bytes
|
Raw QuakeML 1.2 document bytes. |
required |
strict
|
bool
|
If |
True
|
Returns:
| Type | Description |
|---|---|
list[Self]
|
One QuakeML instance per representable event, in document order. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/pysmo/classes/_quakeml.py
all_from_query
classmethod
all_from_query(
*,
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,
strict: bool = True
) -> list[Self]
Fetch and parse a catalogue of events from the USGS fdsnws-event service.
A one-step convenience over
pysmo.tools.web.fetch_quakeml followed by
all_from_bytes. All
parameters other than strict are those of fetch_quakeml, with
the same meanings; mindepth_km / maxdepth_km are in
kilometres while the parsed depth is
in metres.
strict (default True) matches
all_from_bytes: pass
False for a broad query where a few unrepresentable events should
be skipped (with a UserWarning) rather than discarding the whole
catalogue.
Returns:
| Type | Description |
|---|---|
list[Self]
|
One QuakeML instance per representable event, in the service's order. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the response cannot be parsed, or — when |
ResponseError
|
If the event web service returns an HTTP error, including a 404 when nothing matches. |
Source code in src/pysmo/classes/_quakeml.py
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 | |
fetch
classmethod
Fetch and parse a single event from the USGS fdsnws-event service.
Fetches exactly one event by the service's event id. To fetch a
catalogue, use
all_from_query; to fetch
once and parse later (e.g. offline), use
pysmo.tools.web.fetch_quakeml with
from_bytes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_id
|
str
|
The service's event id. |
required |
Returns:
| Type | Description |
|---|---|
Self
|
A new QuakeML instance for the fetched event. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the response cannot be parsed or does not describe exactly one event. |
ResponseError
|
If the event web service returns an HTTP error. |
Source code in src/pysmo/classes/_quakeml.py
from_bytes
classmethod
Create a new instance from a QuakeML document, narrowing to one event.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
xml
|
bytes
|
Raw QuakeML 1.2 document bytes. |
required |
event_id
|
str | None
|
Event to select when |
None
|
strict
|
bool
|
If |
True
|
Returns:
| Type | Description |
|---|---|
Self
|
A new QuakeML instance for the selected event. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
See Also
QuakeML.all_from_bytes:
Return every event in the document without narrowing to one.
Source code in src/pysmo/classes/_quakeml.py
SAC
Access and modify data stored in SAC files.
SAC wraps a SacIO instance
and adds attributes alongside it that allow using pysmo types. The extra
attributes are themselves instances of "helper" classes that should not
be instantiated directly.
Examples:
SAC instances are typically created by reading a SAC file:
>>> from pysmo.classes import SAC
>>> sac = SAC.from_file("example.sac")
>>> sac.seismogram.delta
Timedelta('0 days 00:00:00.050000000')
>>> sac.seismogram.data
array([-47201., -47361., -47511., ..., -82144., -71072., -59960.],
shape=(57465,))
>>>
Raw SAC header values are not compatible with pysmo types. For
example, event coordinates are stored in the
evla and evlo
headers, which do not match the pysmo Location
type. Renaming or aliasing evla to latitude and evlo to
longitude would solve the problem for the event coordinates, but
since the SAC format also specifies station coordinates
(stla, stlo),
the same compatibility issue remains.
The SAC class solves this with helper classes
that map these incompatible attributes to ones compatible with pysmo
types, accessible under different names:
>>> from pysmo import Seismogram
>>>
>>> def sample_count(seismogram: Seismogram) -> int:
... return len(seismogram.data)
...
>>> # A bare SAC instance is not a Seismogram: a type checker rejects
>>> # this, and at runtime the function fails on the missing member:
>>> sample_count(sac)
Traceback (most recent call last):
...
AttributeError: 'SAC' object has no attribute 'data'
>>> # The sac.seismogram helper is a Seismogram:
>>> sample_count(sac.seismogram)
57465
>>>
Because the SAC file format defines a large number of header fields
for metadata, many of them are optional. Since the helper classes
are more specific (and intended to be used with pysmo types), their
attributes typically may not be None:
>>> # No error: a SAC file doesn't have to contain event information:
>>> sac.native.evla = None
>>>
A curated surface, not the full header set
SAC only exposes a small, curated surface
directly (file I/O, and the pysmo-typed
station,
event,
seismogram and
timestamps helpers) rather than
the full raw SAC header set. Seismogram data and sampling interval
are available via seismogram.
Users familiar with the SAC file format who want direct access to a
header by its native name (e.g. evla, stla, kstnm) can reach
the underlying SacIO instance via
SAC.native.
Methods:
| Name | Description |
|---|---|
all_from_zip |
Create one instance per SAC file in a zip archive. |
fetch |
Fetch and parse a SAC seismogram from the EarthScope FDSN dataselect web service, for an absolute time window. |
from_bytes |
Create a new SAC instance from SAC file content as bytes. |
from_file |
Create a new SAC instance from a SAC file. |
from_zip |
Create a new instance from a zip archive containing exactly one continuous SAC segment. |
read |
Read data and headers from a SAC file into an existing SAC instance. |
read_bytes |
Read SAC file content as bytes into an existing SAC instance. |
write |
Write data and header values to a SAC file. |
Attributes:
| Name | Type | Description |
|---|---|---|
event |
SacEvent
|
This SAC object exposed as an |
native |
SacIO
|
The underlying |
seismogram |
SacSeismogram
|
This SAC object exposed as a |
station |
SacStation
|
This SAC object exposed as a |
timestamps |
SacTimestamps
|
Maps SAC time headers such as B, E, O, T0-T9 to |
Source code in src/pysmo/classes/_sac.py
587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 | |
event
class-attribute
instance-attribute
This SAC object exposed as an Event.
native
class-attribute
instance-attribute
The underlying SacIO instance.
This is the escape hatch for direct access to raw SAC headers by their
native names (e.g. SAC.native.evla), for users familiar with the SAC file
format who need it.
Fixed for the lifetime of the instance: seismogram,
station, event
and timestamps are bound to this object
at construction time, so reassigning it would silently orphan them. To
load different data into an existing instance, use
read/read_bytes,
which update this same object in place; otherwise construct a new
SAC instance.
seismogram
class-attribute
instance-attribute
seismogram: SacSeismogram = field(init=False)
This SAC object exposed as a Seismogram.
station
class-attribute
instance-attribute
station: SacStation = field(init=False)
This SAC object exposed as a Station.
timestamps
class-attribute
instance-attribute
timestamps: SacTimestamps = field(init=False)
Maps SAC time headers such as B, E, O, T0-T9 to
Timestamp objects.
all_from_zip
classmethod
Create one instance per SAC file in a zip archive.
Unlike from_zip, this does not
require exactly one segment — a response covering a data gap, an
instrument/metadata epoch change, or a wildcarded channel/location
code returns several, which callers can inspect or merge
themselves.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
archive
|
bytes
|
Raw zip archive bytes, as returned by the FDSN
dataselect web service with |
required |
Returns:
| Type | Description |
|---|---|
list[Self]
|
One SAC instance per member of the archive, in archive order. |
list[Self]
|
Empty if the archive has no members. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/pysmo/classes/_sac.py
fetch
classmethod
Fetch and parse a SAC seismogram from the EarthScope FDSN dataselect web service, for an absolute time window.
For a window relative to a predicted phase arrival instead, compute
the window yourself (e.g. with
pysmo.tools.traveltime.travel_times, which shows exactly this
in its own Examples) and pass the resulting starttime/endtime
here.
To fetch once and interpret later (e.g. offline, or without
repeating the network request), use
pysmo.tools.web.fetch_sac and
from_zip /
all_from_zip directly instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
station
|
Station
|
Any object satisfying the |
required |
starttime
|
Timestamp
|
Start of the requested time window (UTC). |
required |
endtime
|
Timestamp
|
End of the requested time window (UTC). |
required |
Returns:
| Type | Description |
|---|---|
Self
|
A new SAC instance. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no waveform data is returned for the given window, if more than one continuous segment is returned (e.g. due to a data gap, an instrument/metadata epoch change, overlapping records, or a wildcarded channel/ location code matching more than one channel), or if a returned segment cannot be parsed as a SAC file. |
ResponseError
|
If the dataselect web service returns an HTTP error. |
Examples:
>>> import pandas as pd
>>> from pysmo import MiniStation
>>> from pysmo.classes import SAC
>>> station = MiniStation(
... name="ANMO", network="IU", location="00", channel="LHZ",
... latitude=34.945981, longitude=-106.457133,
... )
>>> sac = SAC.fetch(
... station=station,
... starttime=pd.Timestamp("2010-02-27T06:44:00Z"),
... endtime=pd.Timestamp("2010-02-27T06:54:00Z"),
... )
>>>
Source code in src/pysmo/classes/_sac.py
from_bytes
classmethod
Create a new SAC instance from SAC file content as bytes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
bytes
|
Raw bytes of a SAC file. |
required |
Returns:
| Type | Description |
|---|---|
Self
|
A new SAC instance. |
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
If the data isn't evenly-spaced
time-series data (IFTYPE=ITIME, LEVEN=True). Use
|
Source code in src/pysmo/classes/_sac.py
from_file
classmethod
Create a new SAC instance from a SAC file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str | PathLike[str]
|
Name of the SAC file to read. |
required |
Returns:
| Type | Description |
|---|---|
Self
|
A new SAC instance. |
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
If the file isn't evenly-spaced time-series
data (IFTYPE=ITIME, LEVEN=True). Use
|
Source code in src/pysmo/classes/_sac.py
from_zip
classmethod
Create a new instance from a zip archive containing exactly one continuous SAC segment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
archive
|
bytes
|
Raw zip archive bytes containing exactly one SAC file
(as returned by the FDSN dataselect web service with
|
required |
Returns:
| Type | Description |
|---|---|
Self
|
A new SAC instance. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
See Also
SAC.all_from_zip: Parse
every segment in the archive without requiring exactly one.
Source code in src/pysmo/classes/_sac.py
read
Read data and headers from a SAC file into an existing SAC instance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str | PathLike[str]
|
Name of the SAC file to read. |
required |
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
If the file isn't evenly-spaced time-series data (IFTYPE=ITIME, LEVEN=True); the existing instance is left unchanged in this case. |
Source code in src/pysmo/classes/_sac.py
read_bytes
read_bytes(data: bytes) -> None
Read SAC file content as bytes into an existing SAC instance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
bytes
|
Raw bytes of a SAC file. |
required |
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
If the data isn't evenly-spaced time-series data (IFTYPE=ITIME, LEVEN=True); the existing instance is left unchanged in this case. |
Source code in src/pysmo/classes/_sac.py
SacEvent
Bases: _SacNested
Helper class for SAC event attributes.
The SacEvent class maps SAC attributes to match the pysmo
Event type. An instance is created for each new
SAC instance.
Examples:
A SacEvent can be passed to any function that expects the pysmo
Event type:
>>> from pysmo.classes import SAC
>>> from pysmo import Event
>>>
>>> def origin_isoformat(event: Event) -> str:
... return event.time.isoformat()
...
>>> sac = SAC.from_file("example.sac")
>>> origin_isoformat(sac.event)
'2010-02-27T06:34:11.529998536+00:00'
>>>
Event information is optional
Not all SAC files contain event information.
Attributes:
| Name | Type | Description |
|---|---|---|
depth |
int | float
|
Event depth in metres (positive downward from the surface). |
latitude |
int | float
|
Event latitude. |
longitude |
int | float
|
Event longitude. |
time |
UtcTimestamp
|
Event origin time (UTC). |
Source code in src/pysmo/classes/_sac.py
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 | |
depth
property
writable
Event depth in metres (positive downward from the surface).
time
property
writable
time: UtcTimestamp
Event origin time (UTC).
Fixed when iztype is "o"
This property uses the SacIO.o time
header. If SacIO.iztype is "o",
SacIO.o is the reference-time equivalence and is fixed at 0,
so time cannot be changed
directly in that case.
SacPZ
Import class for SAC PZ (pole-zero) files.
Reads an analog instrument response from a
SAC PZ
file (as produced by e.g. EarthScope's fdsnws-station service) and
exposes it as a Response-compatible object. SacPZ only ever
satisfies Response, never
StagedResponse — the SAC PZ format has no
digital-stage fields to parse.
Examples:
>>> from pysmo.classes import SacPZ
>>> text = '''\
... * NETWORK (KNETWK): IU
... * STATION (KSTNM): ANMO
... * LOCATION (KHOLE): 00
... * CHANNEL (KCMPNM): BHZ
... * START : 2018-07-09T20:45:00
... * END :
... * INPUT UNIT : M
... ZEROS 2
... \t+0.000000e+00\t+0.000000e+00
... \t+0.000000e+00\t+0.000000e+00
... POLES 1
... \t-1.000000e-02\t+0.000000e+00
... CONSTANT 1.0e+09
... '''
>>> response = SacPZ.from_text(text)
>>> response.network, response.station
('IU', 'ANMO')
>>>
Methods:
| Name | Description |
|---|---|
all_from_text |
Create one instance per record in a bulk/concatenated SAC PZ text body. |
fetch |
Fetch and parse an instrument response as SAC PZ from EarthScope's fdsnws-station service, selecting one epoch. |
from_text |
Create a new instance from a single-record SAC PZ text body. |
Attributes:
| Name | Type | Description |
|---|---|---|
channel |
str
|
Channel code parsed from the SAC PZ file's comment header. |
end_date |
Timestamp | None
|
End of the epoch this response applies to, or |
input_units |
str
|
Physical units produced by removing this response via full spectral |
location |
str
|
Location code parsed from the SAC PZ file's comment header. |
network |
str
|
Network code parsed from the SAC PZ file's comment header. |
overall_sensitivity |
NonZeroNumber
|
Total system sensitivity (the SAC PZ file's |
poles |
list[complex]
|
Response poles. |
reference_sensitivity |
NonZeroNumber | None
|
Total system sensitivity at the reference frequency, |
start_date |
Timestamp
|
Start of the epoch this response applies to. |
station |
str
|
Station code parsed from the SAC PZ file's comment header. |
zeros |
list[complex]
|
Response zeros. |
Source code in src/pysmo/classes/_sacpz.py
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | |
channel
class-attribute
instance-attribute
channel: str = field(validator=validators.instance_of(str))
Channel code parsed from the SAC PZ file's comment header.
end_date
class-attribute
instance-attribute
end_date: Timestamp | None = field(
default=None,
converter=converters.optional(convert_to_utc_timestamp),
)
End of the epoch this response applies to, or None if still open.
input_units
class-attribute
instance-attribute
input_units: str = field(
validator=validators.instance_of(str)
)
Physical units produced by removing this response via full spectral
deconvolution — not necessarily via the sensitivity-only path, see
remove_response for why.
See Response.input_units for more details.
location
class-attribute
instance-attribute
location: str = field(validator=validators.instance_of(str))
Location code parsed from the SAC PZ file's comment header.
network
class-attribute
instance-attribute
network: str = field(validator=validators.instance_of(str))
Network code parsed from the SAC PZ file's comment header.
overall_sensitivity
class-attribute
instance-attribute
overall_sensitivity: NonZeroNumber = field(
converter=float, validator=validate_nonzero
)
Total system sensitivity (the SAC PZ file's CONSTANT).
See Response.overall_sensitivity
for more details.
poles
class-attribute
instance-attribute
poles: list[complex] = field(
converter=convert_to_complex_list
)
reference_sensitivity
class-attribute
instance-attribute
reference_sensitivity: NonZeroNumber | None = field(
default=None,
converter=_convert_optional_float,
validator=validators.optional(validate_nonzero),
)
Total system sensitivity at the reference frequency, A0 excluded
(the SAC PZ file's SENSITIVITY header, if present).
See
Response.reference_sensitivity
for more details.
start_date
class-attribute
instance-attribute
start_date: Timestamp = field(
converter=convert_to_utc_timestamp
)
Start of the epoch this response applies to.
station
class-attribute
instance-attribute
station: str = field(validator=validators.instance_of(str))
Station code parsed from the SAC PZ file's comment header.
zeros
class-attribute
instance-attribute
zeros: list[complex] = field(
converter=convert_to_complex_list
)
all_from_text
classmethod
Create one instance per record in a bulk/concatenated SAC PZ text body.
Unlike from_text, this does not
require (or merge to) a single record — a SACPZ retrieval that is
not pinned to a single channel epoch returns multiple concatenated
records, each with its own network/station/location/channel/
start_date/end_date provenance, which callers can filter
themselves.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
text
|
str
|
SAC PZ text containing one or more records. |
required |
Returns:
| Type | Description |
|---|---|
list[Self]
|
One SacPZ instance per record found, in order of appearance. |
Source code in src/pysmo/classes/_sacpz.py
fetch
classmethod
Fetch and parse an instrument response as SAC PZ from EarthScope's fdsnws-station service, selecting one epoch.
The response comes from fdsnws-station with
level=response&format=sacpz, EarthScope's designated replacement
for the irisws-sacpz service.
Unlike StationXML.fetch, epoch
selection happens server-side: the web service's time parameter
is passed through, so exactly one record is returned (the epoch
active at time if given, otherwise the one currently open)
without needing to fetch the full response history first.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
station
|
Station
|
Any object satisfying the |
required |
time
|
Timestamp | None
|
Timestamp used to select the response epoch. If |
None
|
Returns:
| Type | Description |
|---|---|
Self
|
A new SacPZ instance for the response epoch active at time |
Self
|
(or currently open, if |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the web service's response does not contain exactly one SAC PZ record. |
ResponseError
|
If the web service returns an HTTP error. |
Prefer StationXML for live fetches
When fetching live from EarthScope rather than reading an
existing SAC PZ file, prefer
StationXML.fetch:
it also captures digital FIR/IIR stages, so it always satisfies
StagedResponse, unlike SacPZ.
Examples:
>>> from pysmo import MiniStation
>>> from pysmo.classes import SacPZ
>>> station = MiniStation(
... name="ANMO", network="IU", location="00", channel="BHZ",
... latitude=34.945981, longitude=-106.457133,
... )
>>> response = SacPZ.fetch(station=station)
>>>
Source code in src/pysmo/classes/_sacpz.py
from_text
classmethod
Create a new instance from a single-record SAC PZ text body.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
text
|
str
|
SAC PZ text containing exactly one record (the common
sidecar-file case, e.g. one |
required |
Returns:
| Type | Description |
|---|---|
Self
|
A new SacPZ instance. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the text contains zero or more than one SAC PZ record. |
See Also
SacPZ.all_from_text: Parse
a bulk/concatenated multi-record text body.
Examples:
Reading a SAC PZ file already saved to disk — the common case for
archived/legacy data, e.g. extracted from an old SEED volume with
rdseed -p, rather than fetched live from EarthScope:
>>> from pathlib import Path
>>> from pysmo.classes import SacPZ
>>> text = Path("SACPZ.IU.ANMO.00.BHZ").read_text()
>>> response = SacPZ.from_text(text)
>>> response.network, response.station
('IU', 'ANMO')
>>>
Source code in src/pysmo/classes/_sacpz.py
SacSeismogram
Bases: _SacNested, SeismogramEndtimeMixin
Helper class for SAC seismogram attributes.
The SacSeismogram class maps SAC attributes to match the pysmo
Seismogram type. An instance is created for each
new SAC instance.
Examples:
A SacSeismogram can be passed to any function that expects the pysmo
Seismogram type:
>>> from pysmo import Seismogram
>>> from pysmo.classes import SAC
>>>
>>> def begin_time_isoformat(seismogram: Seismogram) -> str:
... return seismogram.begin_time.isoformat()
...
>>> sac = SAC.from_file("example.sac")
>>> begin_time_isoformat(sac.seismogram)
'2010-02-27T06:44:06.069538+00:00'
>>>
Timing operations in a SAC file use a reference time, and all times
(begin time, event origin time, picks, etc.) are relative to this
reference time. In pysmo only absolute times are used. The example
below shows the begin_time is the absolute time (in UTC) of the first
data point:
Attributes:
| Name | Type | Description |
|---|---|---|
begin_time |
UtcTimestamp
|
Seismogram begin time. |
data |
NDArray[floating]
|
Seismogram data. |
delta |
PositiveTimedelta
|
Sampling interval. |
Source code in src/pysmo/classes/_sac.py
SacStation
Bases: _SacNested
Helper class for SAC station attributes.
The SacStation class maps SAC attributes to match the pysmo
Station type. An instance is created for each new
SAC instance.
Examples:
A SacStation can be passed to any function that expects the pysmo
Station type:
>>> from pysmo.classes import SAC
>>> from pysmo import Station
>>>
>>> def station_id(station: Station) -> str:
... return f"{station.network}.{station.name}"
...
>>> sac = SAC.from_file("example.sac")
>>> station_id(sac.station)
'IU.ANMO'
>>>
Attributes:
| Name | Type | Description |
|---|---|---|
channel |
str
|
Channel code. |
elevation |
int | float | None
|
Station elevation in metres. |
latitude |
int | float
|
Station latitude. |
location |
str
|
Location code. |
longitude |
int | float
|
Station longitude. |
name |
str
|
Station name or code. |
network |
str
|
Network name or code. |
Source code in src/pysmo/classes/_sac.py
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | |
location
property
writable
location: str
Location code.
Unlike the other station identifiers, a missing location code
(khole not set) is common in real-world SAC files and is not
treated as an error - it is returned as an empty string.
SacTimestamps
Bases: _SacNested
Helper class to access times stored in SAC headers as Timestamp objects.
The SacTimestamps class maps raw SAC time headers — relative to a
file's own reference time — to absolute Timestamp
objects. An instance of this class is created for each new
SAC instance.
Examples:
Relative seismogram begin time as a float vs absolute begin time
as a Timestamp object.
>>> from pysmo.classes import SAC
>>> sac = SAC.from_file("example.sac")
>>>
>>> # SAC header "B" as stored in a SAC file
>>> sac.native.b
0.0005380000220611691
>>>
>>> # the output above is the number of seconds relative
>>> # to the reference time and date:
>>> sac.native.kzdate , sac.native.kztime
('2010-02-27', '06:44:06.069')
>>>
>>> # Accessing the same SAC header via a `SacTimestamps` object
>>> # yields a corresponding Timestamp object with the absolute time:
>>> sac.timestamps.b
Timestamp('2010-02-27 06:44:06.069538+0000', tz='UTC')
>>>
Changing timestamp values:
>>> import pandas as pd
>>> sac = SAC.from_file("example.sac")
>>>
>>> # Original value of the "B" SAC header:
>>> sac.native.b
0.0005380000220611691
>>>
>>> # Add 30 seconds to the absolute time:
>>> sac.timestamps.b += pd.Timedelta(seconds=30)
>>>
>>> # The relative time also changes by the same amount:
>>> sac.native.b
30.000538
>>>
>>> # Changing b to None is not allowed (it is a required time header):
>>> sac.timestamps.b = None
Traceback (most recent call last):
...
TypeError: ...
>>>
Attributes:
| Name | Type | Description |
|---|---|---|
a |
OptionalSacTimestamp
|
First arrival time. |
b |
RequiredSacTimestamp
|
Beginning time of the independent variable. |
e |
RequiredSacTimestamp
|
Ending time of the independent variable (read-only). |
f |
OptionalSacTimestamp
|
Fini or end of event time. |
o |
OptionalSacTimestamp
|
Event origin time. |
t0 |
OptionalSacTimestamp
|
User defined time pick or marker 0. |
t1 |
OptionalSacTimestamp
|
User defined time pick or marker 1. |
t2 |
OptionalSacTimestamp
|
User defined time pick or marker 2. |
t3 |
OptionalSacTimestamp
|
User defined time pick or marker 3. |
t4 |
OptionalSacTimestamp
|
User defined time pick or marker 4. |
t5 |
OptionalSacTimestamp
|
User defined time pick or marker 5. |
t6 |
OptionalSacTimestamp
|
User defined time pick or marker 6. |
t7 |
OptionalSacTimestamp
|
User defined time pick or marker 7. |
t8 |
OptionalSacTimestamp
|
User defined time pick or marker 8. |
t9 |
OptionalSacTimestamp
|
User defined time pick or marker 9. |
Source code in src/pysmo/classes/_sac.py
481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 | |
a
class-attribute
instance-attribute
First arrival time.
b
class-attribute
instance-attribute
Beginning time of the independent variable.
e
class-attribute
instance-attribute
Ending time of the independent variable (read-only).
f
class-attribute
instance-attribute
Fini or end of event time.
o
class-attribute
instance-attribute
Event origin time.
t0
class-attribute
instance-attribute
User defined time pick or marker 0.
t1
class-attribute
instance-attribute
User defined time pick or marker 1.
t2
class-attribute
instance-attribute
User defined time pick or marker 2.
t3
class-attribute
instance-attribute
User defined time pick or marker 3.
t4
class-attribute
instance-attribute
User defined time pick or marker 4.
t5
class-attribute
instance-attribute
User defined time pick or marker 5.
t6
class-attribute
instance-attribute
User defined time pick or marker 6.
t7
class-attribute
instance-attribute
User defined time pick or marker 7.
t8
class-attribute
instance-attribute
User defined time pick or marker 8.
StationXML
Import class for FDSN StationXML station metadata.
Reads one <Channel> epoch from a
FDSN StationXML document and exposes
it as a Station-compatible object: NSLC identity,
coordinates, the epoch's validity window, and — when the document was
fetched at level=response — the instrument
response.
A document commonly covers a channel's full history, i.e. several
epochs. from_bytes narrows to
one (matching a time, or the currently-open one);
all_from_bytes returns every
epoch found. Accessing
response raises for an epoch
parsed from a level=channel / level=station document (e.g. a bulk
inventory fetched with
pysmo.tools.web.fetch_station_inventory) — guard it with
has_response.
fetch always populates it.
Examples:
>>> from pysmo.classes import StationXML
>>> xml = b'''\
... <?xml version="1.0"?>
... <FDSNStationXML xmlns="http://www.fdsn.org/xml/station/1">
... <Network code="IU">
... <Station code="ANMO">
... <Latitude>34.9</Latitude><Longitude>-106.5</Longitude>
... <Channel code="BHZ" locationCode="00"
... startDate="2018-07-09T20:45:00.0000">
... <Latitude>34.945981</Latitude><Longitude>-106.457133</Longitude>
... <Elevation>1632.7</Elevation>
... <Response>
... <InstrumentSensitivity>
... <Value>1.98475E9</Value>
... <InputUnits><Name>m/s</Name></InputUnits>
... </InstrumentSensitivity>
... <Stage number="1">
... <PolesZeros>
... <PzTransferFunctionType>LAPLACE (RADIANS/SECOND)</PzTransferFunctionType>
... <NormalizationFactor>5.03773E14</NormalizationFactor>
... <Zero number="0"><Real>0.0</Real><Imaginary>0.0</Imaginary></Zero>
... <Pole number="0"><Real>-0.037</Real><Imaginary>0.037</Imaginary></Pole>
... </PolesZeros>
... <Decimation><InputSampleRate>40.0</InputSampleRate><Factor>1</Factor></Decimation>
... </Stage>
... </Response>
... </Channel>
... </Station>
... </Network>
... </FDSNStationXML>'''
>>> station = StationXML.from_bytes(xml)
>>> station.network, station.name, station.channel
('IU', 'ANMO', 'BHZ')
>>> station.response.input_units
'm/s'
>>>
Methods:
| Name | Description |
|---|---|
all_from_bytes |
Create one instance per |
fetch |
Fetch one channel's response epoch from the EarthScope FDSN station web service. |
from_bytes |
Create a new instance from a StationXML document, selecting one epoch. |
Attributes:
| Name | Type | Description |
|---|---|---|
channel |
str
|
Channel code (empty for a |
elevation |
float | None
|
Elevation in metres, or |
end_date |
Timestamp | None
|
End of this metadata epoch, or |
has_response |
bool
|
Whether this epoch carries an instrument response. |
latitude |
float
|
Latitude in degrees. |
location |
str
|
Location code (empty for a |
longitude |
float
|
Longitude in degrees. |
name |
str
|
Station code. |
network |
str
|
Network code. |
response |
MiniStagedResponse
|
This epoch's instrument response. |
start_date |
Timestamp
|
Start of this metadata epoch. |
Source code in src/pysmo/classes/_stationxml.py
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 | |
channel
class-attribute
instance-attribute
channel: str = field(validator=validators.instance_of(str))
Channel code (empty for a level=station epoch).
elevation
class-attribute
instance-attribute
elevation: float | None = field(
default=None, converter=converters.optional(float)
)
Elevation in metres, or None if the document omits it.
end_date
class-attribute
instance-attribute
end_date: Timestamp | None = field(
default=None,
converter=converters.optional(convert_to_utc_timestamp),
)
End of this metadata epoch, or None if still open.
has_response
property
has_response: bool
Whether this epoch carries an instrument response.
Guard response with this when
an epoch might have come from a level=channel / level=station
document (e.g. a bulk inventory).
latitude
class-attribute
instance-attribute
Latitude in degrees.
location
class-attribute
instance-attribute
location: str = field(validator=validators.instance_of(str))
Location code (empty for a level=station epoch).
longitude
class-attribute
instance-attribute
Longitude in degrees.
name
class-attribute
instance-attribute
name: str = field(validator=validators.instance_of(str))
Station code.
network
class-attribute
instance-attribute
network: str = field(validator=validators.instance_of(str))
Network code.
response
property
response: MiniStagedResponse
This epoch's instrument response.
Satisfies Response and
StagedResponse (stages is empty for a
document with no digital decimation stages).
Raises:
| Type | Description |
|---|---|
ValueError
|
If this epoch was parsed from a document with no
|
start_date
class-attribute
instance-attribute
start_date: Timestamp = field(
converter=convert_to_utc_timestamp
)
Start of this metadata epoch.
all_from_bytes
classmethod
Create one instance per <Channel> epoch in a StationXML document.
Unlike from_bytes, this does
not narrow — a document covering a channel's full history returns
several, each with its own NSLC / start_date / end_date.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
xml
|
bytes
|
Raw StationXML document bytes. |
required |
Returns:
| Type | Description |
|---|---|
list[Self]
|
One StationXML instance per epoch found, in document order. |
Source code in src/pysmo/classes/_stationxml.py
fetch
classmethod
Fetch one channel's response epoch from the EarthScope FDSN station web service.
Fetches the full response history for the channel in one
level=response request and narrows client-side to the epoch active
at time (or the currently-open one). To fetch once and interpret
later, use pysmo.tools.web.fetch_stationxml with
from_bytes /
all_from_bytes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
station
|
Station
|
Any object satisfying the |
required |
time
|
Timestamp | None
|
Timestamp used to select the epoch. If |
None
|
Returns:
| Type | Description |
|---|---|
Self
|
A new StationXML instance with |
Raises:
| Type | Description |
|---|---|
ValueError
|
If zero or more than one epoch matches time, or if
the fetched document carries no |
ResponseError
|
If the station web service returns an HTTP error. |
Examples:
>>> from pysmo import MiniStation
>>> from pysmo.classes import StationXML
>>> station = MiniStation(
... name="ANMO", network="IU", location="00", channel="BHZ",
... latitude=34.945981, longitude=-106.457133,
... )
>>> epoch = StationXML.fetch(station=station)
>>> epoch.has_response
True
>>>
Source code in src/pysmo/classes/_stationxml.py
from_bytes
classmethod
from_bytes(
xml: bytes,
*,
time: Timestamp | None = None,
network: str | None = None,
station: str | None = None,
location: str | None = None,
channel: str | None = None
) -> Self
Create a new instance from a StationXML document, selecting one epoch.
A document is not guaranteed to cover a single channel — a bulk or
wildcard query can cover several networks and stations, each with
every location/channel combination and its own epoch history.
network/station/location/channel narrow to one before time
is applied; without them, a document covering more than one raises
the same "more than one epoch" error as an ambiguous time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
xml
|
bytes
|
Raw StationXML document bytes. |
required |
time
|
Timestamp | None
|
Timestamp used to select the epoch. If |
None
|
network
|
str | None
|
Network code to narrow to, if |
None
|
station
|
str | None
|
Station code to narrow to, if |
None
|
location
|
str | None
|
Location code to narrow to, if |
None
|
channel
|
str | None
|
Channel code to narrow to, if |
None
|
Returns:
| Type | Description |
|---|---|
Self
|
A new StationXML instance for the epoch active at time (or |
Self
|
currently open, if time is |
Raises:
| Type | Description |
|---|---|
ValueError
|
If, after narrowing, zero or more than one epoch
matches time (or "currently open", if time is |
See Also
StationXML.all_from_bytes:
Parse every epoch in the document without narrowing to one.
Source code in src/pysmo/classes/_stationxml.py
resolve_epochs
resolve_epochs(
epochs: Iterable[StationXML], time: Timestamp
) -> list[StationXML]
Collapse station epochs to the one per NSLC valid at a given time.
Groups epochs by network/station/location/channel and, within each
group, keeps the single epoch whose [start_date, end_date) window
covers time (an epoch with no end_date is still open and covers any
time at or after its start_date). An NSLC with no covering epoch is
dropped — that station provably was not recording then.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
epochs
|
Iterable[StationXML]
|
Station epochs, e.g. from
|
required |
time
|
Timestamp
|
The time each NSLC's metadata is resolved at (UTC). |
required |
Returns:
| Type | Description |
|---|---|
list[StationXML]
|
One |
list[StationXML]
|
NSLC order. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If an NSLC has more than one epoch covering |