MS3RecordValidator

class pymseed.MS3RecordValidator(source, *, return_trace_list=True, unpack_data=True, validate_crc=True, validate_extra_headers=True, extra_headers_schema='FDSN-v1.0', future_data_tolerance=5.0, verbose=0)[source]

Bases: object

Validate miniSEED records with comprehensive error detection.

Processes records from a buffer or file using a 6-step process:

  1. Determine record length (handled by the record source)

  2. Parse record metadata without unpacking data

  3. Optionally check that the record does not contain future data

  4. Optionally validate extra headers

  5. Optionally add record to a trace coverage list (with no data samples)

  6. Optionally decompress data samples and test for decoding errors

This approach ensures maximum information recovery — all records with parseable headers are added to the trace list, with complete error tracking.

Use the factory classmethods from_buffer(), from_file(), or from_filelike() to create instances, then call validate() to run validation.

Parameters:
  • source (_BufferSource | _FileSource | _FileLikeSource) – A record source iterable: _BufferSource, _FileSource, or _FileLikeSource. Use from_buffer(), from_file(), or from_filelike() instead of constructing directly.

  • return_trace_list (bool) – If True, build and return an MS3TraceList.

  • unpack_data (bool) – If True, decompress data samples to detect decoding errors.

  • validate_crc (bool) – If True, validate CRC checksums (miniSEED v3 only).

  • validate_extra_headers (bool) – If True, validate extra headers against a schema.

  • extra_headers_schema (str) – Schema ID for extra headers validation.

  • future_data_tolerance (float | None) – Maximum number of seconds a record’s end time may exceed the system time before it is reported as containing future data. Defaults to 5 seconds, which absorbs ordinary clock skew between the acquisition system and the validating host. Use 0 to report any data past the system time, or None to disable the check. Must be a non-negative, finite number of seconds. The system time is read once per validate() call, and re-read only when a record appears to violate it, so a long-running validation is not measured against a stale clock reading.

  • verbose (int) – Verbosity level for libmseed operations.

Examples

Validate a buffer:

>>> from pymseed import MS3RecordValidator
>>> with open('examples/example_data.mseed', 'rb') as f:
...     buffer = f.read()
>>> errors, traces = MS3RecordValidator.from_buffer(buffer, unpack_data=True).validate()
>>> print(f"Parsed {len(traces)} trace IDs with {len(errors)} errors")
Parsed 3 trace IDs with 0 errors

Validate a file without loading it entirely into memory:

errors, traces = MS3RecordValidator.from_file("data.mseed").validate()

Notes

  • Validation stops only when record length cannot be determined

  • Each error is a ValidationError with offset, message, and optional sourceid, starttime, reclen

  • Not thread-safe. Each thread should use its own MS3RecordValidator instance. The internal record-source iterator, error list, and reused MS3Record C struct have no synchronization. Separate instances running concurrently on separate threads are safe (libmseed’s log registry is thread-local by default).

classmethod from_buffer(buffer, **kwargs)[source]

Create a validator from a miniSEED buffer.

Parameters:
  • buffer (Any) – A buffer-like object containing miniSEED records. Must support the buffer protocol (bytes, bytearray, memoryview, etc.).

  • **kwargs (Any) – Passed to MS3RecordValidator.__init__.

Returns:

A new MS3RecordValidator instance.

Raises:
  • ValueError – If buffer does not support the buffer protocol, raised by validate() when the buffer is read.

  • BufferError – If buffer is not C-contiguous, likewise.

Return type:

MS3RecordValidator

Example:

errors, traces = MS3RecordValidator.from_buffer(buffer, unpack_data=True).validate()
classmethod from_file(filename, *, chunk_size=10485760, **kwargs)[source]

Create a validator for a miniSEED file.

Reads the file in chunks using a sliding buffer, so the entire file does not need to fit in memory.

Parameters:
  • filename (str | PathLike[str]) – Path to miniSEED file. Accepts str or any os.PathLike (e.g. pathlib.Path); other types raise TypeError.

  • chunk_size (int) – Read chunk size in bytes. Default is 10 MiB.

  • **kwargs (Any) – Passed to MS3RecordValidator.__init__.

Returns:

A new MS3RecordValidator instance.

Raises:
Return type:

MS3RecordValidator

Example:

errors, traces = MS3RecordValidator.from_file("data.mseed").validate()
classmethod from_filelike(fh, *, chunk_size=10485760, **kwargs)[source]

Create a validator for a miniSEED file-like stream.

Reads from any object exposing .read(n) -> bytes (e.g. io.BytesIO, sys.stdin.buffer, an HTTP response body, a socket file) using a sliding buffer, so the full stream does not need to fit in memory. The stream is not required to be seekable. The caller retains ownership of fh and is responsible for closing it.

Parameters:
  • fh (Any) – A file-like object with a .read(n) method returning bytes.

  • chunk_size (int) – Read chunk size in bytes. Default is 10 MiB.

  • **kwargs (Any) – Passed to MS3RecordValidator.__init__.

Returns:

A new MS3RecordValidator instance.

Return type:

MS3RecordValidator

Example:

errors, traces = MS3RecordValidator.from_filelike(fh).validate()
validate()[source]

Validate records and return accumulated errors and a trace list.

Returns:

A two-item tuple.

The first item is a list of ValidationError instances describing errors and warnings encountered during parsing.

The second item is an MS3TraceList built from all successfully parsed records; records with validation warnings are included. It is None if return_trace_list=False.

Return type:

tuple[list[ValidationError], MS3TraceList | None]

Note

Validation stops when:

  • All records have been processed

  • Incomplete record at end of source

  • Cannot determine record length

Per-record parse failures are accumulated into the returned errors list.

Setup failures from the underlying source — most commonly OSError (and its subclasses FileNotFoundError, PermissionError, IsADirectoryError) raised when a from_file() source first opens the file — propagate as exceptions, so the caller can distinguish “couldn’t open the source” from “source opened but contained bad records”.