Source code for src.data_acquisition.experiment_runner.experiment_runner
from logging import Logger
from typing import Callable, Generic, Optional, TypeVar
from unittest.mock import MagicMock
from ..eventful_screen import EventfulScreen
from ..gui import Gui
from ..sequencers import ScreenSequencer
from .errors import ExperimentRunnerError
T = TypeVar("T")
[docs]
class ExperimentRunner(Generic[T]):
def __init__(
self,
*,
gui: Gui,
screen_sequencer: ScreenSequencer[T],
end_callback: Callable[[], None] = lambda: None,
logger: Optional[Logger] = None,
) -> None:
self._gui = gui
self._gui.on_init(self._mark_as_should_run)
self._screen_sequencer = screen_sequencer
self._previous_screen: Optional[EventfulScreen[T]] = None
self._end_callback = end_callback
self._logger = logger if logger is not None else MagicMock()
self._should_run = False
self._is_running = True
def _mark_as_should_run(self):
self._should_run = True
[docs]
def run(self) -> None:
while not self._should_run:
pass
self._log("Starting experiment")
self._run_first_screen()
while self._is_running:
pass
self._end_callback()
def _log(self, message: str) -> None:
self._logger.info(f"{self.__class__.__name__}: {message}")
def _run_first_screen(self) -> None:
first_screen = self._screen_sequencer.get_next()
self._log(f"Showing a screen")
self._previous_screen = first_screen
first_screen.show(end_callback=self._go_to_next_screen)
def _go_to_next_screen(self, result: T) -> None:
if self._previous_screen is None:
raise ExperimentRunnerError("No previous screen found.")
self._previous_screen.exit()
self._screen_sequencer.pass_previous_result(result)
try:
next_screen = self._screen_sequencer.get_next()
except StopIteration:
self._is_running = False
return
self._log(f"Showing a screen")
self._previous_screen = next_screen
next_screen.show(end_callback=self._go_to_next_screen)