diff --git a/pyproject.toml b/pyproject.toml index 7c6dcd1..a89f47b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,11 +11,15 @@ classifiers = [ "Programming Language :: Python :: 3.11", ] description = "visible light experiments at the ViSR mini-beamline" -dependencies = [] # Add project dependencies here, e.g. ["click", "numpy"] +dependencies = [ + "dls_dodal @ git+https://github.com/DiamondLightSource/dodal", + "ophyd_async", + "numpy<2.0.0", +] # Add project dependencies here, e.g. ["click", "numpy"] dynamic = ["version"] license.file = "LICENSE" readme = "README.md" -requires-python = ">=3.7" +requires-python = ">=3.10" [project.optional-dependencies] dev = [ diff --git a/src/visr/devices/mirror.py b/src/visr/devices/mirror.py new file mode 100644 index 0000000..70d716b --- /dev/null +++ b/src/visr/devices/mirror.py @@ -0,0 +1,8 @@ +from ophyd_async.epics.motion import Motor + + +class Mirror(Motor): + def __init__(self, prefix: str, name: str = "") -> None: + self.prefix = prefix + super().__init__(name) + self._mirror = None diff --git a/src/visr/devices/stage2d.py b/src/visr/devices/stage2d.py new file mode 100644 index 0000000..5cc9234 --- /dev/null +++ b/src/visr/devices/stage2d.py @@ -0,0 +1,9 @@ +from ophyd_async.epics.signal import epics_signal_rw + + +class Stage2d: + def __init__(self, prefix: str, name: str = "") -> None: + self.x = epics_signal_rw(name + "_x", prefix + ":x") + self.y = epics_signal_rw(name + "_y", prefix + ":y") + self.prefix = prefix + super().__init__(name) diff --git a/src/visr/plans/basic_plan.py b/src/visr/plans/basic_plan.py new file mode 100644 index 0000000..04bfc13 --- /dev/null +++ b/src/visr/plans/basic_plan.py @@ -0,0 +1,66 @@ +from pathlib import Path +from typing import Any + +import bluesky.preprocessors as bpp +from dodal.common import MsgGenerator, inject +from ophyd_async.core import HardwareTriggeredFlyable, StandardDetector +from ophyd_async.core.device_save_loader import Device, load_device +from ophyd_async.panda import HDFPanda, StaticSeqTableTriggerLogic + +DEFAULT_WEBCAM = inject("webcam") +DEFAULT_PANDA = inject("panda1") + +ROOT_CONFIG_SAVES_DIR = Path(__file__).parent.parent.parent / "pvs" / "basic_plan" + + +def basic_plan( + panda: HDFPanda = DEFAULT_PANDA, + metadata: dict[str, Any] | None = None, + webcam: Device = DEFAULT_WEBCAM, + exposure: float = 1.0, +) -> MsgGenerator: + """ + Description + + + Args: + panda: PandA for controlling flyable motion + exposure: exposure time of detectors + metadata: metadata: Key-value metadata to include in exported data, + defaults to None. + + Returns: + MsgGenerator: Plan + + Yields: + Iterator[MsgGenerator]: Bluesky messages + """ + detectors = {webcam} + + plan_args = { + "exposure": exposure, + "panda": repr(panda), + } + _md = { + "detectors": {device.name for device in detectors}, + "motors": {linkam.name}, + "plan_args": plan_args, + # TODO: Can we pass dimensional hint? motors? shape? + "hints": {}, + } + _md.update(metadata or {}) + + for device in detectors: + yield from load_device(device, ROOT_CONFIG_SAVES_DIR / device.__name__) + + load_device(panda, ROOT_CONFIG_SAVES_DIR, panda.__name__) + + devices = detectors + + @bpp.stage_decorator(devices) + @bpp.run_decorator(md=_md) + def inner_plan(): + yield from {} + + rs_uid = yield from inner_plan() + return rs_uid