Skip to content
Open
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
38 changes: 27 additions & 11 deletions src/dodal/beamlines/i24.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from pathlib import PurePath

from ophyd_async.core import AutoIncrementingPathProvider, StaticFilenameProvider
from ophyd_async.core import (
AutoMaxIncrementingPathProvider,
)

from dodal.common.beamlines.beamline_utils import (
BL,
device_factory,
get_path_provider,
)
from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline
from dodal.devices.attenuator.attenuator import EnumFilterAttenuator
Expand All @@ -25,12 +26,14 @@
from dodal.devices.motors import YZStage
from dodal.devices.oav.oav_detector import OAVBeamCentreFile
from dodal.devices.oav.oav_parameters import OAVConfigBeamCentre
from dodal.devices.synchrotron import Synchrotron
from dodal.devices.zebra.zebra import Zebra
from dodal.devices.zebra.zebra_constants_mapping import (
ZebraMapping,
ZebraSources,
ZebraTTLOutputs,
)
from dodal.devices.zebra.zebra_controlled_shutter import ZebraShutter
from dodal.log import set_beamline as set_log_beamline
from dodal.utils import BeamlinePrefix, get_beamline_name

Expand All @@ -45,7 +48,7 @@
set_utils_beamline(BL)

I24_ZEBRA_MAPPING = ZebraMapping(
outputs=ZebraTTLOutputs(TTL_EIGER=1, TTL_PILATUS=2, TTL_FAST_SHUTTER=4),
outputs=ZebraTTLOutputs(TTL_EIGER=1, TTL_JUNGFRAU=2, TTL_FAST_SHUTTER=4),
sources=ZebraSources(),
)

Expand Down Expand Up @@ -200,10 +203,7 @@ def eiger_beam_center() -> DetectorBeamCenter:


@device_factory()
def commissioning_jungfrau(
path_to_dir: str = "/tmp/jf", # Device factory doesn't allow for required args,
filename: str = "jf_output", # but these should be manually entered when commissioning
) -> CommissioningJungfrau:
def commissioning_jungfrau() -> CommissioningJungfrau:
"""Get the commissionning Jungfrau 9M device, which uses a temporary filewriter
device in place of Odin while the detector is in commissioning.
Instantiates the device if it hasn't already been.
Expand All @@ -212,7 +212,23 @@ def commissioning_jungfrau(
return CommissioningJungfrau(
f"{PREFIX.beamline_prefix}-EA-JFRAU-01:",
f"{PREFIX.beamline_prefix}-JUNGFRAU-META:FD:",
AutoIncrementingPathProvider(
StaticFilenameProvider(filename), PurePath(path_to_dir)
),
AutoMaxIncrementingPathProvider(get_path_provider()),
)


@device_factory()
def synchrotron() -> Synchrotron:
"""Get the i24 synchrotron device, instantiate it if it hasn't already been.
If this is called when already instantiated in i24, it will return the existing object.
"""
return Synchrotron()


@device_factory()
def sample_shutter() -> ZebraShutter:
"""Get the i24 sample shutter device, instantiate it if it hasn't already been.
If this is called when already instantiated in i24, it will return the existing object.
"""
return ZebraShutter(
f"{PREFIX.beamline_prefix}-EA-SHTR-01:",
)
19 changes: 9 additions & 10 deletions src/dodal/devices/i24/commissioning_jungfrau.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@
from event_model import DataKey # type: ignore
from ophyd_async.core import (
AsyncStatus,
AutoIncrementingPathProvider,
DetectorWriter,
PathProvider,
StandardDetector,
StandardReadable,
StaticPathProvider,
TriggerInfo,
observe_value,
wait_for_value,
Expand All @@ -22,7 +21,7 @@
from dodal.log import LOGGER


class JunfrauCommissioningWriter(DetectorWriter, StandardReadable):
class JungfrauCommissioningWriter(DetectorWriter, StandardReadable):
"""Implementation of the temporary filewriter used for Jungfrau commissioning on i24.

The PVs on this device are responsible for writing files of a specified name
Expand All @@ -33,11 +32,11 @@ class JunfrauCommissioningWriter(DetectorWriter, StandardReadable):
def __init__(
self,
prefix,
path_provider: AutoIncrementingPathProvider | StaticPathProvider,
path_provider: PathProvider,
name="",
) -> None:
with self.add_children_as_readables():
self._path_info = path_provider
self._path_provider = path_provider
self.frame_counter = epics_signal_rw(int, f"{prefix}NumCaptured")
self.file_name = epics_signal_rw_rbv(str, f"{prefix}FileName")
self.file_path = epics_signal_rw_rbv(str, f"{prefix}FilePath")
Expand All @@ -47,9 +46,8 @@ def __init__(

async def open(self, name: str, exposures_per_event: int = 1) -> dict[str, DataKey]:
self._exposures_per_event = exposures_per_event
_path_info = self._path_info()
_path_info = self._path_provider()

# Commissioning Jungfrau plans allow you to override path, so check to see if file exists
requested_filepath = Path(_path_info.directory_path) / _path_info.filename
if requested_filepath.exists():
raise FileExistsError(
Expand All @@ -65,6 +63,7 @@ async def open(self, name: str, exposures_per_event: int = 1) -> dict[str, DataK
f"Jungfrau writing to folder {_path_info.directory_path} with filename {_path_info.filename}"
)
await wait_for_value(self.writer_ready, 1, timeout=10)
self.final_path = requested_filepath
return await self._describe()

async def _describe(self) -> dict[str, DataKey]:
Expand Down Expand Up @@ -99,7 +98,7 @@ async def close(self) -> None: ...


class CommissioningJungfrau(
StandardDetector[JungfrauController, JunfrauCommissioningWriter]
StandardDetector[JungfrauController, JungfrauCommissioningWriter]
):
"""Ophyd-async implementation of a Jungfrau 9M Detector, using a temporary
filewriter in place of Odin"""
Expand All @@ -108,11 +107,11 @@ def __init__(
self,
prefix: str,
writer_prefix: str,
path_provider: AutoIncrementingPathProvider | StaticPathProvider,
path_provider: PathProvider,
name="",
):
self.drv = JungfrauDriverIO(prefix)
writer = JunfrauCommissioningWriter(writer_prefix, path_provider)
writer = JungfrauCommissioningWriter(writer_prefix, path_provider)
controller = JungfrauController(self.drv)
super().__init__(controller, writer, name=name)

Expand Down
1 change: 1 addition & 0 deletions src/dodal/devices/zebra/zebra_constants_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class ZebraTTLOutputs(ZebraMappingValidations):
TTL_SHUTTER: int = Field(default=-1, ge=-1, le=4)
TTL_XSPRESS3: int = Field(default=-1, ge=-1, le=4)
TTL_PANDA: int = Field(default=-1, ge=-1, le=4)
TTL_JUNGFRAU: int = Field(default=-1, ge=-1, le=4)


class ZebraSources(ZebraMappingValidations):
Expand Down
4 changes: 2 additions & 2 deletions tests/devices/i24/test_commissioning_jungfrau.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ async def test_jungfrau_with_temporary_writer(
):
set_mock_value(jungfrau._writer.writer_ready, 1)
set_mock_value(jungfrau._writer.frame_counter, 10)
jungfrau._writer._path_info = MagicMock()
jungfrau._writer._path_provider = MagicMock()
trigger_info = TriggerInfo(livetime=1e-3, exposures_per_event=5)
await jungfrau.prepare(trigger_info)
assert await jungfrau._writer.frame_counter.get_value() == 0
Expand All @@ -48,7 +48,7 @@ async def _do_fake_writing():
set_mock_value(jungfrau._writer.frame_counter, 5)

await asyncio.gather(status, _do_fake_writing())
jungfrau._writer._path_info.assert_called_once()
jungfrau._writer._path_provider.assert_called_once()


async def test_jungfrau_error_when_writing_to_existing_file(tmp_path: Path):
Expand Down
Loading