fix(frontend): EEG default path points at fixture (HF container has no data/raw/eeg.fif)
Browse files- src/frontend/app.py +9 -1
- tests/frontend/test_app_defaults.py +44 -0
src/frontend/app.py
CHANGED
|
@@ -1197,7 +1197,15 @@ def _render_eeg_tab() -> None:
|
|
| 1197 |
"ICA decomposition, and extracts per-band PSD + statistical features "
|
| 1198 |
"across fixed-duration epochs.",
|
| 1199 |
)
|
| 1200 |
-
eeg_in = st.text_input(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1201 |
eeg_out = st.text_input(
|
| 1202 |
"Output Parquet path",
|
| 1203 |
"data/processed/eeg_features.parquet",
|
|
|
|
| 1197 |
"ICA decomposition, and extracts per-band PSD + statistical features "
|
| 1198 |
"across fixed-duration epochs.",
|
| 1199 |
)
|
| 1200 |
+
eeg_in = st.text_input(
|
| 1201 |
+
"Input FIF/EDF path",
|
| 1202 |
+
"tests/fixtures/eeg_sample.fif",
|
| 1203 |
+
key="eeg_in",
|
| 1204 |
+
help=(
|
| 1205 |
+
"Defaults to the bundled EEG fixture so the demo runs out of "
|
| 1206 |
+
"the box. Replace with your own .fif/.edf path on a real run."
|
| 1207 |
+
),
|
| 1208 |
+
)
|
| 1209 |
eeg_out = st.text_input(
|
| 1210 |
"Output Parquet path",
|
| 1211 |
"data/processed/eeg_features.parquet",
|
tests/frontend/test_app_defaults.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Defaults shown in the Streamlit UI must point at files that actually exist
|
| 2 |
+
in the deployed image. The HF container does not seed `data/raw/eeg.fif`
|
| 3 |
+
unless we explicitly do so in the Dockerfile, so the EEG tab default must
|
| 4 |
+
either be a fixture file (always present) or be seeded server-side.
|
| 5 |
+
"""
|
| 6 |
+
from __future__ import annotations
|
| 7 |
+
|
| 8 |
+
from pathlib import Path
|
| 9 |
+
import re
|
| 10 |
+
|
| 11 |
+
REPO_ROOT = Path(__file__).resolve().parents[2]
|
| 12 |
+
APP_PY = REPO_ROOT / "src" / "frontend" / "app.py"
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
def _eeg_default_path() -> str:
|
| 16 |
+
"""Extract the default value passed to the EEG `input_path` text_input.
|
| 17 |
+
|
| 18 |
+
The line looks like:
|
| 19 |
+
eeg_in = st.text_input("Input FIF/EDF path", "tests/fixtures/eeg_sample.fif", key="eeg_in")
|
| 20 |
+
We pull the second positional arg (the default value).
|
| 21 |
+
"""
|
| 22 |
+
text = APP_PY.read_text()
|
| 23 |
+
match = re.search(
|
| 24 |
+
r'st\.text_input\(\s*"Input FIF/EDF path"\s*,\s*"([^"]+)"',
|
| 25 |
+
text,
|
| 26 |
+
)
|
| 27 |
+
assert match is not None, "could not locate EEG text_input default in app.py"
|
| 28 |
+
return match.group(1)
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def test_eeg_default_path_points_at_existing_file() -> None:
|
| 32 |
+
default = _eeg_default_path()
|
| 33 |
+
abs_path = REPO_ROOT / default
|
| 34 |
+
assert abs_path.exists(), (
|
| 35 |
+
f"EEG default path {default!r} resolves to {abs_path} which does "
|
| 36 |
+
f"not exist on disk. The HF container does not seed this path "
|
| 37 |
+
f"either, so users get an HTTP 404 the moment they click Run."
|
| 38 |
+
)
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def test_eeg_default_path_is_eeg_sample_fixture() -> None:
|
| 42 |
+
"""Pin the exact fix: default must be the canonical fixture so both
|
| 43 |
+
local dev and the deployed image agree."""
|
| 44 |
+
assert _eeg_default_path() == "tests/fixtures/eeg_sample.fif"
|