Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -53,7 +53,7 @@ dependencies = [
"daq-config-server >= 1.3.0",
"blueapi >= 1.12.0",
"ophyd >= 1.10.5",
"ophyd-async >= 0.16.0",
"ophyd-async >= 0.17a4",
"bluesky >= 1.14.6",
"dls-dodal @ git+https://github.com/DiamondLightSource/dodal.git@main",
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ def event(self, doc: dict): # type: ignore
self.wavelength_in_a = data.get("dcm-wavelength_in_a")
self.energy_in_kev = data.get("dcm-energy_in_keV")
self.detector_distance_mm = data.get("detector_motion-z")
assert data.get("detector-_writer-file_path"), (
assert data.get("detector-writer-file_path"), (
"No detector writer path was found"
)
self.final_path = Path(data.get("detector-_writer-file_path"))
self.final_path = Path(data.get("detector-writer-file_path"))

LOGGER.info(
f"Metadata writer received parameters, energy_in_kev: {self.energy_in_kev}, wavelength: {self.wavelength_in_a}, det_distance_mm: {self.detector_distance_mm}, file path: {self.final_path}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
from dodal.devices.attenuator.attenuator import EnumFilterAttenuator
from dodal.devices.beamlines.i24.aperture import Aperture
from dodal.devices.beamlines.i24.beamstop import Beamstop
from dodal.devices.beamlines.i24.commissioning_jungfrau import CommissioningJungfrau
from dodal.devices.beamlines.i24.commissioning_jungfrau import (
CommissioningJungfrauDetector,
)
from dodal.devices.beamlines.i24.dcm import DCM
from dodal.devices.beamlines.i24.dual_backlight import DualBacklight
from dodal.devices.beamlines.i24.vgonio import VerticalGoniometer
Expand All @@ -22,7 +24,7 @@ class RotationScanComposite:

aperture: Aperture
attenuator: EnumFilterAttenuator
jungfrau: CommissioningJungfrau
jungfrau: CommissioningJungfrauDetector
gonio: VerticalGoniometer
synchrotron: Synchrotron
sample_shutter: ZebraShutter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
from bluesky import plan_stubs as bps
from bluesky.utils import MsgGenerator
from dodal.common import inject
from dodal.devices.beamlines.i24.commissioning_jungfrau import CommissioningJungfrau
from dodal.devices.beamlines.i24.commissioning_jungfrau import (
CommissioningJungfrauDetector,
)
from ophyd_async.fastcs.jungfrau import (
AcquisitionType,
GainMode,
Expand All @@ -25,7 +27,7 @@ def do_pedestal_darks(
pedestal_frames: PositiveInt = 20,
pedestal_loops: PositiveInt = 200,
filename: str = "pedestal_darks",
jungfrau: CommissioningJungfrau = inject("jungfrau"),
jungfrau: CommissioningJungfrauDetector = inject("jungfrau"),
) -> MsgGenerator:
"""Acquire darks in pedestal mode, using dynamic gain mode. This calibrates the offsets
for the jungfrau, and must be performed before acquiring real data in dynamic gain mode.
Expand Down Expand Up @@ -61,11 +63,13 @@ def _do_decorated_plan():
trigger_info = create_jungfrau_pedestal_triggering_info(
exp_time_s, pedestal_frames, pedestal_loops
)
yield from bps.mv(jungfrau.detector.pedestal_mode_loops, pedestal_loops)
yield from bps.mv(jungfrau.detector.pedestal_mode_frames, pedestal_frames)
LOGGER.info(
"Jungfrau will be triggered in pedestal mode and in dynamic gain mode"
)
yield from bps.mv(
jungfrau.drv.acquisition_type,
jungfrau.acquisition_type,
AcquisitionType.PEDESTAL,
)
yield from fly_jungfrau(
Expand All @@ -84,7 +88,7 @@ def do_non_pedestal_darks(
exp_time_s: float = 0.001,
total_triggers: PositiveInt = 1000,
filename: str = "darks",
jungfrau: CommissioningJungfrau = inject("jungfrau"),
jungfrau: CommissioningJungfrauDetector = inject("jungfrau"),
) -> MsgGenerator:
"""Internally take a set of images at a given gain mode.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
from bluesky.utils import MsgGenerator
from dodal.devices.beamlines.i24.aperture import AperturePositions
from dodal.devices.beamlines.i24.beamstop import BeamstopPositions
from dodal.devices.beamlines.i24.commissioning_jungfrau import CommissioningJungfrau
from dodal.devices.beamlines.i24.commissioning_jungfrau import (
CommissioningJungfrauDetector,
)
from dodal.devices.beamlines.i24.dual_backlight import BacklightPositions
from dodal.devices.hutch_shutter import ShutterState
from dodal.devices.zebra.zebra import ArmDemand, I24Axes, Zebra
Expand Down Expand Up @@ -238,7 +240,7 @@ def _rotation_scan_plan(
composite.dcm.energy_in_keV,
composite.dcm.wavelength_in_a,
composite.det_stage.z,
composite.jungfrau._writer.file_path, # noqa: SLF001 N
composite.jungfrau.writer.file_path, # noqa: SLF001 N
],
PlanNameConstants.ROTATION_DEVICE_READ,
)
Expand Down Expand Up @@ -280,7 +282,7 @@ def _rotation_scan_plan(

def _cleanup_plan(
zebra: Zebra,
jf: CommissioningJungfrau,
jf: CommissioningJungfrauDetector,
zebra_shutter: ZebraShutter,
group="rotation cleanup",
):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from bluesky.utils import MsgGenerator
from dodal.common import inject
from dodal.devices.beamlines.i24.commissioning_jungfrau import CommissioningJungfrau
from dodal.devices.beamlines.i24.commissioning_jungfrau import (
CommissioningJungfrauDetector,
)
from ophyd_async.core import (
WatchableAsyncStatus,
)
Expand All @@ -20,7 +22,7 @@ def do_external_acquisition(
gain_mode: GainMode,
total_triggers: PositiveInt = 1,
wait: bool = False,
jungfrau: CommissioningJungfrau = inject("commissioning_jungfrau"),
jungfrau: CommissioningJungfrauDetector = inject("commissioning_jungfrau"),
) -> MsgGenerator[WatchableAsyncStatus]:
"""
Kickoff external triggering on the Jungfrau, and optionally wait for completion.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from bluesky.utils import MsgGenerator
from dodal.beamlines.i24 import CommissioningJungfrau
from dodal.beamlines.i24 import CommissioningJungfrauDetector
from dodal.common import inject
from ophyd_async.core import (
WatchableAsyncStatus,
Expand All @@ -19,7 +19,7 @@ def do_internal_acquisition(
exp_time_s: float,
gain_mode: GainMode,
total_frames: PositiveInt = 1,
jungfrau: CommissioningJungfrau = inject("jungfrau"),
jungfrau: CommissioningJungfrauDetector = inject("jungfrau"),
path_of_output_file: str | None = None,
wait: bool = False,
) -> MsgGenerator[WatchableAsyncStatus]:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import bluesky.plan_stubs as bps
from bluesky.utils import MsgGenerator
from dodal.common.watcher_utils import log_on_percentage_complete
from dodal.devices.beamlines.i24.commissioning_jungfrau import CommissioningJungfrau
from dodal.devices.beamlines.i24.commissioning_jungfrau import (
CommissioningJungfrauDetector,
)
from ophyd_async.core import (
TriggerInfo,
WatchableAsyncStatus,
Expand All @@ -17,7 +19,7 @@


def fly_jungfrau(
jungfrau: CommissioningJungfrau,
jungfrau: CommissioningJungfrauDetector,
trigger_info: TriggerInfo,
gain_mode: GainMode,
wait: bool = False,
Expand All @@ -43,7 +45,7 @@ def fly_jungfrau(
"""

LOGGER.info(f"Setting Jungfrau to gain mode {gain_mode}")
yield from bps.mv(jungfrau.drv.gain_mode, gain_mode)
yield from bps.mv(jungfrau.detector.gain_mode, gain_mode)
LOGGER.info("Preparing detector...")
yield from bps.prepare(jungfrau, trigger_info, wait=True)
LOGGER.info("Detector prepared")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ async def test_metadata_writer_produces_correct_output(
await rotation_composite.dcm.wavelength_in_a.set(wavelength)
await rotation_composite.dcm.energy_in_keV.set(energy)
await rotation_composite.det_stage.z.set(det_z)
await rotation_composite.jungfrau._writer.file_path.set(tmp_path)
await rotation_composite.jungfrau.writer.file_path.set(tmp_path)

expected_output = {
"wavelength_in_a": wavelength,
Expand All @@ -54,7 +54,7 @@ async def test_metadata_writer_produces_correct_output(
rotation_composite.dcm.energy_in_keV,
rotation_composite.dcm.wavelength_in_a,
rotation_composite.det_stage.z,
rotation_composite.jungfrau._writer.file_path,
rotation_composite.jungfrau.writer.file_path,
],
params,
metadata_writer,
Expand Down Expand Up @@ -90,7 +90,7 @@ async def test_assertion_error_if_no_jf_path_found(
rotation_composite.dcm.energy_in_keV,
rotation_composite.dcm.wavelength_in_a,
rotation_composite.det_stage.z,
rotation_composite.jungfrau._writer.file_path,
rotation_composite.jungfrau.writer.file_path,
],
params,
metadata_writer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
from dodal.devices.attenuator.attenuator import EnumFilterAttenuator
from dodal.devices.beamlines.i24.aperture import Aperture
from dodal.devices.beamlines.i24.beamstop import Beamstop
from dodal.devices.beamlines.i24.commissioning_jungfrau import CommissioningJungfrau
from dodal.devices.beamlines.i24.commissioning_jungfrau import (
CommissioningJungfrauDetector,
)
from dodal.devices.beamlines.i24.dcm import DCM
from dodal.devices.beamlines.i24.dual_backlight import DualBacklight
from dodal.devices.hutch_shutter import InterlockedHutchShutter
Expand All @@ -22,7 +24,9 @@

@pytest.fixture
def rotation_composite(
jungfrau: CommissioningJungfrau, zebra: Zebra, enum_attenuator: EnumFilterAttenuator
jungfrau: CommissioningJungfrauDetector,
zebra: Zebra,
enum_attenuator: EnumFilterAttenuator,
) -> RotationScanComposite:
with init_devices(mock=True):
aperture = Aperture("")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
from bluesky.callbacks import CallbackBase
from bluesky.run_engine import RunEngine
from bluesky.simulators import RunEngineSimulator, assert_message_and_return_remaining
from dodal.devices.beamlines.i24.commissioning_jungfrau import CommissioningJungfrau
from dodal.devices.beamlines.i24.commissioning_jungfrau import (
CommissioningJungfrauDetector,
)
from ophyd_async.core import completed_status
from ophyd_async.fastcs.jungfrau import (
AcquisitionType,
Expand Down Expand Up @@ -58,7 +60,7 @@ def fake_complete(_, group=None):
new=MagicMock(side_effect=fake_complete),
)
async def test_full_do_pedestal_darks(
jungfrau: CommissioningJungfrau,
jungfrau: CommissioningJungfrauDetector,
run_engine: RunEngine,
):
# Test that plan succeeds in RunEngine and pedestal-specific signals are changed as expected
Expand All @@ -71,39 +73,41 @@ async def test_full_do_pedestal_darks(
}
)
def test_plan():
yield from bps.monitor(jungfrau.drv.acquisition_type, name="AT")
yield from bps.monitor(jungfrau.drv.pedestal_mode_state, name="PM")
yield from bps.monitor(jungfrau.drv.gain_mode, name="GM")
yield from bps.monitor(jungfrau.acquisition_type, name="AT")
yield from bps.monitor(jungfrau.detector.pedestal_mode_state, name="PM")
yield from bps.monitor(jungfrau.detector.gain_mode, name="GM")
yield from do_pedestal_darks(0.001, 2, 2, test_path, jungfrau=jungfrau)

jungfrau._controller.arm = AsyncMock()
assert await jungfrau.drv.acquisition_type.get_value() == AcquisitionType.STANDARD
await jungfrau.drv.gain_mode.set(GainMode.FIX_G2)
await jungfrau.drv.pedestal_mode_state.set(PedestalMode.OFF)
jungfrau._arm_logic.arm = AsyncMock() # type: ignore
assert await jungfrau.acquisition_type.get_value() == AcquisitionType.STANDARD
await jungfrau.detector.gain_mode.set(GainMode.FIX_G2)
await jungfrau.detector.pedestal_mode_state.set(PedestalMode.OFF)
monitor_tracker = CheckMonitor(
[
"detector-drv-acquisition_type",
"detector-drv-pedestal_mode_state",
"detector-drv-gain_mode",
"detector-acquisition_type",
"detector-detector-pedestal_mode_state",
"detector-detector-gain_mode",
]
)
run_engine.subscribe(monitor_tracker)
run_engine(test_plan())

assert monitor_tracker.signals_and_values["detector-drv-acquisition_type"] == [
assert monitor_tracker.signals_and_values["detector-acquisition_type"] == [
AcquisitionType.STANDARD,
AcquisitionType.PEDESTAL,
AcquisitionType.STANDARD,
]
assert monitor_tracker.signals_and_values["detector-drv-pedestal_mode_state"] == [
assert monitor_tracker.signals_and_values[
"detector-detector-pedestal_mode_state"
] == [
PedestalMode.OFF,
PedestalMode.ON,
PedestalMode.OFF,
]

# When using the real detector, the switching of gain mode is a bit more complicated,
# see the docstring for the do_pedestal_darks plan.
assert monitor_tracker.signals_and_values["detector-drv-gain_mode"] == [
assert monitor_tracker.signals_and_values["detector-detector-gain_mode"] == [
GainMode.FIX_G2,
GainMode.DYNAMIC,
]
Expand All @@ -113,7 +117,7 @@ class FakeError(Exception): ...


async def test_pedestals_unstage_and_wait_on_exception(
jungfrau: CommissioningJungfrau,
jungfrau: CommissioningJungfrauDetector,
run_engine: RunEngine,
):
jungfrau.prepare = MagicMock(side_effect=FakeError)
Expand All @@ -131,7 +135,7 @@ async def test_pedestals_unstage_and_wait_on_exception(
new=MagicMock(),
)
async def test_do_pedestals_waits_on_stage_before_prepare(
jungfrau: CommissioningJungfrau, sim_run_engine: RunEngineSimulator
jungfrau: CommissioningJungfrauDetector, sim_run_engine: RunEngineSimulator
):
msgs = sim_run_engine.simulate_plan(
do_pedestal_darks(0.001, 2, 2, jungfrau=jungfrau)
Expand All @@ -145,11 +149,15 @@ async def test_do_pedestals_waits_on_stage_before_prepare(
)


@pytest.mark.timeout(5)
def test_do_darks_stops_if_exception_after_stage(
run_engine: RunEngine, jungfrau: CommissioningJungfrau
run_engine: RunEngine, jungfrau: CommissioningJungfrauDetector
):
mock_stop = AsyncMock()
jungfrau.drv.acquisition_stop.trigger = mock_stop
jungfrau.detector.acquisition_stop.trigger = mock_stop
jungfrau.complete = MagicMock(
side_effect=FailedStatus("Simulated completion exception")
)

with pytest.raises(FailedStatus):
run_engine(do_pedestal_darks(0, 2, 2, jungfrau=jungfrau))
Expand All @@ -162,7 +170,7 @@ def test_do_darks_stops_if_exception_after_stage(
new=MagicMock(side_effect=FakeError),
)
def test_do_non_pedestal_darks_unstages_jf_on_exception(
run_engine: RunEngine, jungfrau: CommissioningJungfrau
run_engine: RunEngine, jungfrau: CommissioningJungfrauDetector
):
jungfrau.stage = MagicMock(side_effect=lambda: completed_status())
jungfrau.unstage = MagicMock(side_effect=lambda: completed_status())
Expand All @@ -179,7 +187,7 @@ def test_do_non_pedestal_darks_unstages_jf_on_exception(
def test_do_non_pedestal_darks_triggers_correct_plans(
mock_fly_jf: MagicMock,
run_engine: RunEngine,
jungfrau: CommissioningJungfrau,
jungfrau: CommissioningJungfrauDetector,
):
gain_mode = GainMode.FORCE_SWITCH_G1
parent_mock = MagicMock()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from bluesky.preprocessors import run_decorator
from bluesky.run_engine import RunEngine
from bluesky.simulators import RunEngineSimulator, assert_message_and_return_remaining
from dodal.beamlines.i24 import CommissioningJungfrau
from dodal.beamlines.i24 import CommissioningJungfrauDetector
from ophyd_async.core import set_mock_value
from ophyd_async.fastcs.jungfrau import GainMode

Expand All @@ -19,7 +19,7 @@


def test_full_do_external_acquisition(
jungfrau: CommissioningJungfrau, run_engine: RunEngine, caplog
jungfrau: CommissioningJungfrauDetector, run_engine: RunEngine, caplog
):
@run_decorator(
md={
Expand All @@ -34,13 +34,13 @@ def test_plan():
val = 0
while not status.done:
val += 1
set_mock_value(jungfrau._writer.frame_counter, val)
set_mock_value(jungfrau.writer.frame_counter, val)

# Let status update
yield from bps.wait_for([partial(asyncio.sleep, 0)])
yield from bps.wait(JF_COMPLETE_GROUP)

jungfrau._controller.arm = AsyncMock()
jungfrau._arm_logic.arm = AsyncMock() # type: ignore
run_engine(test_plan())
for i in range(20, 120, 20):
assert f"Jungfrau data collection triggers received: {i}%" in caplog.messages
Expand All @@ -52,7 +52,7 @@ def test_plan():
def test_do_external_acquisition_does_wait(
mock_log_on_percent_complete: MagicMock,
sim_run_engine: RunEngineSimulator,
jungfrau: CommissioningJungfrau,
jungfrau: CommissioningJungfrauDetector,
):
msgs = sim_run_engine.simulate_plan(
do_external_acquisition(0.01, GainMode.DYNAMIC, 1, wait=True, jungfrau=jungfrau)
Expand Down
Loading
Loading