Skip to content

Commit 74a5067

Browse files
committed
add the option of accessing previous pipelines results in the h5file
1 parent 653493a commit 74a5067

3 files changed

Lines changed: 90 additions & 0 deletions

File tree

src/eye_flow.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,45 @@ def get(self, key: str, default=None):
117117
return default
118118

119119

120+
class _EyeFlowView:
121+
def __init__(self, work_h5: h5py.File) -> None:
122+
self.work_h5 = work_h5
123+
124+
def _pipeline_group_names(self) -> list[str]:
125+
eye_flow_group = self.work_h5.get("EyeFlow")
126+
if not isinstance(eye_flow_group, h5py.Group):
127+
return []
128+
return list(eye_flow_group.keys())
129+
130+
def get(self, key: str, default=None):
131+
normalized_key = _normalize_h5_lookup_path(key)
132+
if not normalized_key:
133+
return default
134+
135+
explicit = self.work_h5.get(f"EyeFlow/{normalized_key}")
136+
if explicit is not None:
137+
return explicit
138+
139+
for pipeline_group_name in reversed(self._pipeline_group_names()):
140+
candidate = self.work_h5.get(
141+
f"EyeFlow/{pipeline_group_name}/{normalized_key}"
142+
)
143+
if candidate is not None:
144+
return candidate
145+
return default
146+
147+
def __getitem__(self, key: str):
148+
found = self.get(key)
149+
if found is None:
150+
raise KeyError(key)
151+
return found
152+
153+
def __contains__(self, key: object) -> bool:
154+
if not isinstance(key, str):
155+
return False
156+
return self.get(key) is not None
157+
158+
120159
class _PipelineInputView:
121160
def __init__(
122161
self,
@@ -132,6 +171,7 @@ def __init__(
132171
self.work = work_h5
133172
self.hd = holodoppler_h5
134173
self.dv = doppler_vision_h5
174+
self.ef = _EyeFlowView(work_h5)
135175
self.preferred_input = preferred_input
136176
self.attrs = _MergedAttrs(
137177
self.work_h5,

src/pipelines/dual_input_tutorial.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class DualInputTutorial(ProcessPipeline):
1515
- `h5file.hd`: the holodoppler input handle
1616
- `h5file.dv`: the doppler vision input handle
1717
- `h5file.work`: the current EyeFlow output/work file
18+
- `h5file.ef`: previous EyeFlow pipeline outputs, searchable via `h5file.ef["path"]`
1819
"""
1920

2021
description = "Tutorial: read HD and DV inputs simultaneously in one pipeline."

test/test_dual_input_tutorial.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,55 @@ def test_pipeline_reads_hd_and_dv_inputs_together(self) -> None:
9292
result.attrs["dv_example_path"],
9393
)
9494

95+
def test_eye_flow_proxy_resolves_previous_pipeline_outputs(self) -> None:
96+
with tempfile.TemporaryDirectory() as tmp_dir:
97+
tmp_path = Path(tmp_dir)
98+
hd_path = tmp_path / "sample_holodoppler.h5"
99+
dv_path = tmp_path / "sample_doppler_vision.h5"
100+
work_path = tmp_path / "work.h5"
101+
102+
with h5py.File(hd_path, "w") as hd_h5:
103+
hd_h5.create_dataset("moment0", data=np.array([1.0], dtype=float))
104+
105+
with h5py.File(dv_path, "w") as dv_h5:
106+
dv_h5.create_dataset("Meta/example", data=np.array([2.0], dtype=float))
107+
108+
with h5py.File(work_path, "w") as work_h5:
109+
eye_flow = work_h5.create_group("EyeFlow")
110+
previous = eye_flow.create_group("first_pipeline")
111+
previous.create_dataset(
112+
"summary/value",
113+
data=np.array([11.0], dtype=float),
114+
)
115+
latest = eye_flow.create_group("second_pipeline")
116+
latest.create_dataset(
117+
"summary/value",
118+
data=np.array([22.0], dtype=float),
119+
)
120+
latest.create_dataset(
121+
"other/path",
122+
data=np.array([33.0], dtype=float),
123+
)
124+
125+
with (
126+
h5py.File(work_path, "r") as work_h5,
127+
h5py.File(hd_path, "r") as hd_h5,
128+
h5py.File(dv_path, "r") as dv_h5,
129+
):
130+
input_view = _PipelineInputView(
131+
work_h5=work_h5,
132+
holodoppler_h5=hd_h5,
133+
doppler_vision_h5=dv_h5,
134+
)
135+
136+
latest_value = np.asarray(input_view.ef["summary/value"])
137+
explicit_value = np.asarray(
138+
input_view.ef["second_pipeline/other/path"]
139+
)
140+
141+
np.testing.assert_allclose(latest_value, np.array([22.0], dtype=float))
142+
np.testing.assert_allclose(explicit_value, np.array([33.0], dtype=float))
143+
95144

96145
if __name__ == "__main__":
97146
unittest.main()

0 commit comments

Comments
 (0)