Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test ophyd async speedup #895

Merged
merged 44 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
9f75e38
Make pyright happy
rtuck99 Oct 4, 2024
e67444d
Remove get_processing_result()
rtuck99 Oct 10, 2024
02b9f23
Changes to support extracting the results from the event
rtuck99 Oct 14, 2024
7a5445a
Fix InvocationError due to usage of missing attribute centres_of_mass
rtuck99 Oct 23, 2024
ce5c634
Misc enum fixes, remove timeout from expected call args
rtuck99 Oct 22, 2024
2328324
Most unit tests now working
rtuck99 Oct 22, 2024
f6186ff
Pin to current head of ophyd-async PR branch
rtuck99 Oct 22, 2024
e688086
Re-enable disabled test now that naming is fixed
rtuck99 Oct 22, 2024
379c493
Fix various type linting issues
rtuck99 Oct 22, 2024
ba3beac
Fix panda instantiations
rtuck99 Oct 23, 2024
6be7cf6
Make private signals public
rtuck99 Oct 23, 2024
f665eb6
Change PMAC string signals to Movable devices
rtuck99 Oct 23, 2024
0396d23
Repin to latest ophyd-async branch
rtuck99 Oct 23, 2024
ee62dc9
Fix enum type for fluorescence detector
rtuck99 Oct 23, 2024
7cf58fb
Fix AperturePositions enum
rtuck99 Oct 25, 2024
3f1cec1
Fix more panda uri/prefix changes, beamstop enum
rtuck99 Oct 25, 2024
6f6d897
Fix PMAC to use new Reference wrapper
rtuck99 Oct 29, 2024
1ec93d6
Fix Thawer to use new Reference wrapper
rtuck99 Oct 29, 2024
14aba8b
Fix OAV to redis forwarder signal types
rtuck99 Oct 29, 2024
0467c38
Allow I10 devices to accept float64 from bluesky scan() plan
rtuck99 Oct 29, 2024
8469a37
Revert panda uri changes back to prefix
rtuck99 Oct 29, 2024
e02138f
Misc I10 fixes for ophyd-async type changes
rtuck99 Oct 29, 2024
7a89200
Revert uri/prefix mangling in device_instantiation()
rtuck99 Oct 29, 2024
2ed9ec3
Fix I10 unit tests by flattening devices
rtuck99 Oct 29, 2024
6441f1b
Make type-checking happy
rtuck99 Oct 29, 2024
9e19d2e
bump ophyd-async hash
rtuck99 Oct 29, 2024
aedc595
Remove nonsensical fgs counter mock set
rtuck99 Oct 29, 2024
12731a8
Bump dodal commit hash
rtuck99 Oct 29, 2024
643f3cc
Bump ophyd-async hash
rtuck99 Oct 30, 2024
da1e43b
Fix connection issue due to typing on xspress3
rtuck99 Oct 30, 2024
2397f4a
Document the aperturescatterguard radius. Make the attenuator fields …
rtuck99 Oct 30, 2024
7453069
Make mirror voltage attribs private again
rtuck99 Oct 31, 2024
a545004
Remove unneeded lint ignore
rtuck99 Oct 31, 2024
90cf17d
Make zebra shutter manual_position_setpoint private again
rtuck99 Oct 31, 2024
228cbde
Update comment with reference to the correct ophyd-async issue
rtuck99 Oct 31, 2024
4361da5
Remove superfluous calls to add_children_as_readables() in i10 device…
rtuck99 Oct 31, 2024
3136e41
Pin dodal to >=0.8.0a1
rtuck99 Oct 31, 2024
45fbfa2
Fix usage of deprecated ConfigSignal, HintedSignal etc in favour of S…
rtuck99 Nov 1, 2024
7dffb4e
Remove ignores for now-fixed deprecation warnings in ophyd-async, pin…
rtuck99 Nov 4, 2024
4d2bdc5
Merge branch 'main' into fixes_for_declarative_epics
DominicOram Nov 8, 2024
bac94f3
Pin to correct ophyd-async
DominicOram Nov 8, 2024
f8157dc
Fix tests against the faster ophyd-async
DominicOram Nov 8, 2024
511c4e9
Merge branch 'main' into test_ophyd_async_speedup
DominicOram Nov 12, 2024
de596e3
Remove accidentally added file
DominicOram Nov 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ description = "Ophyd devices and other utils that could be used across DLS beaml
dependencies = [
"click",
"ophyd",
"ophyd-async==0.8.0a3",
"ophyd-async==0.8.0a4",
"bluesky",
"pyepics",
"dataclasses-json",
Expand Down
40 changes: 21 additions & 19 deletions src/dodal/devices/apple2_undulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from bluesky.protocols import Movable
from ophyd_async.core import (
AsyncStatus,
Reference,
StandardReadable,
StandardReadableFormat,
StrictEnum,
Expand Down Expand Up @@ -387,9 +388,9 @@ def __init__(

# Attributes are set after super call so they are not renamed to
# <name>-undulator, etc.
with self.add_children_as_readables():
self.gap = id_gap
self.phase = id_phase
self.gap = Reference(id_gap)
self.phase = Reference(id_phase)

with self.add_children_as_readables(StandardReadableFormat.HINTED_SIGNAL):
# Store the polarisation for readback.
self.polarisation, self._polarisation_set = soft_signal_r_and_setter(
Expand Down Expand Up @@ -436,27 +437,29 @@ async def _set(self, value: Apple2Val, energy: float) -> None:
"""

# Only need to check gap as the phase motors share both fault and gate with gap.
await self.gap.check_id_status()
await self.gap().check_id_status()
await asyncio.gather(
self.phase.top_outer.user_setpoint.set(value=value.top_outer),
self.phase.top_inner.user_setpoint.set(value=value.top_inner),
self.phase.btm_inner.user_setpoint.set(value=value.btm_inner),
self.phase.btm_outer.user_setpoint.set(value=value.btm_outer),
self.gap.user_setpoint.set(value=value.gap),
self.phase().top_outer.user_setpoint.set(value=value.top_outer),
self.phase().top_inner.user_setpoint.set(value=value.top_inner),
self.phase().btm_inner.user_setpoint.set(value=value.btm_inner),
self.phase().btm_outer.user_setpoint.set(value=value.btm_outer),
self.gap().user_setpoint.set(value=value.gap),
)
timeout = np.max(
await asyncio.gather(self.gap.get_timeout(), self.phase.get_timeout())
await asyncio.gather(self.gap().get_timeout(), self.phase().get_timeout())
)
LOGGER.info(
f"Moving f{self.name} energy and polorisation to {energy}, {self.pol}"
+ f"with motor position {value}, timeout = {timeout}"
)

await asyncio.gather(
self.gap.set_move.set(value=1, timeout=timeout),
self.phase.set_move.set(value=1, timeout=timeout),
self.gap().set_move.set(value=1, timeout=timeout),
self.phase().set_move.set(value=1, timeout=timeout),
)
await wait_for_value(
self.gap().gate, UndulatorGateStatus.close, timeout=timeout
)
await wait_for_value(self.gap.gate, UndulatorGateStatus.close, timeout=timeout)
self._energy_set(energy) # Update energy for after move for readback.

def _get_id_gap_phase(self, energy: float) -> tuple[float, float]:
Expand Down Expand Up @@ -521,12 +524,11 @@ async def determinePhaseFromHardware(self) -> tuple[str | None, float]:
(May be for future one can use the inverse poly to work out the energy and try to match it with the current energy
to workout the polarisation but during my test the inverse poly is too unstable for general use.)
"""
cur_loc = await self.read()
top_outer = cur_loc[self.phase.top_outer.user_setpoint_readback.name]["value"]
top_inner = cur_loc[self.phase.top_inner.user_setpoint_readback.name]["value"]
btm_inner = cur_loc[self.phase.btm_inner.user_setpoint_readback.name]["value"]
btm_outer = cur_loc[self.phase.btm_outer.user_setpoint_readback.name]["value"]
gap = cur_loc[self.gap.user_readback.name]["value"]
top_outer = await self.phase().top_outer.user_setpoint_readback.get_value()
top_inner = await self.phase().top_inner.user_setpoint_readback.get_value()
btm_inner = await self.phase().btm_inner.user_setpoint_readback.get_value()
btm_outer = await self.phase().btm_outer.user_setpoint_readback.get_value()
gap = await self.gap().user_readback.get_value()
if gap > MAXIMUM_GAP_MOTOR_POSITION:
raise RuntimeError(
f"{self.name} is not in use, close gap or set polarisation to use this ID"
Expand Down
8 changes: 4 additions & 4 deletions src/dodal/devices/i10/i10_apple2.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def __init__(
name=name,
)
with self.add_children_as_readables():
self.id_jaw_phase = id_jaw_phase
self.id_jaw_phase = Reference(id_jaw_phase)

@AsyncStatus.wrap
async def set(self, value: SupportsFloat) -> None:
Expand Down Expand Up @@ -148,8 +148,8 @@ async def set(self, value: SupportsFloat) -> None:
LOGGER.info(f"Setting polarisation to {self.pol}, with {id_set_val}")
await self._set(value=id_set_val, energy=value)
if self.pol != "la":
await self.id_jaw_phase.set(0)
await self.id_jaw_phase.set_move.set(1)
await self.id_jaw_phase().set(0)
await self.id_jaw_phase().set_move.set(1)

def update_lookuptable(self):
"""
Expand Down Expand Up @@ -299,7 +299,7 @@ async def set(self, value: SupportsFloat) -> None:
f"jaw_phase position for angle ({value}) is outside permitted range"
f" [-{self.jaw_phase_limit}, {self.jaw_phase_limit}]"
)
await self.id_ref().id_jaw_phase.set(jaw_phase)
await self.id_ref().id_jaw_phase().set(jaw_phase)
self._angle_set(value)


Expand Down
4 changes: 2 additions & 2 deletions src/dodal/devices/oav/oav_detector.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from enum import IntEnum

from ophyd_async.core import DEFAULT_TIMEOUT, AsyncStatus, StandardReadable
from ophyd_async.core import DEFAULT_TIMEOUT, AsyncStatus, LazyMock, StandardReadable
from ophyd_async.epics.core import epics_signal_rw

from dodal.common.signal_utils import create_hardware_backed_soft_signal
Expand Down Expand Up @@ -118,7 +118,7 @@ async def _get_beam_position(self, coord: int) -> int:

async def connect(
self,
mock: bool = False,
mock: bool | LazyMock = False,
timeout: float = DEFAULT_TIMEOUT,
force_reconnect: bool = False,
):
Expand Down
32 changes: 16 additions & 16 deletions tests/devices/i10/test_i10Apple2.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,10 @@ async def test_I10Apple2_determine_pol(
btm_inner_phase: float,
btm_outer_phase: float,
):
set_mock_value(mock_id.phase.top_inner.user_setpoint_readback, top_inner_phase)
set_mock_value(mock_id.phase.top_outer.user_setpoint_readback, top_outer_phase)
set_mock_value(mock_id.phase.btm_inner.user_setpoint_readback, btm_inner_phase)
set_mock_value(mock_id.phase.btm_outer.user_setpoint_readback, btm_outer_phase)
set_mock_value(mock_id.phase().top_inner.user_setpoint_readback, top_inner_phase)
set_mock_value(mock_id.phase().top_outer.user_setpoint_readback, top_outer_phase)
set_mock_value(mock_id.phase().btm_inner.user_setpoint_readback, btm_inner_phase)
set_mock_value(mock_id.phase().btm_outer.user_setpoint_readback, btm_outer_phase)

if pol is None:
with pytest.raises(ValueError):
Expand Down Expand Up @@ -234,7 +234,7 @@ async def test_fail_I10Apple2_set_lookup_gap_pol(mock_id: I10Apple2):


async def test_fail_I10Apple2_set_undefined_pol(mock_id: I10Apple2):
set_mock_value(mock_id.gap.user_readback, 101)
set_mock_value(mock_id.gap().user_readback, 101)
with pytest.raises(RuntimeError) as e:
await mock_id.set(600)
assert (
Expand All @@ -244,15 +244,15 @@ async def test_fail_I10Apple2_set_undefined_pol(mock_id: I10Apple2):


async def test_fail_I10Apple2_set_id_not_ready(mock_id: I10Apple2):
set_mock_value(mock_id.gap.fault, 1)
set_mock_value(mock_id.gap().fault, 1)
with pytest.raises(RuntimeError) as e:
await mock_id.set(600)
assert str(e.value) == mock_id.gap.name + " is in fault state"
set_mock_value(mock_id.gap.fault, 0)
set_mock_value(mock_id.gap.gate, UndulatorGateStatus.open)
assert str(e.value) == mock_id.gap().name + " is in fault state"
set_mock_value(mock_id.gap().fault, 0)
set_mock_value(mock_id.gap().gate, UndulatorGateStatus.open)
with pytest.raises(RuntimeError) as e:
await mock_id.set(600)
assert str(e.value) == mock_id.gap.name + " is already in motion."
assert str(e.value) == mock_id.gap().name + " is already in motion."


async def test_I10Apple2_RE_scan(mock_id: I10Apple2, RE: RunEngine):
Expand Down Expand Up @@ -341,23 +341,23 @@ async def test_I10Apple2_pol_set(
else:
await mock_id_pol.set(pol)
assert mock_id_pol.id.pol == pol
top_inner = get_mock_put(mock_id_pol.id.phase.top_inner.user_setpoint)
top_inner = get_mock_put(mock_id_pol.id.phase().top_inner.user_setpoint)
top_inner.assert_called_once()
assert float(top_inner.call_args[0][0]) == pytest.approx(expect_top_inner, 0.01)

top_outer = get_mock_put(mock_id_pol.id.phase.top_outer.user_setpoint)
top_outer = get_mock_put(mock_id_pol.id.phase().top_outer.user_setpoint)
top_outer.assert_called_once()
assert float(top_outer.call_args[0][0]) == pytest.approx(expect_top_outer, 0.01)

btm_inner = get_mock_put(mock_id_pol.id.phase.btm_inner.user_setpoint)
btm_inner = get_mock_put(mock_id_pol.id.phase().btm_inner.user_setpoint)
btm_inner.assert_called_once()
assert float(btm_inner.call_args[0][0]) == pytest.approx(expect_btm_inner, 0.01)

btm_outer = get_mock_put(mock_id_pol.id.phase.btm_outer.user_setpoint)
btm_outer = get_mock_put(mock_id_pol.id.phase().btm_outer.user_setpoint)
btm_outer.assert_called_once()
assert float(btm_outer.call_args[0][0]) == pytest.approx(expect_btm_outer, 0.01)

gap = get_mock_put(mock_id_pol.id.gap.user_setpoint)
gap = get_mock_put(mock_id_pol.id.gap().user_setpoint)
gap.assert_called_once()
assert float(gap.call_args[0][0]) == pytest.approx(expect_gap, 0.05)

Expand Down Expand Up @@ -428,7 +428,7 @@ def capture_emitted(name, doc):
assert_emitted(docs, start=1, descriptor=1, event=num_point, stop=1)

jaw_phase = get_mock_put(
mock_linear_arbitrary_angle.id_ref().id_jaw_phase.jaw_phase.user_setpoint
mock_linear_arbitrary_angle.id_ref().id_jaw_phase().jaw_phase.user_setpoint
)

poly = poly1d(
Expand Down
Loading