Skip to content

Commit 911f048

Browse files
authored
Update clabe to v0.11 (#576)
* Instrument script * Update dependencies * Close after script is done * Update dependencies on clabe * Launch with terminal * Add defaults to ConfirmRequest prompts * Allow people to bypass metadata generation if recovering session * Pin against release
1 parent 04af942 commit 911f048

4 files changed

Lines changed: 160 additions & 87 deletions

File tree

pyproject.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,8 @@ dev = [
3434
"codespell",
3535
"pytest",
3636
"pytest-cov",
37-
'aind-behavior-vr-foraging[data]',
38-
'aind-behavior-vr-foraging[mappers]',
39-
"aind-clabe >= 0.10.7",
37+
'aind-behavior-vr-foraging[data, mappers]',
38+
"aind-clabe>=0.11.0",
4039
]
4140

4241
[tool.codespell]

scripts/aind.py

Lines changed: 83 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from aind_behavior_services.rig.aind_manipulator import ManipulatorPosition
77
from aind_behavior_services.session import Session
88
from aind_behavior_services.utils import utcnow
9-
from clabe import resource_monitor
9+
from clabe import resource_monitor, ui
1010
from clabe.apps import (
1111
AindBehaviorServicesBonsaiApp,
1212
CurriculumApp,
@@ -46,6 +46,7 @@ async def _run_curriculum_if_applicable(
4646
or (picker.trainer_state.stage is None)
4747
):
4848
return None, None, None
49+
picker.frontend.notify("Running curriculum evaluation…", ui.MessageLevel.INFO)
4950
settings = CurriculumSettings(
5051
input_trainer_state=input_trainer_state_path.resolve(),
5152
data_directory=launcher.session_directory,
@@ -59,8 +60,10 @@ async def _run_curriculum_if_applicable(
5960

6061

6162
def _run_data_qc(picker: DataversePicker, launcher: Launcher) -> None:
62-
if not picker.ui_helper.prompt_yes_no_question(
63-
"Would you like to generate a qc report?"
63+
if not picker.frontend.prompt_confirm(
64+
ui.ConfirmRequest(
65+
label="Would you like to generate a qc report?", default=False
66+
)
6467
):
6568
return
6669
try:
@@ -70,21 +73,26 @@ def _run_data_qc(picker: DataversePicker, launcher: Launcher) -> None:
7073

7174
from aind_behavior_vr_foraging.data_qc.data_qc import make_qc_runner
7275

76+
picker.frontend.notify("Running data QC…", ui.MessageLevel.INFO)
7377
vr_dataset = data_contract.dataset(launcher.session_directory)
7478
runner = make_qc_runner(vr_dataset)
7579
qc_path = launcher.session_directory / "Behavior" / "Logs" / "qc_report.html"
7680
reporter = HtmlReporter(output_path=qc_path)
7781
runner.run_all_with_progress(reporter=reporter)
82+
picker.frontend.notify(f"QC report saved to {qc_path}", ui.MessageLevel.SUCCESS)
7883
webbrowser.open(qc_path.as_uri(), new=2)
7984
except Exception as e:
8085
logger.error("Failed to run data QC: %s", e)
86+
picker.frontend.notify(f"Failed to run data QC: {e}", ui.MessageLevel.ERROR)
8187

8288

8389
def _run_data_transfer(
8490
picker: DataversePicker, launcher: Launcher, session: Session
8591
) -> None:
86-
if not picker.ui_helper.prompt_yes_no_question("Would you like to transfer data?"):
87-
logger.info("Data transfer skipped by user.")
92+
if not picker.frontend.prompt_confirm(
93+
ui.ConfirmRequest(label="Would you like to transfer data?", default=True)
94+
):
95+
picker.frontend.notify("Data transfer skipped.", ui.MessageLevel.WARNING)
8896
return
8997

9098
watchdog_settings = WatchdogSettings()
@@ -106,6 +114,9 @@ def _run_data_transfer(
106114
).transfer()
107115
except Exception as e:
108116
logger.error("Initial data transfer failed: %s", e)
117+
picker.frontend.notify(
118+
f"Initial data transfer failed: {e}", ui.MessageLevel.ERROR
119+
)
109120

110121
WatchdogDataTransferService(
111122
source=launcher.session_directory,
@@ -171,6 +182,9 @@ async def aind_experiment_protocol(launcher: Launcher) -> None:
171182
manipulator_modifier.dump()
172183
except Exception as e:
173184
logger.error("Failed to update manipulator initial position: %s", e)
185+
launcher.frontend.notify(
186+
f"Failed to update manipulator position: {e}", ui.MessageLevel.WARNING
187+
)
174188

175189
# Curriculum
176190
(
@@ -195,6 +209,7 @@ async def aind_experiment_protocol(launcher: Launcher) -> None:
195209
# Mappers
196210
assert launcher.repository.working_tree_dir is not None
197211

212+
launcher.frontend.notify("Running data mappers…", ui.MessageLevel.INFO)
198213
DataMapperCli(
199214
data_path=launcher.session_directory,
200215
repository_path=launcher.repository.working_tree_dir, # type: ignore[arg-type]
@@ -204,6 +219,7 @@ async def aind_experiment_protocol(launcher: Launcher) -> None:
204219
else None,
205220
session_end_time=utcnow(),
206221
).cli_cmd()
222+
launcher.frontend.notify("Data mapping complete.", ui.MessageLevel.SUCCESS)
207223

208224
# Run data qc
209225
_run_data_qc(picker, launcher)
@@ -241,7 +257,9 @@ async def calibration_protocol(launcher: Launcher) -> None:
241257
session=session,
242258
)
243259
await bonsai_app.run_async()
244-
logger.info("Calibration protocol completed successfully.")
260+
launcher.frontend.notify(
261+
"Calibration protocol completed successfully.", ui.MessageLevel.SUCCESS
262+
)
245263

246264

247265
def _dump_suggestion(suggestion: CurriculumSuggestion, session_directory: Path) -> Path:
@@ -287,10 +305,15 @@ async def recover_session(launcher: Launcher) -> None:
287305
# Start experiment setup
288306
picker = DataversePicker(launcher=launcher, settings=_DEFAULT_PICKER_SETTINGS)
289307
session_path = Path(
290-
picker.ui_helper.input("Enter the path to the session you want to recover:")
308+
picker.frontend.prompt_text(
309+
ui.TextRequest(label="Enter the path to the session you want to recover:")
310+
)
291311
)
292312
if not session_path.exists():
293313
logger.error("Session path does not exist: %s", session_path)
314+
launcher.frontend.notify(
315+
f"Session path does not exist: {session_path}", ui.MessageLevel.ERROR
316+
)
294317
return
295318
session_model = Session.model_validate_json(
296319
(session_path / "behavior/Logs/session_input.json").read_text(encoding="utf-8")
@@ -306,37 +329,60 @@ async def recover_session(launcher: Launcher) -> None:
306329

307330
launcher.register_session(session_model, rig_model.data_directory)
308331

309-
# Curriculum
310-
(
311-
suggestion,
312-
suggestion_path,
313-
curriculum_settings,
314-
) = await _run_curriculum_if_applicable(picker, input_trainer_state_path, launcher)
315-
316-
# Mappers
317-
assert launcher.repository.working_tree_dir is not None
318-
319-
session_end_time: datetime.datetime | None = None
320-
while session_end_time is None:
321-
try:
322-
s = launcher.ui_helper.input(
323-
"Enter the session end time in ISO format (YYYY-MM-DDTHH:MM:SSz), e.g: 2024-01-01T12:00:00Z:"
324-
)
325-
session_end_time = datetime.datetime.fromisoformat(s)
326-
except ValueError:
327-
logger.error(
328-
"Invalid date format. Please enter the date in ISO format (YYYY-MM-DDTHH:MM:SSz)."
329-
)
332+
# Curriculum + Mappers
333+
suggestion: CurriculumSuggestion | None = None
334+
suggestion_path: Path | None = None
335+
curriculum_settings: CurriculumSettings | None = None
336+
if picker.frontend.prompt_confirm(
337+
ui.ConfirmRequest(
338+
label="Would you like to run curriculum evaluation and metadata mapping?",
339+
default=True,
340+
)
341+
):
342+
(
343+
suggestion,
344+
suggestion_path,
345+
curriculum_settings,
346+
) = await _run_curriculum_if_applicable(
347+
picker, input_trainer_state_path, launcher
348+
)
330349

331-
DataMapperCli(
332-
data_path=launcher.session_directory,
333-
repository_path=launcher.repository.working_tree_dir, # type: ignore[arg-type]
334-
curriculum_suggestion=suggestion_path,
335-
curriculum_repository_path=curriculum_settings.project_directory
336-
if curriculum_settings
337-
else None,
338-
session_end_time=session_end_time,
339-
).cli_cmd()
350+
assert launcher.repository.working_tree_dir is not None
351+
352+
session_end_time: datetime.datetime | None = None
353+
while session_end_time is None:
354+
try:
355+
s = launcher.frontend.prompt_text(
356+
ui.TextRequest(
357+
label="Enter the session end time in ISO format (YYYY-MM-DDTHH:MM:SSz), e.g: 2024-01-01T12:00:00Z:"
358+
)
359+
)
360+
session_end_time = datetime.datetime.fromisoformat(s)
361+
except ValueError:
362+
logger.error(
363+
"Invalid date format. Please enter the date in ISO format (YYYY-MM-DDTHH:MM:SSz)."
364+
)
365+
launcher.frontend.notify(
366+
"Invalid date format. Please use ISO format (YYYY-MM-DDTHH:MM:SSz).",
367+
ui.MessageLevel.WARNING,
368+
)
369+
370+
launcher.frontend.notify("Running data mappers…", ui.MessageLevel.INFO)
371+
DataMapperCli(
372+
data_path=launcher.session_directory,
373+
repository_path=launcher.repository.working_tree_dir, # type: ignore[arg-type]
374+
curriculum_suggestion=suggestion_path,
375+
curriculum_repository_path=curriculum_settings.project_directory
376+
if curriculum_settings
377+
else None,
378+
session_end_time=session_end_time,
379+
).cli_cmd()
380+
launcher.frontend.notify("Data mapping complete.", ui.MessageLevel.SUCCESS)
381+
else:
382+
picker.frontend.notify(
383+
"Curriculum evaluation and metadata mapping skipped.",
384+
ui.MessageLevel.WARNING,
385+
)
340386

341387
# Run data qc
342388
_run_data_qc(picker, launcher)

scripts/launcher.cmd

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
@echo off
22
setlocal
33
set "scriptPath=%~dp0"
4+
set "repoPath=%scriptPath%.."
45
set "launcherPath=%scriptPath%launcher.ps1"
5-
powershell -ExecutionPolicy Bypass -File "%launcherPath%"
6+
where wt.exe >nul 2>&1
7+
if %errorlevel% == 0 (
8+
wt.exe -d "%repoPath%" powershell -ExecutionPolicy Bypass -File "%launcherPath%"
9+
) else (
10+
powershell -ExecutionPolicy Bypass -File "%launcherPath%"
11+
)
612
endlocal
13+
exit

0 commit comments

Comments
 (0)