66from aind_behavior_services .rig .aind_manipulator import ManipulatorPosition
77from aind_behavior_services .session import Session
88from aind_behavior_services .utils import utcnow
9- from clabe import resource_monitor
9+ from clabe import resource_monitor , ui
1010from 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
6162def _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
8389def _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
247265def _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 )
0 commit comments