from pathlib import Path
import dascore as dc
patch = dc.get_example_patch()
path = Path("output_file.h5")
patch.io.write(path, "DASDAE")
round_trip = dc.spool(path)[0]Working with Files
DASCore reads and writes local pathlib.Path objects and remote UPath resources supported by each format. See Working with remote patches for cache policy.
Writing and reading
Write through Patch.io, then open the result as a spool:
Remote destinations use the same interface through universal-pathlib, whose UPath objects support URLs implemented by fsspec:
from upath import UPath
remote_path = UPath("memory://dascore/tutorial/output.pkl")
patch.io.write(remote_path, "pickle")
remote_patch = dc.spool(remote_path)[0]Format support varies by backend: a formatter that requires a local seekable file may use the remote cache, while formats built on fsspec-compatible stores can operate directly.
Scanning metadata
dc.scan returns PatchSummary objects without loading patch arrays.
summary_index = 0
summary = dc.scan("examples://terra15_das_1_trimmed.hdf5")[summary_index]
print(summary.source_path)
print(summary.get_coord_summary("time").min)/home/runner/work/dascore/dascore/.test_data_cache/0.0.0/terra15_das_1_trimmed.hdf5
2021-10-11T22:43:37.380047104
Scanning also reports source_format, source_version, and source_patch_key, which together identify the formatter and patch inside a multi-patch file.
Use the source path and the summary’s position to load the same patch through its spool. Scan results and file-spool rows have the same order, and the spool uses each row’s source_patch_key when materializing it. For compact directory listings, use scan or scan_to_df.
source_spool = dc.spool(
summary.source_path,
file_format=summary.source_format,
file_version=summary.source_version,
)
loaded = source_spool[summary_index]dc.scan_payloads(...) also returns each formatter’s CoordManager. With snap=False, formats that store per-sample coordinates expose their exact values:
payload = dc.scan_payloads(summary.source_path, snap=False)[0]
time = payload["coords"].get_coord("time")Payload scans still may read and retain large coordinate arrays, so reserve them for targeted files.
Patch.attrs contains non-coordinate metadata. Access coordinate bounds and steps from Patch.summary, PatchSummary.get_coord_summary(...), or the flattened summary returned by flat_dump().
Directory spools
dc.spool(directory) creates a lazy, indexed view of every supported file below that directory:
from dascore import examples
directory = examples.spool_to_directory(dc.get_example_spool("diverse_das"))
spool = (
dc.spool(directory)
.select(acquisition_key="DAS2.*")
.select(time=(..., "2022-01-01"))
.chunk(time=2, overlap=0.5)
)Iteration is where patch arrays are loaded:
for patch in spool:
processed = patch.detrend("time")The hidden .dascore_index.sqlite3 stores file metadata and enables selections before patch data is loaded. Opening a new directory creates the index; call spool.update() after files change. See the spool tutorial and index note for path attributes and index lifecycle.
update() scans new or modified files, removes rows for deleted files, and leaves unchanged rows alone. File size and modification time identify candidates for rescanning.
An optional .inventory companion describes the observing system and is not scanned as data.
The index and inventory are companions to the archive rather than data sources themselves, so both use reserved hidden names and are excluded from formatter discovery.
External formats
Patch.io also converts patches to structures used by Pandas, Xarray, and ObsPy. See the external conversion recipe.