From 8435f6ae981fd82684e20d6764d5ddf077e0a164 Mon Sep 17 00:00:00 2001 From: Joe Knapper Date: Tue, 10 Feb 2026 18:06:21 +0000 Subject: [PATCH] Move illumination to new IlluminationThing --- ofm_config_full.json | 1 + .../things/illumination.py | 54 +++++++++++++++++++ .../things/stage/sangaboard.py | 37 +------------ 3 files changed, 56 insertions(+), 36 deletions(-) create mode 100644 src/openflexure_microscope_server/things/illumination.py diff --git a/ofm_config_full.json b/ofm_config_full.json index 75534b10..885b65a2 100644 --- a/ofm_config_full.json +++ b/ofm_config_full.json @@ -10,6 +10,7 @@ "autofocus": "openflexure_microscope_server.things.autofocus:AutofocusThing", "camera_stage_mapping": "openflexure_microscope_server.things.camera_stage_mapping:CameraStageMapper", "system": "openflexure_microscope_server.things.system:OpenFlexureSystem", + "illumination": "openflexure_microscope_server.things.illumination:SangaIllumination", "smart_scan": { "class": "openflexure_microscope_server.things.smart_scan:SmartScanThing", "kwargs": { diff --git a/src/openflexure_microscope_server/things/illumination.py b/src/openflexure_microscope_server/things/illumination.py new file mode 100644 index 00000000..39d752e8 --- /dev/null +++ b/src/openflexure_microscope_server/things/illumination.py @@ -0,0 +1,54 @@ +import time +from typing import Literal + +import labthings_fastapi as lt + + +class Illumination(lt.Thing): + """Abstract illumination controller.""" + + brightness: float = lt.property( + default=0.0, + description="Illumination brightness (0-1)", + ) + + @lt.action + def set_brightness(self, brightness: float) -> None: + self.brightness = brightness + + @lt.action + def flash( + self, + number_of_flashes: int = 10, + dt: float = 0.5, + ) -> None: + """Flash the illumination source.""" + for _ in range(number_of_flashes): + self.set_brightness(1.0) + time.sleep(dt) + self.set_brightness(0.0) + time.sleep(dt) + + +class SangaIllumination(Illumination): + """Illumination driven by a Sangaboard.""" + + sangaboard = lt.thing_slot(description="Sangaboard providing LED control") + + @lt.action + def set_brightness(self, brightness: float) -> None: + self.sangaboard.set_led_brightness(brightness) + self.brightness = brightness + + @lt.action + def flash( + self, + number_of_flashes: int = 10, + dt: float = 0.5, + led_channel: Literal["cc"] = "cc", + ) -> None: + for _ in range(number_of_flashes): + self.sangaboard.set_led(True, led_channel) + time.sleep(dt) + self.sangaboard.set_led(False, led_channel) + time.sleep(dt) diff --git a/src/openflexure_microscope_server/things/stage/sangaboard.py b/src/openflexure_microscope_server/things/stage/sangaboard.py index db64ccc3..800a0e31 100644 --- a/src/openflexure_microscope_server/things/stage/sangaboard.py +++ b/src/openflexure_microscope_server/things/stage/sangaboard.py @@ -3,11 +3,10 @@ from __future__ import annotations import threading -import time from contextlib import contextmanager from copy import copy from types import TracebackType -from typing import Any, Iterator, Literal, Optional, Self +from typing import Any, Iterator, Optional, Self import semver @@ -173,37 +172,3 @@ class SangaboardThing(BaseStage): with self.sangaboard() as sb: sb.zero_position() self.update_position() - - @lt.action - def flash_led( - self, - number_of_flashes: int = 10, - dt: float = 0.5, - led_channel: Literal["cc"] = "cc", - ) -> None: - """Flash the LED to identify the board. - - This is intended to be useful in situations where there are multiple - Sangaboards in use, and it is necessary to identify which one is - being addressed. - """ - led_command = f"led_{led_channel}" - with self.sangaboard() as sb: - return_value = sb.query(f"{led_command}?") - if not return_value.startswith("CC LED:"): - raise IOError("The sangaboard does not support LED control") - - # Reading and setting LED brightness suffers from repeated reads and writes - # decreasing the value. Rather than use the value the code warns that the value - # cannot be used. - intended_brightness = float(return_value[7:]) - on_brightness = 0.32 - self.logger.warning( - "Brightness control is not yet implemented. Desired brightness: " - f"{intended_brightness}. Set brightness: {on_brightness}" - ) - for _i in range(number_of_flashes): - sb.query(f"{led_command} 0") - time.sleep(dt) - sb.query(f"{led_command} {on_brightness}") - time.sleep(dt)