From 57b20782a0a2d0eb2e2edaa1a0f90f8f56e61511 Mon Sep 17 00:00:00 2001 From: Julian Stirling Date: Fri, 16 Jan 2026 13:04:23 +0000 Subject: [PATCH] Further fixes after introducing scan workflow selection --- ofm_config_full.json | 3 ++- .../things/smart_scan.py | 27 ++++++++++++------- tests/unit_tests/test_smart_scan.py | 5 +++- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/ofm_config_full.json b/ofm_config_full.json index 19b9e89a..50e0fa7c 100644 --- a/ofm_config_full.json +++ b/ofm_config_full.json @@ -13,7 +13,8 @@ "smart_scan": { "class": "openflexure_microscope_server.things.smart_scan:SmartScanThing", "kwargs": { - "scans_folder": "/var/openflexure/scans/" + "scans_folder": "/var/openflexure/scans/", + "default_workflow": "histo_scan_workflow" } }, "histo_scan_workflow": "openflexure_microscope_server.things.scan_workflows:HistoScanWorkflow", diff --git a/src/openflexure_microscope_server/things/smart_scan.py b/src/openflexure_microscope_server/things/smart_scan.py index 2a44474a..c415a9c5 100644 --- a/src/openflexure_microscope_server/things/smart_scan.py +++ b/src/openflexure_microscope_server/things/smart_scan.py @@ -135,7 +135,7 @@ class SmartScanThing(lt.Thing): self, thing_server_interface: lt.ThingServerInterface, scans_folder: str, - default_workflow: Optional[str], + default_workflow: str, ) -> None: """Initialise a SmartScanThing saving to and loading from the input directory. @@ -147,21 +147,27 @@ class SmartScanThing(lt.Thing): self._scan_dir_manager = scan_directories.ScanDirectoryManager(scans_folder) self._scan_lock = threading.Lock() self._default_workflow = default_workflow - self._workflow_name: Optional[str] = None + self._workflow_name = default_workflow def __enter__(self) -> Self: """Open hardware connection when the Thing context manager is opened.""" - self._workflow_name = coerce_thing_selector( + valid_name = coerce_thing_selector( thing_mapping=self._all_workflows, selected=self.workflow_name, default=self._default_workflow, ) + if valid_name is None: + raise RuntimeError( + "Could not set Scan Workflow. A Scan Workflow must be present in your " + "configuration." + ) + self._workflow_name = valid_name return self # Note that the default detector name is set at init. This is over written if # setting is loaded from disk. @lt.setting - def workflow_name(self) -> Optional[str]: + def workflow_name(self) -> str: """The name of the scan workflow selector.""" return self._workflow_name @@ -222,13 +228,14 @@ class SmartScanThing(lt.Thing): if not got_lock: raise RuntimeError("Trying to run scan while scan is already running!") - # `scan_data` should already be None. This is added as a precaution as - # the presence of `scan_data` is used during error handling to - # determine whether the scan started. - self._scan_data = None - # probably make workflow a context manager with a lock? - workflow = self._workflow try: + # `scan_data` should already be None. This is added as a precaution as + # the presence of `scan_data` is used during error handling to + # determine whether the scan started. + self._scan_data = None + # probably make workflow a context manager with a lock? + workflow = self._workflow + workflow.check_before_start(scan_name) self._ongoing_scan = self._scan_dir_manager.new_scan_dir(scan_name) self._latest_scan_name = self.ongoing_scan.name diff --git a/tests/unit_tests/test_smart_scan.py b/tests/unit_tests/test_smart_scan.py index 21901f7c..14220f85 100644 --- a/tests/unit_tests/test_smart_scan.py +++ b/tests/unit_tests/test_smart_scan.py @@ -50,7 +50,10 @@ def _clear_scan_dir() -> None: def smart_scan_thing(): """Return a smart scan thing as a fixture.""" return create_thing_without_server( - SmartScanThing, scans_folder=SCAN_DIR, mock_all_slots=True + SmartScanThing, + scans_folder=SCAN_DIR, + default_workflow="mock-_all_workflows", + mock_all_slots=True )