From c70338e4fbdb63c49a2b93c3b9cbaa535a5ffcdd Mon Sep 17 00:00:00 2001 From: Keith Ralphs Date: Tue, 11 Jun 2024 11:47:57 +0000 Subject: [PATCH 1/4] Use attach_session_metadata decorator --- pyproject.toml | 1 + src/dls_bluesky_core/plans/wrapped.py | 33 +++++++++++++-------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 786f46e..c9b902f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,7 @@ dependencies = [ "ophyd", "ophyd_async", "scanspec", + "dls-dodal", ] # Add project dependencies here, e.g. ["click", "numpy"] dynamic = ["version"] license.file = "LICENSE" diff --git a/src/dls_bluesky_core/plans/wrapped.py b/src/dls_bluesky_core/plans/wrapped.py index 5d914fd..82e5cf9 100644 --- a/src/dls_bluesky_core/plans/wrapped.py +++ b/src/dls_bluesky_core/plans/wrapped.py @@ -1,10 +1,13 @@ from typing import Any, List, Mapping, Optional, Union import bluesky.plans as bp +import bluesky.preprocessors as bpp from bluesky.protocols import Readable from dls_bluesky_core.core import MsgGenerator +from dodal.plans.data_session_metadata import attach_data_session_metadata_decorator + """ Wrappers for Bluesky built-in plans with type hinting and renamed metadata """ @@ -14,6 +17,7 @@ def count( detectors: List[Readable], num: int = 1, delay: Optional[Union[float, List[float]]] = None, + baseline: Optional[List[Readable]] = None, metadata: Optional[Mapping[str, Any]] = None, ) -> MsgGenerator: """ @@ -21,10 +25,11 @@ def count( Args: detectors (List[Readable]): Readable devices to read - num (int, optional): Number of readings to take. Defaults to 1. - delay (Optional[Union[float, List[float]]], optional): Delay between readings. + num (int): Number of readings to take. Defaults to 1. + delay (Optional[Union[float, List[float]]]): Delay between readings. Defaults to None. - metadata (Optional[Mapping[str, Any]], optional): Key-value metadata to include + baseline (Optional[List[Readable]]): List of devices to read at start and end of scan + metadata (Optional[Mapping[str, Any]]): Key-value metadata to include in exported data. Defaults to None. @@ -34,17 +39,11 @@ def count( Yields: Iterator[MsgGenerator]: _description_ """ - plan_args = ( - { # If bp.count added delay to plan_args, we could remove all md handling - "detectors": list(map(repr, detectors)), - "num": num, - "delay": delay, - } - ) - - _md = { - "plan_args": plan_args, - **(metadata or {}), - } - - yield from bp.count(detectors, num, delay=delay, md=_md) + baseline = baseline or [] + + @bpp.baseline_decorator(baseline) + @attach_data_session_metadata_decorator(provider=None) + def inner_plan(): + yield from bp.count(detectors, num, delay=delay, md=metadata) + + yield from inner_plan() From 8e2128f6620d6557ce2338d4673eae5962fccd58 Mon Sep 17 00:00:00 2001 From: Keith Ralphs Date: Tue, 11 Jun 2024 12:56:50 +0000 Subject: [PATCH 2/4] linting --- src/dls_bluesky_core/plans/wrapped.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/dls_bluesky_core/plans/wrapped.py b/src/dls_bluesky_core/plans/wrapped.py index 82e5cf9..3a29c36 100644 --- a/src/dls_bluesky_core/plans/wrapped.py +++ b/src/dls_bluesky_core/plans/wrapped.py @@ -3,11 +3,10 @@ import bluesky.plans as bp import bluesky.preprocessors as bpp from bluesky.protocols import Readable +from dodal.plans.data_session_metadata import attach_data_session_metadata_decorator from dls_bluesky_core.core import MsgGenerator -from dodal.plans.data_session_metadata import attach_data_session_metadata_decorator - """ Wrappers for Bluesky built-in plans with type hinting and renamed metadata """ @@ -27,11 +26,12 @@ def count( detectors (List[Readable]): Readable devices to read num (int): Number of readings to take. Defaults to 1. delay (Optional[Union[float, List[float]]]): Delay between readings. - Defaults to None. - baseline (Optional[List[Readable]]): List of devices to read at start and end of scan + Defaults to None. + baseline (Optional[List[Readable]]): List of devices to read at start + and end of scan metadata (Optional[Mapping[str, Any]]): Key-value metadata to include - in exported data. - Defaults to None. + in exported data. + Defaults to None. Returns: MsgGenerator: _description_ @@ -43,7 +43,7 @@ def count( @bpp.baseline_decorator(baseline) @attach_data_session_metadata_decorator(provider=None) - def inner_plan(): + def inner_plan() -> MsgGenerator: yield from bp.count(detectors, num, delay=delay, md=metadata) yield from inner_plan() From 80356d97a8f0514f8301bf33fcf0a584da6601c0 Mon Sep 17 00:00:00 2001 From: Keith Ralphs Date: Tue, 11 Jun 2024 13:12:18 +0000 Subject: [PATCH 3/4] further liniting --- tests/test_boilerplate_removed.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_boilerplate_removed.py b/tests/test_boilerplate_removed.py index b7632d0..ff71e40 100644 --- a/tests/test_boilerplate_removed.py +++ b/tests/test_boilerplate_removed.py @@ -2,6 +2,7 @@ This file checks that all the example boilerplate text has been removed. It can be deleted when all the contained tests pass """ + import sys from pathlib import Path From ff2459bd8990433b0a531a3d96bf398c32c7c318 Mon Sep 17 00:00:00 2001 From: Keith Ralphs Date: Wed, 12 Jun 2024 08:33:52 +0000 Subject: [PATCH 4/4] Delete obsolete plan and test and remove pythoon 3.9 compatibility --- .../actions/install_requirements/action.yml | 2 +- .github/workflows/code.yml | 2 +- pyproject.toml | 3 +- src/dls_bluesky_core/stubs/flyables.py | 60 ------------------- tests/stubs/test_flyables.py | 54 ----------------- 5 files changed, 3 insertions(+), 118 deletions(-) delete mode 100644 src/dls_bluesky_core/stubs/flyables.py delete mode 100644 tests/stubs/test_flyables.py diff --git a/.github/actions/install_requirements/action.yml b/.github/actions/install_requirements/action.yml index f9c986d..5145fa4 100644 --- a/.github/actions/install_requirements/action.yml +++ b/.github/actions/install_requirements/action.yml @@ -9,7 +9,7 @@ inputs: required: true python_version: description: Python version to install - default: "3.9" + default: "3.11" runs: using: composite diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index b0b4de6..ede6a68 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -32,7 +32,7 @@ jobs: fail-fast: false matrix: os: ["ubuntu-latest"] # can add windows-latest, macos-latest - python: ["3.9", "3.10", "3.11"] + python: ["3.10", "3.11"] install: [".[dev]", "-e .[dev]"] runs-on: ${{ matrix.os }} diff --git a/pyproject.toml b/pyproject.toml index c9b902f..eb7f8d7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,6 @@ name = "dls-bluesky-core" classifiers = [ "Development Status :: 3 - Alpha", "License :: OSI Approved :: Apache Software License", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", ] @@ -21,7 +20,7 @@ dependencies = [ dynamic = ["version"] license.file = "LICENSE" readme = "README.rst" -requires-python = ">=3.9" +requires-python = ">=3.10" [project.optional-dependencies] dev = [ diff --git a/src/dls_bluesky_core/stubs/flyables.py b/src/dls_bluesky_core/stubs/flyables.py deleted file mode 100644 index 41acacb..0000000 --- a/src/dls_bluesky_core/stubs/flyables.py +++ /dev/null @@ -1,60 +0,0 @@ -import bluesky.plan_stubs as bps -from bluesky.protocols import Flyable - -from dls_bluesky_core.core import MsgGenerator, group_uuid - - -def fly_and_collect( - flyer: Flyable, - flush_period: float = 0.5, - checkpoint_every_collect: bool = False, - stream_name: str = "primary", -) -> MsgGenerator: - """Fly and collect a flyer, waiting for collect to finish with a period. - - flyer.kickoff and complete are called, which starts the fly scanning process. - bps.wait is called, which finishes after each flush period and then repeats, until - complete finishes. At this point, bps.collect is called to gather the documents - produced. - - For some flyers, this plan will need to be called in succession in order to, for - example, set up a flyer to send triggers multiple times and collect data. For such - a use case, this plan can be setup to checkpoint for each collect. - - Note: this plan must be wrapped with calls to open and close run, and the flyer - must implement the Collectable protocol. See tests/stubs/test_flyables for an - example. - - Args: - flyer (Flyable, Collectable): ophyd-async device which implements Flyable and - Collectable. - flush_period (float): How often to check if flyer.complete has finished. - Defaults to 0.5 - checkpoint_every_collect (bool): whether or not to checkpoint after - flyer.collect has been called. Defaults to - False. - stream_name (str): name of the stream to collect from. Defaults to "primary". - - - Returns: - MsgGenerator: Plan - - Yields: - Iterator[MsgGenerator]: Bluesky messages - """ - yield from bps.kickoff(flyer) - complete_group = group_uuid("complete") - yield from bps.complete(flyer, group=complete_group) - done = False - while not done: - try: - yield from bps.wait(group=complete_group, timeout=flush_period) - except TimeoutError: - pass - else: - done = True - yield from bps.collect( - flyer, stream=True, return_payload=False, name=stream_name - ) - if checkpoint_every_collect: - yield from bps.checkpoint() diff --git a/tests/stubs/test_flyables.py b/tests/stubs/test_flyables.py deleted file mode 100644 index 366b2a0..0000000 --- a/tests/stubs/test_flyables.py +++ /dev/null @@ -1,54 +0,0 @@ -import asyncio -from typing import Dict - -import bluesky.plan_stubs as bps -import pytest -from bluesky.protocols import Collectable, Descriptor, Flyable -from ophyd_async.core import AsyncStatus - -from dls_bluesky_core.stubs.flyables import fly_and_collect - - -class DummyFlyer(Flyable, Collectable): - def __init__(self, name: str) -> None: - self._name = name - self.has_flown = False - - @property - def name(self) -> str: - return self._name - - @AsyncStatus.wrap - async def kickoff(self) -> None: - self._fly_status = AsyncStatus(self._fly()) - - async def _fly(self) -> None: - self.has_flown = True - await asyncio.sleep(0.1) - - def complete(self) -> AsyncStatus: - return self._fly_status - - def describe_collect(self) -> Dict[str, Descriptor]: - return { - self.name: Descriptor( - source="some:source", shape=[], dtype="array", external="STREAM:" - ) - } - - -@pytest.fixture -def flyer() -> Flyable: - return DummyFlyer("test") - - -async def test_fly_and_collect(RE, flyer: DummyFlyer): - def open_and_close_run_for_fly_and_collect(): - yield from bps.open_run() - yield from fly_and_collect( - flyer, flush_period=0.01, checkpoint_every_collect=True - ) - yield from bps.close_run() - - RE(open_and_close_run_for_fly_and_collect()) - assert flyer.has_flown is True