diff --git a/environment.yml b/environment.yml index f100c2ee..f120f59c 100644 --- a/environment.yml +++ b/environment.yml @@ -56,7 +56,7 @@ dependencies: - bluesky-adaptive - bluesky >=1.8.1 - ophyd >=1.6.3 - - ophyd-async >= 0.5.1 + - ophyd-async >= 0.6.0 - apstools >= 1.6.20 - pcdsdevices # For extra signal types - pydm >=1.18.0 diff --git a/src/haven/instrument/motor.py b/src/haven/instrument/motor.py index 6afcf19d..1140a6d8 100644 --- a/src/haven/instrument/motor.py +++ b/src/haven/instrument/motor.py @@ -6,10 +6,10 @@ from ophyd import Component as Cpt from ophyd import EpicsMotor, EpicsSignal, EpicsSignalRO, Kind from ophyd_async.core import ( + CALCULATE_TIMEOUT, DEFAULT_TIMEOUT, AsyncStatus, CalculatableTimeout, - CalculateTimeout, ConfigSignal, SignalBackend, SignalX, @@ -36,10 +36,10 @@ def __init__(self, *args, trigger_value=1, **kwargs): super().__init__(*args, **kwargs) def trigger( - self, wait=False, timeout: CalculatableTimeout = CalculateTimeout + self, wait=False, timeout: CalculatableTimeout = CALCULATE_TIMEOUT ) -> AsyncStatus: """Trigger the action and return a status saying when it's done""" - if timeout is CalculateTimeout: + if timeout is CALCULATE_TIMEOUT: timeout = self._timeout coro = self._backend.put(self.trigger_value, wait=wait, timeout=timeout) return AsyncStatus(coro) diff --git a/src/haven/instrument/srs570.py b/src/haven/instrument/srs570.py index c67d05ba..676907d4 100644 --- a/src/haven/instrument/srs570.py +++ b/src/haven/instrument/srs570.py @@ -24,9 +24,9 @@ from typing import Optional, Type from ophyd_async.core import ( + CALCULATE_TIMEOUT, AsyncStatus, CalculatableTimeout, - CalculateTimeout, Device, SignalRW, SubsetEnum, @@ -162,7 +162,7 @@ async def calculate_settle_time(self, value): @AsyncStatus.wrap async def set( - self, value: T, wait=True, timeout: CalculatableTimeout = CalculateTimeout + self, value: T, wait=True, timeout: CalculatableTimeout = CALCULATE_TIMEOUT ) -> AsyncStatus: aw = super().set(value=value, wait=wait, timeout=timeout) if wait: diff --git a/src/haven/motor_position.py b/src/haven/motor_position.py index 5f5a3afb..d8ec4e10 100644 --- a/src/haven/motor_position.py +++ b/src/haven/motor_position.py @@ -8,7 +8,7 @@ from bluesky import plans as bp from pydantic import BaseModel from rich import print as rprint -from tiled.queries import Key +from tiled.queries import Key, Regex from .catalog import Catalog, tiled_client from .instrument.instrument_registry import registry @@ -210,7 +210,10 @@ def get_motor_position(uid: str) -> MotorPosition: async def get_motor_positions( - before: float | None = None, after: float | None = None + before: float | None = None, + after: float | None = None, + name: str | None = None, + case_sensitive: bool = True, ) -> list[MotorPosition]: """Get all motor position objects from the catalog. @@ -222,6 +225,11 @@ async def get_motor_positions( after Only include motor positions recorded after this unix timestamp if provided. + name + A regular expression used to filter motor positions based on + name. + case_sensitive + Whether the regular expression is applied with case-sensitivity. Returns ======= @@ -230,12 +238,19 @@ async def get_motor_positions( """ runs = Catalog(client=tiled_client()) - # Prepare the database for all plans + # Filter only saved motor positions runs = await runs.search(Key("plan_name") == "save_motor_position") + # Filter by timestamp if before is not None: runs = await runs.search(Key("time") < before) if after is not None: runs = await runs.search(Key("time") > after) + # Filter by position name + if name is not None: + runs = await runs.search( + Regex("position_name", name, case_sensitive=case_sensitive) + ) + # Create the actual motor position objects async for uid, run in runs.items(): try: yield await MotorPosition.aload(run) @@ -257,7 +272,6 @@ def recall_motor_position(uid: str): # Create a move plan to recall the position plan_args = [] for axis in position.motors: - print(axis.name) motor = registry.find(name=axis.name) plan_args.append(motor) plan_args.append(axis.readback) diff --git a/src/haven/tests/test_save_motor_positions.py b/src/haven/tests/test_save_motor_positions.py index 3f19c8ba..87f8ef43 100644 --- a/src/haven/tests/test_save_motor_positions.py +++ b/src/haven/tests/test_save_motor_positions.py @@ -94,12 +94,12 @@ }, metadata={ "plan_name": "save_motor_position", - "position_name": "Another good position", + "position_name": "A good position B", "time": 1725897193, "uid": "1b7f2ef5-6a3c-496e-9f6f-f1a4805c0065", "start": { "plan_name": "save_motor_position", - "position_name": "Another good position", + "position_name": "A good position B", "time": 1725897193, "uid": "1b7f2ef5-6a3c-496e-9f6f-f1a4805c0065", }, @@ -131,12 +131,12 @@ }, metadata={ "plan_name": "save_motor_position", - "position_name": "Another good position", + "position_name": "Good position C", "time": 1725897033, "uid": "5dd9a185-d5c4-4c8b-a719-9d7beb9007dc", "start": { "plan_name": "save_motor_position", - "position_name": "Another good position", + "position_name": "Good position C", "time": 1725897033, "uid": "5dd9a185-d5c4-4c8b-a719-9d7beb9007dc", }, @@ -259,6 +259,16 @@ async def test_get_motor_positions(client): assert motorA.uid == "a9b3e0fa-eba1-43e0-a38c-c7ac76278000" +async def test_get_motor_positions_by_name(client): + results = get_motor_positions(name=r"^.*good.+itio.+[AB]$", case_sensitive=False) + results = [pos async for pos in results] + print([r.name for r in results]) + assert len(results) == 2 + # Check the motor position details + motorA, motorB = results + assert motorA.uid == "a9b3e0fa-eba1-43e0-a38c-c7ac76278000" + + def test_recall_motor_position(client, motors): # Re-set the previous value uid = "a9b3e0fa-eba1-43e0-a38c-c7ac76278000"