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 (network/station/location/channel/
start_date/end_date) needed to select the right response from a document —
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. |
SAC |
Access and modify data stored in SAC files. |
SacEvent |
Helper class for SAC event attributes. |
SacPZ |
Import/export 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 response metadata. |
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 import Seismogram
>>> 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)
>>> isinstance(seismogram, Seismogram)
True
>>> seismogram.sid
'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.sid
'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
|
Seismogram data. |
delta |
PositiveTimedelta
|
Seismogram sampling interval. |
sample_count |
int
|
Number of samples, always equal to |
sid |
str
|
FDSN source identifier of the parsed GeoCSV data (e.g. |
Source code in src/pysmo/classes/_geocsv.py
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 | |
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 = field(
converter=convert_to_ndarray,
validator=validators.instance_of(np.ndarray),
on_setattr=setters.pipe(
setters.convert, setters.validate
),
)
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.
sid
class-attribute
instance-attribute
sid: str = field(
validator=validators.instance_of(str),
on_setattr=setters.validate,
)
FDSN source identifier of the parsed GeoCSV data (e.g. IU_ANMO_00_LHZ).
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.web.fetch_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"),
... ) # doctest: +SKIP
>>>
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
|
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.sid == seismogram.sid
True
>>>
Source code in src/pysmo/classes/_geocsv.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:
>>> # Import the Seismogram type to check if the nested class is compatible:
>>> from pysmo import Seismogram
>>>
>>> # First verify that a SAC instance is not a pysmo Seismogram:
>>> isinstance(sac, Seismogram)
False
>>> # The sac.seismogram object is, however:
>>> isinstance(sac.seismogram, Seismogram)
True
>>>
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
>>>
Tip
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_buffer |
Create a new SAC instance from a SAC data buffer. |
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_buffer |
Read data and headers from a SAC byte buffer 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
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 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 | |
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_buffer,
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.web.fetch_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"),
... ) # doctest: +SKIP
>>>
Source code in src/pysmo/classes/_sac.py
from_buffer
classmethod
from_file
classmethod
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_buffer
read_buffer(buffer: bytes) -> None
Read data and headers from a SAC byte buffer into an existing SAC instance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
buffer
|
bytes
|
Buffer containing SAC file content. |
required |
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:
Checking if a SacEvent matches the pysmo
Event type:
>>> from pysmo.classes import SAC
>>> from pysmo import Event
>>> sac = SAC.from_file("example.sac")
>>> isinstance(sac.event, Event)
True
>>>
Note
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
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 345 346 347 348 349 350 351 352 353 354 355 356 357 358 | |
depth
property
writable
Event depth in metres (positive downward from the surface).
time
property
writable
time: UtcTimestamp
Event origin time (UTC).
Important
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/export class for SAC PZ (pole-zero) files.
Reads an analog instrument response from a
SAC PZ
file (as produced by e.g. the EarthScope SACPZ web 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.
To serialise an instance back to a SAC PZ file call
write, or use pysmo.lib.io.write_sacpz for
multi-record output.
Examples:
>>> from pysmo import Response
>>> 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)
>>> isinstance(response, Response)
True
>>> response.network, response.station
('IU', 'ANMO')
>>> from pathlib import Path
>>> response.write("out.pz"); recovered = SacPZ.from_text(Path("out.pz").read_text())
>>> recovered.network, recovered.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 from the EarthScope SACPZ web service, selecting one epoch. |
from_text |
Create a new instance from a single-record SAC PZ text body. |
write |
Write this response to a SAC PZ file. |
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
23 24 25 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 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 | |
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 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
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 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
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 from the EarthScope SACPZ web service, selecting one epoch.
Unlike StationXML.fetch, epoch
selection happens server-side: the SACPZ web service's own 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. |
Tip
When fetching live from EarthScope rather than reading an
existing SAC PZ file, prefer
StationXML.fetch: the
StationXML response 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) # doctest: +SKIP
>>>
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 import Response
>>> from pysmo.classes import SacPZ
>>> text = Path("SACPZ.IU.ANMO.00.BHZ").read_text()
>>> response = SacPZ.from_text(text)
>>> isinstance(response, Response)
True
>>> response.network, response.station
('IU', 'ANMO')
>>>
Source code in src/pysmo/classes/_sacpz.py
write
Write this response to a SAC PZ file.
Serialises the instance as a single SAC PZ record using the header
convention produced by the EarthScope SACPZ web service. If
reference_sensitivity
is None the * SENSITIVITY header line is omitted (the file
remains valid; CONSTANT carries the full system gain). To write
several responses into one concatenated file use
pysmo.lib.io.write_sacpz directly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike
|
Destination file path. The file is written in UTF-8 text mode and any existing content is overwritten. |
required |
Examples:
>>> from pathlib import Path
>>> from pysmo.classes import SacPZ
>>> text = Path("SACPZ.IU.ANMO.00.BHZ").read_text()
>>> response = SacPZ.from_text(text)
>>> response.write("out.pz"); recovered = SacPZ.from_text(Path("out.pz").read_text())
>>> recovered.network == response.network
True
>>>
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:
Checking if a SacSeismogram matches the pysmo
Seismogram type:
>>> from pysmo import Seismogram
>>> from pysmo.classes import SAC
>>> sac = SAC.from_file("example.sac")
>>> isinstance(sac.seismogram, Seismogram)
True
>>>
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
|
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:
Checking if a SacStation matches the pysmo
Station type:
>>> from pysmo.classes import SAC
>>> from pysmo import Station
>>> sac = SAC.from_file("example.sac")
>>> isinstance(sac.station, Station)
True
>>>
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
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 | |
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
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 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 | |
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 response metadata.
Reads an instrument response from a
FDSN StationXML document (as
returned by e.g. the EarthScope station web service with
level=response) and exposes it as a
Response-compatible object. Unlike
SacPZ, StationXML always satisfies
StagedResponse too — stages is simply empty
if the document has no digital FIR/IIR decimation stages.
A StationXML document commonly covers a channel's full instrument
history, i.e. several response epochs (e.g. after a sensor swap).
from_bytes narrows this to a
single epoch (matching a given time, or the currently-open one);
all_from_bytes returns
every epoch found, for callers who want to do their own selection.
Examples:
>>> from pysmo import Response, StagedResponse
>>> 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">
... <Channel code="BHZ" locationCode="00"
... startDate="2018-07-09T20:45:00.0000">
... <Response>
... <InstrumentSensitivity>
... <Value>1.98475E9</Value>
... <Frequency>0.02</Frequency>
... <InputUnits><Name>m/s</Name></InputUnits>
... <OutputUnits><Name>counts</Name></OutputUnits>
... </InstrumentSensitivity>
... <Stage number="1">
... <PolesZeros>
... <InputUnits><Name>m/s</Name></InputUnits>
... <OutputUnits><Name>V</Name></OutputUnits>
... <PzTransferFunctionType>LAPLACE (RADIANS/SECOND)</PzTransferFunctionType>
... <NormalizationFactor>5.03773E14</NormalizationFactor>
... <NormalizationFrequency>0.02</NormalizationFrequency>
... <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>
... <StageGain><Value>1183.0</Value><Frequency>0.02</Frequency></StageGain>
... </Stage>
... </Response>
... </Channel>
... </Station>
... </Network>
... </FDSNStationXML>'''
>>> response = StationXML.from_bytes(xml)
>>> isinstance(response, Response)
True
>>> isinstance(response, StagedResponse)
True
>>> response.network, response.station
('IU', 'ANMO')
>>>
Methods:
| Name | Description |
|---|---|
all_from_bytes |
Create one instance per response epoch in a StationXML document. |
fetch |
Fetch and parse an instrument response from the EarthScope FDSN station web service, selecting one epoch. |
from_bytes |
Create a new instance from a StationXML document, selecting one epoch. |
Attributes:
| Name | Type | Description |
|---|---|---|
channel |
str
|
Channel code parsed from the StationXML document. |
end_date |
Timestamp | None
|
End of the epoch this response applies to, or |
input_units |
str
|
Physical units produced by removing this response. |
location |
str
|
Location code parsed from the StationXML document. |
network |
str
|
Network code parsed from the StationXML document. |
overall_sensitivity |
NonZeroNumber
|
Scale factor combined with |
poles |
list[complex]
|
Response poles. |
reference_sensitivity |
NonZeroNumber | None
|
Total system sensitivity at the reference frequency, |
stages |
list[ResponseStage]
|
Digital decimation stages, in signal order. Empty if the document has |
start_date |
Timestamp
|
Start of the epoch this response applies to. |
station |
str
|
Station code parsed from the StationXML document. |
zeros |
list[complex]
|
Response zeros. |
Source code in src/pysmo/classes/_stationxml.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 | |
channel
class-attribute
instance-attribute
channel: str = field(validator=validators.instance_of(str))
Channel code parsed from the StationXML document.
end_date
class-attribute
instance-attribute
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)
)
location
class-attribute
instance-attribute
location: str = field(validator=validators.instance_of(str))
Location code parsed from the StationXML document.
network
class-attribute
instance-attribute
network: str = field(validator=validators.instance_of(str))
Network code parsed from the StationXML document.
overall_sensitivity
class-attribute
instance-attribute
overall_sensitivity: NonZeroNumber = field(
converter=float, validator=validate_nonzero
)
Scale factor combined with poles/zeros to reconstruct H(f)
(NormalizationFactor * InstrumentSensitivity).
See Response.overall_sensitivity
for more details.
poles
class-attribute
instance-attribute
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
(StationXML's InstrumentSensitivity/Value).
See
Response.reference_sensitivity
for more details.
stages
class-attribute
instance-attribute
stages: list[ResponseStage] = field(factory=list)
Digital decimation stages, in signal order. Empty if the document has no digital stages.
See StagedResponse.stages for more details.
start_date
class-attribute
instance-attribute
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 StationXML document.
zeros
class-attribute
instance-attribute
all_from_bytes
classmethod
Create one instance per response epoch in a StationXML document.
Unlike from_bytes, this
does not narrow to a single epoch — a document covering a channel's
full instrument history returns several, each with its own
network/station/location/channel/start_date/end_date
provenance, which callers can filter themselves.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
xml
|
bytes
|
Raw StationXML document bytes. |
required |
Returns:
| Type | Description |
|---|---|
list[Self]
|
One StationXML instance per response epoch found, in document |
list[Self]
|
order. |
Source code in src/pysmo/classes/_stationxml.py
fetch
classmethod
Fetch and parse an instrument response from the EarthScope FDSN station web service, selecting one epoch.
A channel's instrument response usually has several epochs (e.g.
after a sensor swap), so the request is narrowed to a single one:
the epoch active at time if given, otherwise the one currently
open (no endDate). Fetches the full response history in one
request and narrows client-side (like
from_bytes); to fetch once
and interpret later (e.g. offline, or without repeating the network
request), use pysmo.tools.web.fetch_stationxml and
from_bytes /
all_from_bytes directly
instead.
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 StationXML instance for the response epoch active at |
Self
|
time (or currently open, if |
Raises:
| Type | Description |
|---|---|
ValueError
|
If zero or more than one response epoch matches
time (or "currently open", if |
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,
... )
>>> response = StationXML.fetch(station=station) # doctest: +SKIP
>>>
Source code in src/pysmo/classes/_stationxml.py
from_bytes
classmethod
from_bytes(
xml: bytes,
*,
time: Timestamp | 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
station-level query (or one saved for later, offline use) commonly
returns every location/channel combination on record, each with its
own epoch history. location/channel narrow to one before time
is applied; without them, a multi-channel document raises the same
"more than one epoch" error as an ambiguous time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
xml
|
bytes
|
Raw StationXML document bytes (as returned by the FDSN
station web service with |
required |
time
|
Timestamp | None
|
Timestamp used to select the response epoch. 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 response epoch active at |
Self
|
time (or currently open, if |
Raises:
| Type | Description |
|---|---|
ValueError
|
If, after narrowing by |
See Also
StationXML.all_from_bytes:
Parse every epoch in the document without narrowing to one.