MS3Record¶
- class pymseed.MS3Record(reclen=None, encoding=None)[source]¶
Bases:
objectA wrapper for miniSEED data records supporting formats v2 and v3.
MS3Record provides a Python interface to individual miniSEED data records, which are the fundamental unit of the miniSEED time series data format. Each record contains metadata (timing, sample rate, encoding) and optionally, but commonly, data samples.
miniSEED is a format optimized for continuous time series data. It’s widely used in seismology, and related geophysical data for storing and exchanging time series data.
- Key Features:
Read and write miniSEED v2 and v3 formats
Access to all record metadata (timing, sample rates, encoding, etc.)
Efficient data sample access via memoryview (zero-copy) or numpy arrays
Support for all defined data encodings
Common Usage Patterns:
- Reading records (from a file):
>>> from pymseed import MS3Record >>> for msr in MS3Record.from_file('examples/example_data.mseed', unpack_data=True): ... print(f"{msr.sourceid}: {msr.numsamples} samples") ... break # only print the first record to limit testing output FDSN:IU_COLA_00_L_H_1: 135 samples
- Creating records:
>>> from pymseed import MS3Record, DataEncoding >>> msr = MS3Record() >>> msr.sourceid = "FDSN:NET_STA_LOC_B_S_X" >>> msr.set_starttime_str("2024-01-01T00:00:00Z") >>> msr.samprate = 100.0 >>> msr.encoding = DataEncoding.STEIM2 >>> msr.reclen = 512
>>> for record in msr.generate(data_samples=[1,2,3,4], sample_type='i'): ... print(f"Packed {len(record)} byte record") Packed 126 byte record
- Working with data samples:
# Get data as memoryview (no copy) data_mv = msr.datasamples # Get data as numpy array (requires numpy, no copy) data_np = msr.np_datasamples # Get data as Python list (copy) data_list = msr.datasamples[:]
- All miniSEED record fields are accessible as properties with both
- getters and setters where appropriate. Key properties include
- - sourceid
FDSN Source Identifier (e.g., “FDSN:IU_COLA_00_B_H_Z”)
- - starttime
Start time in nanoseconds since Unix epoch
- - samprate
Sample rate in Hz (positive) or interval in seconds (negative)
- - numsamples
Number of decoded data samples
- - datasamples
Access to the actual data samples
- - encoding
Data encoding format (Steim1/2, Float, etc.)
See also
MSTraceList: For working with collections of records as traces
Initialize a new, empty MS3Record.
The structure is initialized with library defaults, which the optional parameters override.
- Parameters:
reclen (int | None) – Maximum record length in bytes. Common values are 512 and 4096. If None, uses library default.
encoding (int | None) – Data encoding format code. Common values: DataEncoding.TEXT, DataEncoding.STEIM1, DataEncoding.STEIM2, DataEncoding.FLOAT32, DataEncoding.FLOAT64. If None, uses library default.
- Raises:
ValueError – If
reclenorencodingis outside its valid range (see thereclenandencodingsetters).MiniSEEDError – If the underlying libmseed allocation fails.
Note
To read an existing record instead of creating one, use
from_file(),from_buffer(),from_filelike(), orparse().Example
>>> # Create empty record >>> from pymseed import MS3Record >>> msr = MS3Record() >>> msr.sourceid = "FDSN:XX_TEST__B_S_X" >>> msr.samprate = 20.0 >>> >>> # Create with specific encoding for Steim2 compression >>> msr = MS3Record(encoding=11, reclen=4096)
- __init__(reclen=None, encoding=None)[source]¶
Initialize a new, empty MS3Record.
The structure is initialized with library defaults, which the optional parameters override.
- Parameters:
reclen (int | None) – Maximum record length in bytes. Common values are 512 and 4096. If None, uses library default.
encoding (int | None) – Data encoding format code. Common values: DataEncoding.TEXT, DataEncoding.STEIM1, DataEncoding.STEIM2, DataEncoding.FLOAT32, DataEncoding.FLOAT64. If None, uses library default.
- Raises:
ValueError – If
reclenorencodingis outside its valid range (see thereclenandencodingsetters).MiniSEEDError – If the underlying libmseed allocation fails.
- Return type:
None
Note
To read an existing record instead of creating one, use
from_file(),from_buffer(),from_filelike(), orparse().Example
>>> # Create empty record >>> from pymseed import MS3Record >>> msr = MS3Record() >>> msr.sourceid = "FDSN:XX_TEST__B_S_X" >>> msr.samprate = 20.0 >>> >>> # Create with specific encoding for Steim2 compression >>> msr = MS3Record(encoding=11, reclen=4096)
- property record_mv: memoryview¶
Return raw, parsed miniSEED record as a memoryview (no copy).
The record is returned as it was parsed, whatever
reclenhas been set to since.The memoryview holds a reference to this MS3Record, keeping its C memory alive for as long as the view is used. It is still tied to this record’s current state: re-parsing, repacking, or freeing the record invalidates the underlying bytes even though the view itself stays reachable. Copy with
bytes(...)or.tobytes()to detach from the underlying record.
- property reclen: int¶
Return the parsed record length in bytes, or the maximum length set for packing (-1 for the library default)
- property sourceid: str¶
Source identifier string identifying the data source.
- Returns:
Source identifier string
- flags_dict()[source]¶
Record flags as a dictionary.
Decodes the 8-bit flags field into named boolean indicators for data quality assessment.
- Returns:
- Dictionary with flag names as keys:
’calibration_signals_present’: Calibration signals detected ‘time_tag_is_questionable’: Timing accuracy uncertain ‘clock_locked’: Clock was locked to reference
- Return type:
Example
>>> from pymseed import MS3Record >>> msr = MS3Record() >>> flags = msr.flags_dict() >>> if flags.get('time_tag_is_questionable'): ... print("Warning: questionable timing")
See also
flags: Raw 8-bit flags value
- property starttime: int¶
Time of the first sample as nanoseconds since Unix epoch.
Depending on the version of miniSEED, and the characteristics of the data source, the start time may not have nanosecond precision. A precision of microseconds is common, along with .0001 second resolution.
- Returns:
Nanoseconds since Unix epoch (1970-01-01T00:00:00Z)
- Return type:
Example
>>> from pymseed import MS3Record >>> msr = MS3Record() >>> msr.starttime = 1609459200000000000 # 2021-01-01T00:00:00Z
See also
starttime_seconds: For working with floating-point seconds starttime_str(): For human-readable time strings
- starttime_str(timeformat=TimeFormat.ISOMONTHDAY_Z, subsecond=SubSecond.NANO_MICRO_NONE)[source]¶
Return start time as formatted string
Returns the sentinel strings
"ERROR"or"UNSET"when the underlying nanosecond timestamp is the corresponding libmseed sentinel.- Parameters:
timeformat (TimeFormat)
subsecond (SubSecond)
- Return type:
- set_starttime_str(value)[source]¶
Set start time from formatted date-time string
- Parameters:
value (str) – Formatted date-time string A number of formats are supported, but the recommended form is YYYY-MM-DDTHH:MM:SS.ssssssZ (RFC 3339/ISO 8601).
- Raises:
ValueError – If the string is not a valid date-time string
- Return type:
None
Example
>>> from pymseed import MS3Record >>> msr = MS3Record() >>> msr.set_starttime_str("2021-01-01T00:00:00.123456789Z") >>> msr.starttime_str() '2021-01-01T00:00:00.123456789Z'
See also
starttime_str(): For formatting the start time as a string
- property samprate: float¶
Nominal sample rate in samples per second (Hz)
Examples
>>> from pymseed import MS3Record >>> msr = MS3Record() >>> msr.samprate = 100.0 # 100 Hz sampling >>> msr.samprate 100.0 >>> msr.samprate = -10.0 # 10 second intervals >>> msr.samprate 0.1
See also
samprate_raw: Nominal sample rate in Hz or sample interval in seconds
- property samprate_raw: float¶
Nominal sample rate in samples per second (Hz) or sample interval in seconds.
When positive, this represents samples per second (Hz). When negative, this represents the sample period in seconds (-1/period).
- Returns:
Sample rate in Hz (positive) or interval in seconds (negative)
Examples
>>> from pymseed import MS3Record >>> msr = MS3Record() >>> msr.samprate = 100.0 # 100 Hz sampling >>> msr.samprate_raw 100.0 >>> msr.samprate = -10.0 # 10 second intervals >>> msr.samprate_raw -10.0
See also
samprate: Nominal sample rate in Hz
- property samprate_period_ns: int¶
Nominal sample period in nanoseconds.
Examples
>>> from pymseed import MS3Record >>> msr = MS3Record() >>> msr.samprate = 40.0 # 40 Hz sampling >>> msr.samprate_period_ns 25000000 >>> msr.samprate = -10.0 # 10 second intervals >>> msr.samprate_period_ns 10000000000
See also
samprate_period_seconds: Nominal sample period in seconds
- property samprate_period_seconds: float¶
Nominal sample period in seconds.
Returned as a 64-bit IEEE-754 float, i.e. the closest binary representation of
period_ns / 1_000_000_000. For typical seismic sample periods the value round-trips back to the exact integer nanosecond count, but the float is not bit-identical to the corresponding decimal (e.g. a 40 Hz period is the nearest float to0.025, not the decimal0.025itself), so downstream arithmetic can accumulate small errors. Usesamprate_period_nswhen you need exact integer-nanosecond arithmetic.Examples
>>> from pymseed import MS3Record >>> msr = MS3Record() >>> msr.samprate = 40.0 # 40 Hz sampling >>> msr.samprate_period_seconds 0.025 >>> msr.samprate = -10.0 # 10 second intervals >>> msr.samprate_period_seconds 10.0
See also
samprate_period_ns: Nominal sample period in nanoseconds (exact integer)
- property encoding: int¶
Data encoding format code specifying how data samples are compressed/stored.
Returns -1 when not set, matching the C library convention used by other unset fields (reclen, samplecnt).
miniSEED supports various encoding formats optimized for different data types and compression requirements. Common encoding values:
DataEncoding.TEXT: UTF-8 text
DataEncoding.STEIM1: Steim1 32-bit integer compression
DataEncoding.STEIM2: Steim2 32-bit integer compression
DataEncoding.FLOAT32: IEEE Float32 (little-endian)
DataEncoding.FLOAT64: IEEE Float64 (little-endian)
- Returns:
Encoding format code, or -1 if not set.
- Return type:
Examples
>>> from pymseed import MS3Record, DataEncoding >>> msr = MS3Record() >>> msr.encoding -1 >>> msr.encoding = DataEncoding.STEIM2 >>> msr.encoding = DataEncoding.FLOAT32
See also
encoding_str(): Human-readable encoding description
- get_extra_header(ptr)[source]¶
Get an extra header value specified by JSON Pointer
- Parameters:
ptr (str) – JSON Pointer (RFC 6901) to the header value to get
- Returns:
Value of the header, can be a boolean, integer, float, string, or None if the header does not exist.
- Raises:
TypeError – If ptr is not a str
ValueError – If the header value cannot be read
- Return type:
Examples
>>> from pymseed import MS3Record >>> msr = MS3Record() >>> msr.extra = '''{ ... "FDSN": { ... "Time": { ... "Quality": 100, ... "Correction": 1.234 ... }, ... "Flags": { ... "MassPositionOffscale": true ... } ... }, ... "Operator": { ... "Battery": { ... "Status": "CHARGING" ... } ... }}'''
>>> msr.get_extra_header("/FDSN/Time/Quality") 100 >>> msr.get_extra_header("/FDSN/Time/Correction") 1.234 >>> msr.get_extra_header("/FDSN/Flags/MassPositionOffscale") True >>> msr.get_extra_header("/Operator/Battery/Status") 'CHARGING'
# Returns None when header does not exist >>> assert msr.get_extra_header(“/Nonexistent/Header”) is None
See also
set_extra_header(): Set an extra header value
- set_extra_header(ptr, value)[source]¶
Set an extra header value specified by JSON Pointer
The header value at the specified JSON Pointer will be set to the value provided, either replacing or creating the value.
- Parameters:
- Raises:
TypeError – If ptr is not a str, or value is not one of the supported types.
ValueError – If the header value cannot be set.
- Return type:
None
Examples
>>> from pymseed import MS3Record >>> msr = MS3Record() >>> msr.set_extra_header("/FDSN/Time/Quality", 100) >>> msr.set_extra_header("/FDSN/Time/Correction", 1.234) >>> msr.set_extra_header("/FDSN/Flags/MassPositionOffscale", True) >>> msr.set_extra_header("/Operator/Battery/Status", "CHARGING")
See also
merge_extra_headers(): Apply a JSON Merge Patch to extra headers
- merge_extra_headers(value)[source]¶
Apply a JSON Merge (RFC 7386) Patch to extra headers
A JSON Merge Patch can be used to create, update, or delete extra headers.
- Parameters:
value (str) – JSON Merge Patch to apply, serialized as a string
- Raises:
ValueError – If
valueis not valid JSON, or the patch cannot be applied- Return type:
None
Examples
>>> from pymseed import MS3Record >>> msr = MS3Record() >>> merge_patch = '{"FDSN": {"Time": {"Quality": 100}}}' >>> msr.merge_extra_headers(merge_patch) >>> msr.extra '{"FDSN":{"Time":{"Quality":100}}}'
Remove time /FDSN/Time/Quality header and add an /FDSN/Time/Correction header: >>> merge_patch = ‘’’{ … “FDSN”: { … “Time”: { … “Quality”: null, … “Correction”: 1.234 … } … }}’’’ >>> msr.merge_extra_headers(merge_patch) >>> msr.extra ‘{“FDSN”:{“Time”:{“Correction”:1.234}}}’
- validate_extra_headers(schema_id='FDSN-v1.0', schema_file=None)[source]¶
Validate the extra headers against a JSON Schema
The selected schema should conform to the JSON Schema 2020-12 specification: https://json-schema.org/draft/2020-12#draft-2020-12
Any specified schema_file will take precedence over schema_id.
The schema_id is a known schema ID that can be used to select a schema from the package. As of this writing only “FDSN-v1.0” is an accepted value and uses the published schema: ExtraHeaders-FDSN-v1.0.schema-2020-12.json
- Parameters:
schema_id (str) – ID of the known schema to use, defaults to “FDSN-v1.0”
schema_file (str | os.PathLike[str] | None) – Path to specific schema file to use, accepting
stror anyos.PathLike. Defaults to None.
- Returns:
A list of
jsonschema_rs.ValidationErrorinstances, empty if no errors.- Return type:
list[JsonSchemaValidationError]
Examples
>>> from pymseed import MS3Record >>> msr = MS3Record() >>> msr.extra = '''{ ... "FDSN": { ... "Time": { ... "Quality": 100, ... "Correction": 1.234 ... }, ... "Flags": { ... "MassPositionOffscale": true ... } ... }, ... "Operator": { ... "Battery": { ... "Status": "CHARGING" ... } ... }}''' >>> msr.validate_extra_headers() []
# INVALID headers >>> msr.extra = ‘’’{ … “FDSN”: { … “Time”: { … “Quality”: “really good”, … “Correction”: false … }, … “Flags”: { … “MassPositionOffscale”: 1.2345 … }, … “Invalid”: { … “Header”: “value not allowed in FDSN section” … } … }}’’’ >>> errors = msr.validate_extra_headers() >>> len(errors) 4
- valid_extra_headers(schema_id='FDSN-v1.0', schema_file=None)[source]¶
Check if the extra headers are valid
The selected schema should conform to the JSON Schema 2020-12 specification: https://json-schema.org/draft/2020-12#draft-2020-12
Any specified schema_file will take precedence over schema_id.
The schema_id is a known schema ID that can be used to select a schema from the package. As of this writing only “FDSN-v1.0” is an accepted value and uses the published schema: ExtraHeaders-FDSN-v1.0.schema-2020-12.json
- Parameters:
- Returns:
True if the extra headers are valid, False otherwise.
- Return type:
Examples
>>> from pymseed import MS3Record >>> msr = MS3Record() >>> msr.extra = '''{ ... "FDSN": { ... "Time": { ... "Quality": 100 ... } ... } ... }''' >>> msr.valid_extra_headers() True
>>> from pymseed import MS3Record >>> msr = MS3Record() >>> msr.extra = '''{ ... "FDSN": { ... "Emit": { ... "Ytilauq": 100 ... } ... } ... }''' >>> msr.valid_extra_headers() False
- property datasamples: memoryview[Any]¶
Data samples as a memoryview (zero-copy access).
Returns a memoryview of the decoded data samples. This provides direct access to the internal buffer without copying data.
The view type depends on the data encoding:
Integer data (Steim1/2, int16/32): memoryview of 32-bit integers
Float32 data: memoryview of 32-bit floats
Float64 data: memoryview of 64-bit floats
Text data: memoryview of bytes
Note
The returned view is only valid while this MS3Record exists. If data is needed beyond the record’s lifetime, make a copy.
- Returns:
Direct view of sample data, indexed 0 to numsamples-1
- Return type:
Examples
>>> from pymseed import MS3Record >>> reader = MS3Record.from_file("examples/example_data.mseed", unpack_data=True) >>> msr = reader.read() >>> # Direct indexing (no copy) >>> first_sample = msr.datasamples[0] >>> last_sample = msr.datasamples[-1] >>> >>> # Slicing (no copy) >>> first_ten = msr.datasamples[:10] >>> >>> # Copy to Python list >>> data_list = msr.datasamples[:] >>> >>> # Copy to new array >>> import array >>> data_array = array.array('f', msr.datasamples)
See also
np_datasamples: NumPy array view (requires numpy) numsamples: Number of available samples sampletype: Type indicator (‘i’, ‘f’, ‘d’, ‘t’)
- property np_datasamples: Any¶
Data samples as a NumPy array view (zero-copy access).
Returns a NumPy array view of the decoded data samples without copying the underlying data.
The array dtype depends on the data encoding: - Integer data (Steim1/2, int16/32): numpy.int32 - Float32 data: numpy.float32 - Float64 data: numpy.float64 - Text data: numpy dtype ‘S1’ (1-byte strings)
- Returns:
1D array view of the sample data
- Return type:
- Raises:
ImportError – If NumPy is not installed
ValueError – If sample type is unknown or unsupported
Note
Requires NumPy to be installed. The returned array is only valid while this MS3Record exists. For permanent storage, make a copy.
Examples
>>> from pymseed import MS3Record >>> reader = MS3Record.from_file("examples/example_data.mseed", unpack_data=True) >>> msr = reader.read()
>>> # Direct NumPy operations (no copy) >>> import numpy as np >>> data = msr.np_datasamples >>> mean_value = np.mean(data) >>> max_value = np.max(data)
>>> # Copy for permanent storage >>> data_copy = msr.np_datasamples.copy()
>>> # Mathematical operations >>> filtered = data * 0.5 # Creates new array
See also
datasamples: Raw memoryview access numsamples: Number of available samples sampletype: Type indicator (‘i’, ‘f’, ‘d’, ‘t’)
- property numsamples: int¶
Number of data samples that have been decoded and are available.
This represents the actual number of samples accessible via datasamples or np_datasamples properties. May differ from samplecnt (which is the declared sample count in the record header) if data has not been decoded.
- Returns:
Number of decoded samples (0 if no data decoded)
- Return type:
See also
samplecnt: Sample count from record header datasamples: Access to the actual sample data
- property endtime: int¶
End time of the last sample as nanoseconds since Unix epoch.
Calculated from starttime, sample rate, and number of samples. For regularly sampled data: endtime = starttime + (numsamples-1)/samprate
- Returns:
Nanoseconds since Unix epoch (1970-01-01T00:00:00Z)
- Return type:
See also
starttime: Start time of first sample endtime_seconds: End time as floating-point seconds endtime_str(): Human-readable end time string
- endtime_str(timeformat=TimeFormat.ISOMONTHDAY_Z, subsecond=SubSecond.NANO_MICRO_NONE)[source]¶
Return end time as formatted string
Returns the sentinel strings
"ERROR"or"UNSET"when the underlying nanosecond timestamp is the corresponding libmseed sentinel.- Parameters:
timeformat (TimeFormat)
subsecond (SubSecond)
- Return type:
- encoding_str()[source]¶
Human-readable description of the data encoding format.
- Returns:
- Descriptive string like “STEIM-2 integer compression”,
”32-bit float (IEEE single)”,
"Unset"if the encoding is not set, or"Unknown"if libmseed does not recognize the encoding code.
- Return type:
See also
encoding: Numeric encoding code
- print(details=0)[source]¶
Print record information to stdout with configurable detail level.
Useful for debugging and inspecting record contents. Output includes metadata, timing information, and optionally sample data.
- Parameters:
details (int) – Detail level for output: 0 = Basic record header information (default) 1 = All record header information
- Return type:
None
- unpack_data(verbose=0)[source]¶
Unpack the record’s data samples
This method unpacks (decodes) the data samples associated with the record if they were not decoded during the parsing process. This is useful when only specific records need to be unpacked or for delayed unpacking workflows.
- Parameters:
verbose (int) – Verbosity level for diagnostic output. Default: 0
- Returns:
Number of samples unpacked
- Raises:
MiniSEEDError – If unpacking fails
- Return type:
- with_datasamples(data_samples, sample_type)[source]¶
Context manager for temporarily setting data samples with automatic cleanup.
This context manager temporarily sets data samples, counts, and type for the record and automatically restores the original state when exiting the context.
A common use case is to set data samples for creating (packing) miniSEED records, but this can be used for any purpose that requires setting data samples for a short period of time.
- Parameters:
data_samples (Any) – One-dimensional sequence containing the data samples. Can be a list, numpy array, memoryview, or any object supporting the sequence protocol. If the value supports a memoryview, it will be used directly without copying.
sample_type (str) – Single character string indicating the data type (‘i’, ‘f’, ‘d’, ‘t’)
- Yields:
MS3Record – The record with the temporary data samples set
- Raises:
ValueError – If
data_samplesis not one-dimensional, orsample_typeis not one of ‘i’, ‘f’, ‘d’, ‘t’.- Return type:
Examples
Setting data samples for packing:
>>> from pymseed import MS3Record, DataEncoding >>> msr = MS3Record() >>> msr.sourceid = "FDSN:XX_TEST__H_S_X" >>> msr.reclen = 512 >>> msr.formatversion = 3 >>> msr.set_starttime_str("2023-01-02T01:02:03.123456789Z") >>> msr.samprate = 100.0 >>> msr.pubversion = 1 >>> msr.encoding = DataEncoding.STEIM2
# A data array that can be used without copying (zero-copy). This is # a common case for data that is already in a bytearray, numpy array, # or other object from which a memoryview can be created. >>> import array >>> data = array.array(‘i’, [1, 2, 3, 4])
>>> output_file = "output.mseed" >>> with msr.with_datasamples(data, 'i'): ... print (f"Writing records for {msr.numsamples} samples of type {msr.sampletype}") ... packed_records = msr.to_file(output_file) Writing records for 4 samples of type i
# Setting data samples for packing from a simple list that will be copied
>>> data = [1.1, 2.6, 3.2, 4.8] # A simple list will be copied (no memoryview) >>> with msr.with_datasamples(data, 'f'): ... print (f"Record has {msr.numsamples} samples of type {msr.sampletype}") Record has 4 samples of type f
# Setting text data can be a string, bytes, bytearray, or a sequence # that is converted to byte characters. Text data is always copied.
>>> text_samples = "This is a log entry" >>> msr.sourceid = "FDSN:XX_TEST__L_O_G" >>> msr.samprate = 0 >>> with msr.with_datasamples(text_samples, 't'): ... print (f"Record has {msr.numsamples} samples of type {msr.sampletype}") Record has 19 samples of type t
Note
The original record state is completely restored when exiting the context, including datasamples pointer, data size, sample counts, and sample type.
A zero-copy source is held by reference for the whole context and must not be resized within it, which would leave the record pointing at freed memory. On CPython the buffer protocol refuses the resize with
BufferError; PyPy keeps no export count, so there such a resize is undefined behavior that nothing reports.See also
MS3TraceList.add_data(): Add data samples to a trace list
- generate(data_samples=None, sample_type=None, *, verbose=0)[source]¶
Create miniSEED record(s) using parameters from the record.
This method creates miniSEED records using the parameters (encoding, record length, etc.) in this MS3Record. Alternate data samples (and type) can be provided, otherwise the existing record data is used.
This method returns a generator that yields each miniSEED record as
bytes.- Parameters:
data_samples (Any) – Data to pack. If None, uses existing record data. Types supported: list of int/float/str, numpy arrays, or any buffer-protocol compatible object.
sample_type (str | None) – Sample type indicator when providing data_samples: ‘i’ = 32-bit integer ‘f’ = 32-bit float ‘d’ = 64-bit float ‘t’ = text (1 byte per sample) Required when data_samples is provided.
verbose (int) – Verbosity level for diagnostic output (0=quiet, 1+=verbose)
- Yields:
bytes – Each miniSEED record as it is created
- Raises:
ValueError – If only one of
data_samplesandsample_typeis provided. They must be passed together or both omitted.- Return type:
Examples
>>> from pymseed import MS3Record, DataEncoding >>> >>> # Create record template with MS3Record() >>> msr = MS3Record() >>> msr.sourceid = "FDSN:XX_TEST__L_H_Z" >>> msr.set_starttime_str("2024-01-01T00:00:00Z") >>> msr.samprate = 1 >>> >>> # Generate miniSEED records and write to file >>> # (See `MS3Record.to_file()` for a more convenient way to write to a file) >>> with open('output.mseed', 'wb') as f: ... for record in msr.generate( ... data_samples=[1, 2, 3, 4, 5], ... sample_type='i' ... ): ... f.write(record) >>> >>> # Generate miniSEED records and collect in a list >>> record_list = [] >>> msr.encoding = DataEncoding.FLOAT32 >>> data_samples = [1.0, 2.1, 3.2, 4.3, 5.4] >>> for record in msr.generate(data_samples=data_samples, sample_type='f'): ... record_list.append(record) >>> print(f"Generated {len(record_list)} records") Generated 1 records
See also
MS3Record: Full record documentation
- to_file(filename, *, overwrite=False, verbose=0)[source]¶
Write data contained in the record to a miniSEED file
- Parameters:
filename (str | PathLike[str]) – Path to the output miniSEED file. Accepts
stror anyos.PathLike(e.g.pathlib.Path); other types raiseTypeError. The file will be created if it doesn’t exist. Directory must already exist.overwrite (bool) – If True, overwrites existing file. If False and file exists, append data to the end of the file. Default is False for safety.
verbose (int) – Verbosity level for libmseed output (0=quiet, 1=info, 2=detailed).
- Returns:
Number of miniSEED records written to the file.
- Return type:
- Raises:
TypeError – If filename is not a str or os.PathLike.
MiniSEEDError – If the underlying libmseed library encounters an error during file writing (e.g., permission denied, disk full, invalid data).
See also
generate(): For creating record MS3Record: Full record documentation
- classmethod from_file(filename, **kwargs)[source]¶
Create a record reader for miniSEED files.
This convenience method returns an MS3RecordReader that can iterate over all records in a miniSEED file.
Note that the objects returned by this iterator are only valid during the lifetime of the iterator. Once the iterator is exhausted, the objects are no longer valid and should not be used.
Records may be filtered with the
sourceid,starttime, andendtimekeyword arguments; only records matching the source ID glob pattern and/or overlapping the time window are returned. The filtering is performed inside libmseed, so non-matching records are skipped without crossing into Python and their data samples are never decoded.- Parameters:
filename (str | os.PathLike[str] | int) – Path to miniSEED file
**kwargs (Any) – Additional arguments passed to MS3RecordReader, e.g.
unpack_data,sourceid,starttime,endtime,skip_not_data,validate_crc,verbose.
- Returns:
Iterator over records in the file
- Return type:
Note
A filter that matches nothing yields no records rather than raising, and so does an empty file. Non-empty content that isn’t miniSEED still raises.
A file ending part way through a record, or with bytes remaining that are too few for one, raises
MiniSEEDErrorafter the records that did parse. Passskip_not_data=Trueto accept such a remnant as the end of the stream.Examples
Read every record in a file:
>>> from pymseed import MS3Record >>> total_samples = 0 >>> for msr in MS3Record.from_file( ... 'examples/example_data.mseed', unpack_data=True ... ): ... total_samples += msr.numsamples >>> print(f"Total samples: {total_samples}") Total samples: 12600
Read only the records matching a source ID and time window:
>>> records = [ ... (msr.sourceid, msr.starttime_str()) ... for msr in MS3Record.from_file( ... "examples/example_data.mseed", ... sourceid="FDSN:IU_COLA_00_L_H_Z", ... starttime="2010-02-27T07:00:00Z", ... endtime="2010-02-27T07:30:00Z", ... ) ... ] >>> len(records) 15
A record is selected when it overlaps the window, so the first one may start before
starttime:>>> records[0] ('FDSN:IU_COLA_00_L_H_Z', '2010-02-27T06:59:01.069539Z')
See also
from_buffer(): Read from memory buffer MS3RecordReader: Full file reader documentation
- classmethod from_buffer(buffer, *, unpack_data=False, sourceid=None, starttime=None, endtime=None, validate_crc=True, verbose=0)[source]¶
Iterate over miniSEED records in a memory buffer.
Parses miniSEED records sequentially from a bytes-like object and yields each record. All state is kept in local variables for maximum iteration speed.
Note that each yielded
MS3Recordshares a C struct with the generator. The record is only valid until the nextnext()call on the generator. If you need to retain a record beyond the current iteration step, copy the fields you need or useparse()instead.The buffer is held by reference for the lifetime of the generator (CFFI keeps a buffer-protocol export over it). For mutable buffer types (
bytearray,memoryviewover abytearray, writablenumpy.ndarray), the caller must not modify the contents until iteration finishes — doing so is undefined behavior that silently corrupts the next record read and is not caught by Python or CFFI. On CPython, resizing operations (e.g.buf.extend(...),buf.clear(),del buf[i:]) are caught by the buffer protocol and raiseBufferErrorwhile the generator is alive; PyPy keeps no such export count, so there a resize is undefined behavior as well. If the source must remain writable, pass an immutable copy (bytes(buf)), or close the generator (e.g.gen.close(), or let theforloop complete) before mutating.- Parameters:
buffer (Any) – Bytes-like object containing miniSEED data. Must support the buffer protocol (e.g.
bytes,bytearray,memoryview,numpy.ndarray).unpack_data (bool) – If
True, decode data samples for each record. Default isFalse.sourceid (str | None) – Source ID glob pattern to select matching records (e.g.
"FDSN:IU_COLA_*").Nonematches all source IDs. Default isNone.starttime (str | None) – Start of time window as a formatted date-time string (e.g.
"2024-01-01T00:00:00Z"). Only records containing data after this time are yielded.Nonemeans open start. Default isNone.endtime (str | None) – End of time window as a formatted date-time string. Only records containing data before this time are yielded.
Nonemeans open end. Default isNone.validate_crc (bool) – If
True, validate CRC checksums when present (miniSEED v3 only). Default isTrue.verbose (int) – Verbosity level for libmseed diagnostics. Default is 0.
- Yields:
MS3Record – Each parsed record. Valid only until the next iteration.
- Raises:
ValueError – If
bufferdoes not support the buffer protocol, or ifstarttimeorendtimeis not a valid date-time string. Being a generator, this is raised on first iteration rather than at the call.BufferError – If
bufferis not C-contiguous.MiniSEEDError – If a record cannot be parsed, or if the buffer ends part way through a record, or with bytes remaining that are too few for one; the truncated cases carry a status of
MS_ENDOFFILE.
- Return type:
Note
Every record header in the buffer is parsed even when a filter is active; libmseed provides no way to skip a record without first reading its header. Matching is done in C (
msr3_matchselect) and data samples of rejected records are never decoded, but the per-record loop remains in Python.Examples
>>> from pymseed import MS3Record >>> with open('examples/example_data.mseed', 'rb') as f: ... buffer = f.read() >>> total_samples = 0 >>> for msr in MS3Record.from_buffer(buffer, unpack_data=True): ... total_samples += msr.numsamples >>> print(f"Total samples: {total_samples}") Total samples: 12600
With source ID and time-window filtering, a record is selected when it overlaps the requested window:
>>> selected = 0 >>> for msr in MS3Record.from_buffer( ... buffer, ... sourceid="FDSN:IU_COLA_00_L_H_Z", ... starttime="2010-02-27T07:00:00Z", ... endtime="2010-02-27T07:30:00Z", ... ): ... selected += 1 >>> print(f"Selected records: {selected}") Selected records: 15
See also
parse(): Parse a single record from a buffer (owns the C struct) from_file(): Iterate over records in a file
- classmethod from_filelike(fh, *, chunk_size=65536, unpack_data=False, sourceid=None, starttime=None, endtime=None, validate_crc=True, verbose=0)[source]¶
Iterate over miniSEED records from a file-like object using chunked reads.
Reads from any object with a
.read(n)method (e.g.io.BytesIO,sys.stdin.buffer, a network socket file, an HTTP response body) without loading the entire content into memory first.Note that each yielded
MS3Recordshares a C struct with the generator. The record is only valid until the nextnext()call on the generator. If you need to retain a record beyond the current iteration step, copy the fields you need or useparse()instead.- Parameters:
fh (Any) – A file-like object with a
.read(n)method that returnsbytes.chunk_size (int) – Number of bytes to read per
.read()call, greater than 0 and less than 1 GiB. Default is 65536.unpack_data (bool) – If
True, decode data samples for each record. Default isFalse.sourceid (str | None) – Source ID glob pattern to select matching records (e.g.
"FDSN:IU_COLA_*").Nonematches all source IDs. Default isNone.starttime (str | None) – Start of time window as a formatted date-time string (e.g.
"2024-01-01T00:00:00Z"). Only records containing data after this time are yielded.Nonemeans open start. Default isNone.endtime (str | None) – End of time window as a formatted date-time string. Only records containing data before this time are yielded.
Nonemeans open end. Default isNone.validate_crc (bool) – If
True, validate CRC checksums when present (miniSEED v3 only). Default isTrue.verbose (int) – Verbosity level for libmseed diagnostics. Default is 0.
- Yields:
MS3Record – Each parsed record. Valid only until the next iteration.
- Raises:
TypeError – If
fhhas no callable.readmethod.ValueError – If
chunk_sizeis not greater than 0 and less than 1 GiB, or ifstarttimeorendtimeis not a valid date-time string.MiniSEEDError – If a record cannot be parsed, or if the stream ends part way through a record, or with bytes remaining that are too few for one; the truncated cases carry a status of
MS_ENDOFFILE.
- Return type:
Note
Every record header in the stream is parsed even when a filter is active; libmseed provides no way to skip a record without first reading its header. Matching is done in C (
msr3_matchselect) and data samples of rejected records are never decoded, but the per-record loop remains in Python.Examples
>>> import io >>> from pymseed import MS3Record >>> with open('examples/example_data.mseed', 'rb') as f: ... data = f.read() >>> total_samples = 0 >>> for msr in MS3Record.from_filelike(io.BytesIO(data), unpack_data=True): ... total_samples += msr.numsamples >>> print(f"Total samples: {total_samples}") Total samples: 12600
With source ID and time-window filtering, a record is selected when it overlaps the requested window:
>>> selected = 0 >>> for msr in MS3Record.from_filelike( ... io.BytesIO(data), ... sourceid="FDSN:IU_COLA_00_L_H_Z", ... starttime="2010-02-27T07:00:00Z", ... endtime="2010-02-27T07:30:00Z", ... ): ... selected += 1 >>> print(f"Selected records: {selected}") Selected records: 15
See also
from_buffer(): Iterate over records in a complete in-memory buffer from_file(): Iterate over records in a file
- classmethod iter_records(source, **kwargs)[source]¶
Iterate over miniSEED records from any source.
This convenience method is a wrapper around the main record reader methods.
stroros.PathLikeorint(file descriptor) →MS3Record.from_file()— C-level file reading, streamingfile-like object (has
.read()) →MS3Record.from_filelike()— chunked.read(), streamingbytes-like object (buffer protocol) →
MS3Record.from_buffer()— contiguous memory, generator
All keyword arguments are forwarded to the underlying method. Common kwargs shared by all three paths:
unpack_data,sourceid,starttime,endtime,validate_crc,verbose.chunk_sizeis forwarded only for file-like sources.Passing
sourceid,starttime, and/orendtimeyields only the records matching the source ID glob pattern and/or overlapping the time window. For file sources the filtering happens entirely inside libmseed; for buffer and file-like sources each record header is parsed in order to be matched, but rejected records are never decoded.- Parameters:
source (Any) – A file path (
str/os.PathLike), an open file descriptor (non-negativeint, e.g. fromos.open()), a file-like object with.read(), or a bytes-like object. Negative integers raiseValueError.**kwargs (Any) – Forwarded to the underlying reader method.
- Yields:
MS3Record – Each parsed record.
- Raises:
MiniSEEDError – If a record cannot be parsed, or if the source ends part way through a record.
TypeError – If source is not a recognised type.
ValueError – If source is a negative integer (not a valid fd).
- Return type:
Examples
>>> record_count = 0 >>> total_samples = 0 >>> for msr in MS3Record.iter_records('examples/example_data.mseed'): ... record_count += 1 ... total_samples += msr.samplecnt >>> print(f"Records: {record_count}, Samples: {total_samples}") Records: 107, Samples: 12600
>>> import io >>> with open('examples/example_data.mseed', 'rb') as f: ... data = f.read() >>> for msr in MS3Record.iter_records(io.BytesIO(data)): ... print(msr) >>> for msr in MS3Record.iter_records(data): ... print(msr)
- classmethod parse(buffer, *, unpack_data=False, validate_crc=True, verbose=0)[source]¶
Parse a single miniSEED record from a buffer.
This method is designed as an optimized path to parse a single miniSEED record from a memory buffer.
- Parameters:
buffer (Any) – Bytes-like object containing a single miniSEED record. Must support the buffer protocol (e.g.
bytes,bytearray,memoryview).unpack_data (bool) – If
True, decode and unpack data samples. Required when the record will be repacked (e.g. format conversion). Default isFalse.validate_crc (bool) – If
True, validate the CRC checksum when present (miniSEED v3 only). Default isTrue.verbose (int) – Verbosity level for libmseed diagnostics. Default is 0.
- Returns:
Fully self-contained record instance.
- Return type:
- Raises:
ValueError – If
bufferdoes not support the buffer protocol.BufferError – If
bufferis not C-contiguous.MiniSEEDError – If the buffer does not contain a complete, valid miniSEED record.
Examples
Parse header metadata only (fastest):
>>> from pymseed import MS3Record >>> with open('examples/example_data.mseed', 'rb') as f: ... raw = f.read(512) # first record >>> msr = MS3Record.parse(raw) >>> msr.sourceid != '' True
Parse with data samples for repacking (v2 to v3 conversion):
>>> with open('examples/example_data.mseed', 'rb') as f: ... raw = f.read(512) >>> msr = MS3Record.parse(raw, unpack_data=True) >>> msr.formatversion = 3 >>> records = list(msr.generate()) >>> len(records) > 0 True
See also
from_buffer(): Iterate over multiple records in a buffer
- parse_into(buffer, *, unpack_data=False, validate_crc=True, verbose=0)[source]¶
Parse a miniSEED record into this existing instance, reusing the C struct.
This is an optimized alternative to
parse()for high-throughput loops where the sameMS3Recordobject is reused across many records. By passing the existing C struct pointer tomsr3_parse, the library can reuse the allocation rather than free and reallocate on every call, eliminating the__init__/__del__overhead in tight loops.- Parameters:
buffer (Any) – Bytes-like object containing a single miniSEED record. Must support the buffer protocol (e.g.
bytes,bytearray,memoryview).unpack_data (bool) – If
True, decode and unpack data samples. Default isFalse.validate_crc (bool) – If
True, validate the CRC checksum when present (miniSEED v3 only). Default isTrue.verbose (int) – Verbosity level for libmseed diagnostics. Default is 0.
- Returns:
self, updated in place with the new record’s fields.- Return type:
- Raises:
MiniSEEDError – If the buffer does not contain a complete, valid miniSEED record.
BufferError – If
bufferis not C-contiguous.ValueError – If
bufferdoes not support the buffer protocol, or if this wrapper does not own its underlying C struct (e.g. it was obtained from an iterator likefrom_buffer(),from_filelike(), orMS3RecordReader, or it is a view into anMS3TraceList). Reparsing into a borrowed struct would silently corrupt the foreign owner’s state.
Example
>>> from pymseed import MS3Record >>> msr = MS3Record() >>> with open('examples/example_data.mseed', 'rb') as f: ... buf = f.read(512) >>> _ = msr.parse_into(buf) >>> msr.samplecnt > 0 True >>> msr.sourceid != '' True
See also
parse(): Classmethod that allocates a new MS3Record per call from_buffer(): Iterate over multiple records in a buffer