Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dascore/data_registry.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ terra15_v6_test_file.hdf5 63f130ed93c1fe4105f2a355272d136a51abfe5c212a40be3a2907
iDAS005_hdf5_example.626.h5 28f4f9b1f2b248fa0419b41c11e971f2d395c3ed43afc1ef5d5c35f399e99190 https://github.com/dasdae/test_data/raw/master/das/iDAS005_hdf5_example.626.h5
iDAS005_tdms_example.626.tdms 0c31f75015bc671d958967c7fdf32e2e64fdb467f997d331ae6a7d4c989ab380 https://github.com/dasdae/test_data/raw/master/das/iDAS005_tdms_example.626.tdms
sample_tdms_file_v4713.tdms 22a79c4c3166ce3cc8467265540cdb3ad2b54460209d39641c1e8f20e64eca65 https://github.com/dasdae/test_data/raw/master/das/sample_tdms_file_v4713.tdms
etna_9n_3chan_10s.mseed e79608a6aa47cd0b70fa227679bc5d266af117ea4bc3e02e0c336c563b35b280 https://github.com/DASDAE/test_data/raw/master/das/etna_9n_3chan_10s.mseed
example_dasdae_event_1.h5 854530af7ea10bab54dd0f6458c5d67d8b334ee6e4032b75702fa408352b5007 https://github.com/dasdae/test_data/raw/master/das/example_dasdae_event_1.h5
opta_sense_quantx_v2.h5 fca8c8b19a9e253f9252c14de3f2a7778391a763f39142fffc63ab0cc3fa9cc7 https://github.com/dasdae/test_data/raw/master/das/opta_sense_quantx_v2.h5
prodml_2.0.h5 8f8eded106acab0b4266c5c752cc702363cb09391f5fddf1534429e94e4e9ab2 https://github.com/dasdae/test_data/raw/master/das/prodml_2.0.h5
Expand Down
5 changes: 5 additions & 0 deletions dascore/io/mseed/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""DASCore support for MiniSEED files."""

from __future__ import annotations

from dascore.io.mseed.core import MSeedV2, MSeedV3
81 changes: 81 additions & 0 deletions dascore/io/mseed/core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
"""IO support for MiniSEED files.

DASCore maps MiniSEED source IDs into 2D ``("channel", "time")`` patches.
MiniSEED source identity is preserved as per-channel coordinates instead of
scalar attrs because one DASCore patch can contain many MiniSEED sources.
The preserved source coordinates are ``source_id``, ``network``, ``station``,
``location``, and ``seed_channel``.

Compatible MiniSEED sources are merged into one patch when they share the same
format version, network, location, SEED channel, start time, sample rate, and
sample count. Sources with different sample rates, start times, or sample
counts are returned as separate patches. When sources split across multiple
patches, DASCore keeps stable integer ``channel`` coordinate values so
selections still refer to the same source.

The MiniSEED ``channel`` coordinate is an integer source index, not optical
distance. Optical distance is usually stored in companion DAS metadata rather
than MiniSEED record headers and should be attached from that metadata when
available.

The mapping follows the FDSN source identifier convention, where a SEED NSLC
code maps to ``FDSN:<network>_<station>_<location>_<band>_<source>_<subsource>``.
See https://docs.fdsn.org/projects/source-identifiers/en/latest/definition.html.

For DAS MiniSEED, GEOFON recommends representing each fiber sampling point as
a station because each sampling point has its own position; the channel code
``HSF`` is recommended for fiber optic DAS. See
https://geofon.gfz.de/redmine/projects/redmine/wiki/DAS.
"""

from __future__ import annotations

import dascore as dc
from dascore.constants import opt_timeable_types
from dascore.io import FiberIO, ScanPayload
from dascore.utils.io import LocalPath
from dascore.utils.misc import optional_import

from .utils import _detect_format, _get_patches, _scan_patches


class MSeedV2(FiberIO):
"""Support MiniSEED version 2 files."""

name = "MSEED"
preferred_extensions = ("mseed", "msd", "miniseed")
version = "2"

def get_format(self, resource: LocalPath, **kwargs) -> tuple[str, str] | bool:
"""Determine if path is a MiniSEED file."""
return _detect_format(resource)

def scan(self, resource: LocalPath, **kwargs) -> list[ScanPayload]:
"""Scan a MiniSEED file."""
pymseed = optional_import("pymseed")
return _scan_patches(resource, pymseed)

def read(
self,
resource: LocalPath,
time: tuple[opt_timeable_types, opt_timeable_types] | None = None,
channel: tuple[int | None, int | None] | None = None,
source_patch_id=(),
**kwargs,
) -> dc.BaseSpool:
"""Read a MiniSEED file."""
pymseed = optional_import("pymseed")
patches = _get_patches(
resource,
pymseed,
time=time,
channel=channel,
source_patch_id=source_patch_id,
)
return dc.spool(patches)


class MSeedV3(MSeedV2):
"""Support MiniSEED version 3 files."""

version = "3"
Loading
Loading