| Title: | Versioned, Lineage-Tracked Data Management for the Physio Ecosystem |
|---|---|
| Description: | Integrates the PhysioExperiment ecosystem with 'OmicsLake', a versioned, on-disk data-management engine built on 'DuckDB', 'Apache Arrow' and 'Parquet' with automatic dataset-level lineage tracking. Rather than reimplementing a data lake, PhysioLake inherits the domain-agnostic OmicsLake core (storage backend, snapshots and time-travel, cross-dataset lineage, query layer) and registers physiology-specific adapters and utilities: 'PhysioExperiment' objects are stored and retrieved with full fidelity, preserving the sampling-rate slot and the W3C-PROV provenance held in object metadata. This connects the ecosystem's per-object (micro) provenance with the lake's cross-dataset (macro) lineage. |
| Authors: | Yusuke Matsui [aut, cre] |
| Maintainer: | Yusuke Matsui <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.1.3 |
| Built: | 2026-10-03 13:43:25 UTC |
| Source: | https://github.com/x-biosignal/PhysioLake |
PhysioExperiment adapter for OmicsLake
PhysioExperiment adapter for OmicsLake
An OmicsLake::LakeAdapter that stores and retrieves PhysioExperiment objects in an OmicsLake with full fidelity.
A PhysioExperiment is a SummarizedExperiment subclass with one extra slot
(samplingRate); its provenance, events, and derived estimates live in
metadata(). OmicsLake's generic SEAdapter already round-trips assays,
colData, rowData, and metadata, but it reconstructs a plain
SummarizedExperiment – losing the class identity and the sampling rate.
This adapter inherits SEAdapter and adds only that missing piece: it stashes
the sampling rate in metadata on put() and rebuilds a PhysioExperiment on
get(). Because provenance is carried in metadata(), it survives the round
trip unchanged (verified: provenanceHash() is identical before and after),
so the ecosystem's per-object (micro) W3C-PROV provenance lands intact next to
OmicsLake's cross-dataset (macro) lineage. Assays that are not 2-D matrices
(e.g. epoched time x channel x trial arrays), which the generic SEAdapter
would collapse when storing them as flat tables, are likewise stashed in
metadata and spliced back in their original order on get().
A higher priority() than the generic SEAdapter ensures this adapter is
selected for PhysioExperiment objects (which also satisfy SEAdapter).
An R6 generator for the PhysioExperimentAdapter.
OmicsLake::LakeAdapter -> OmicsLake::SEAdapter -> PhysioExperimentAdapter
name()
Adapter type name.
PhysioExperimentAdapter$name()
can_handle()
Whether this adapter handles data.
PhysioExperimentAdapter$can_handle(data)
dataAn object to test.
priority()
Selection priority (above the generic SummarizedExperiment adapter, which is 100).
PhysioExperimentAdapter$priority()
put()
Store a PhysioExperiment in the lake.
PhysioExperimentAdapter$put(lake, name, data)
lakeAn OmicsLake Lake.
nameObject name.
dataA PhysioExperiment.
get()
Retrieve a PhysioExperiment from the lake.
PhysioExperimentAdapter$get(lake, name, ref = "@latest")
lakeAn OmicsLake Lake.
nameObject name.
refVersion reference (default "@latest").
clone()
The objects of this class are cloneable with this method.
PhysioExperimentAdapter$clone(deep = FALSE)
deepWhether to make a deep clone.
registerPhysioAdapters(), OmicsLake::register_adapter()
if (requireNamespace("OmicsLake", quietly = TRUE)) { adapter <- PhysioExperimentAdapter$new() adapter$name() # "PhysioExperiment" adapter$priority() # 200, above the generic SummarizedExperiment adapter }if (requireNamespace("OmicsLake", quietly = TRUE)) { adapter <- PhysioExperimentAdapter$new() adapter$name() # "PhysioExperiment" adapter$priority() # 200, above the generic SummarizedExperiment adapter }
Returns the companion provenance table written by physioPut().
physioProvenance(lake, name, provenance_suffix = "__prov")physioProvenance(lake, name, provenance_suffix = "__prov")
lake |
An OmicsLake |
name |
Object name. |
provenance_suffix |
Suffix used when storing (default |
A data.frame of the operation DAG (one row per recorded activity), or
NULL if none was stored.
if (requireNamespace("OmicsLake", quietly = TRUE)) { lake <- OmicsLake::Lake$new(basename(tempfile("lake")), root = tempdir()) pe <- PhysioExperiment::PhysioExperiment( assays = list(raw = matrix(as.numeric(1:20), nrow = 10, ncol = 2)), samplingRate = 100 ) physioPut(lake, "subj01", pe) # NULL here because this object carries no recorded op-DAG. physioProvenance(lake, "subj01") }if (requireNamespace("OmicsLake", quietly = TRUE)) { lake <- OmicsLake::Lake$new(basename(tempfile("lake")), root = tempdir()) pe <- PhysioExperiment::PhysioExperiment( assays = list(raw = matrix(as.numeric(1:20), nrow = 10, ncol = 2)), samplingRate = 100 ) physioPut(lake, "subj01", pe) # NULL here because this object carries no recorded op-DAG. physioProvenance(lake, "subj01") }
Wraps OmicsLake::Lake's put() so that the object's W3C-PROV operation DAG
(from PhysioExperiment::provenance()) is stored as a queryable companion table and
recorded as a lineage dependency of the object (via put(..., depends_on =)). The ecosystem's per-object (micro) provenance thus becomes a first-class
node in OmicsLake's cross-dataset (macro) lineage, visible to lake$tree(),
lake$deps(), and lake$impact().
physioPut(lake, name, x, tags = "physio", provenance_suffix = "__prov")physioPut(lake, name, x, tags = "physio", provenance_suffix = "__prov")
lake |
An OmicsLake |
name |
Object name. |
x |
A Physio object, e.g. a PhysioExperiment. |
tags |
Character tags for the object (default |
provenance_suffix |
Suffix for the companion provenance table
(default |
Objects that carry no provenance are stored normally (no companion table).
Invisibly, the provenance table's name, or NA_character_ if the
object carried no provenance.
if (requireNamespace("OmicsLake", quietly = TRUE)) { lake <- OmicsLake::Lake$new(basename(tempfile("lake")), root = tempdir()) pe <- PhysioExperiment::PhysioExperiment( assays = list(raw = matrix(as.numeric(1:20), nrow = 10, ncol = 2)), samplingRate = 100 ) physioPut(lake, "subj01", pe) restored <- lake$get("subj01") # a PhysioExperiment again PhysioExperiment::samplingRate(restored) }if (requireNamespace("OmicsLake", quietly = TRUE)) { lake <- OmicsLake::Lake$new(basename(tempfile("lake")), root = tempdir()) pe <- PhysioExperiment::PhysioExperiment( assays = list(raw = matrix(as.numeric(1:20), nrow = 10, ncol = 2)), samplingRate = 100 ) physioPut(lake, "subj01", pe) restored <- lake$get("subj01") # a PhysioExperiment again PhysioExperiment::samplingRate(restored) }
Stores the parts of a run bundle (e.g. the frozen pre-registration, the run
manifest, the operation DAG, the terminal artifact, the claims registry, the
verification report) as individual OmicsLake entries under a common prefix,
wired together with lineage edges so the run's internal structure is queryable
via lake$tree() / lake$deps(). Combined with lake$snap(), a whole run
becomes a versioned, lineage-tracked lake object — giving the substrate the
persistent, queryable store it otherwise lacks (it content-addresses runs but
does not persist them).
physioPutBundle(lake, name, components, edges = list(), tags = "run-bundle")physioPutBundle(lake, name, components, edges = list(), tags = "run-bundle")
lake |
An OmicsLake |
name |
Bundle name; used as the entry prefix ( |
components |
Named list of bundle parts. |
edges |
Named list: for each component key, a character vector of the component keys it depends on (a within-bundle lineage DAG). |
tags |
Character tags applied to every entry (default |
data.frame components are stored as queryable tables; other objects are
serialised. Components are stored parents-first (topological order over
edges) so each depends_on target already exists.
Invisibly, a named character vector mapping each component key to its stored lake entry name.
if (requireNamespace("OmicsLake", quietly = TRUE)) { lake <- OmicsLake::Lake$new(basename(tempfile("lake")), root = tempdir()) components <- list( prereg = data.frame(key = "alpha", value = 1), result = data.frame(metric = "hr", value = 72) ) # `result` depends on `prereg`; the bundle stores that lineage edge. physioPutBundle(lake, "run001", components, edges = list(result = "prereg")) lake$deps("run001__result") }if (requireNamespace("OmicsLake", quietly = TRUE)) { lake <- OmicsLake::Lake$new(basename(tempfile("lake")), root = tempdir()) components <- list( prereg = data.frame(key = "alpha", value = 1), result = data.frame(metric = "hr", value = 72) ) # `result` depends on `prereg`; the bundle stores that lineage edge. physioPutBundle(lake, "run001", components, edges = list(result = "prereg")) lake$deps("run001__result") }
Registers PhysioLake's adapters (currently PhysioExperimentAdapter) with the
OmicsLake adapter registry so that lake$put() / lake$get() handle Physio
objects automatically. Called on package load; exported so it can be re-run
after OmicsLake::clear_adapters().
registerPhysioAdapters()registerPhysioAdapters()
Invisibly TRUE.
if (requireNamespace("OmicsLake", quietly = TRUE)) { # Re-run after OmicsLake::clear_adapters(); also called on package load. registerPhysioAdapters() }if (requireNamespace("OmicsLake", quietly = TRUE)) { # Re-run after OmicsLake::clear_adapters(); also called on package load. registerPhysioAdapters() }