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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ dependencies = [
"ophyd >= 1.10.5",
"ophyd-async >= 0.14.0",
"bluesky >= 1.14.6",
"dls-dodal @ git+https://github.com/DiamondLightSource/dodal.git@main",
"dls-dodal @ git+https://github.com/DiamondLightSource/dodal.git@use_fastcs_eiger_for_xrc",
]


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from dodal.plans.preprocessors.verify_undulator_gap import (
verify_undulator_gap_before_run_decorator,
)
from ophyd_async.fastcs.eiger import EigerDetector as FastCSEiger
from pydantic import BaseModel

from mx_bluesky.beamlines.i04.external_interaction.config_server import (
Expand Down Expand Up @@ -136,6 +137,7 @@ def i04_default_grid_detect_and_xray_centre(
smargon: Smargon = inject("smargon"),
detector_motion: DetectorMotion = inject("detector_motion"),
transfocator: Transfocator = inject("transfocator"),
fastcs_eiger: FastCSEiger = inject("fastcs_eiger"),
oav_config: str = OavConstants.OAV_CONFIG_JSON,
udc: bool = False,
) -> MsgGenerator:
Expand All @@ -152,27 +154,28 @@ def i04_default_grid_detect_and_xray_centre(
"""

composite = GridDetectThenXRayCentreComposite(
eiger,
synchrotron,
zocalo,
smargon,
aperture_scatterguard,
attenuator,
backlight,
beamstop,
beamsize,
dcm,
detector_motion,
zebra_fast_grid_scan,
flux,
oav,
pin_tip_detection,
s4_slit_gaps,
undulator,
xbpm_feedback,
zebra,
robot,
sample_shutter,
eiger=eiger,
synchrotron=synchrotron,
zocalo=zocalo,
smargon=smargon,
aperture_scatterguard=aperture_scatterguard,
attenuator=attenuator,
backlight=backlight,
beamstop=beamstop,
beamsize=beamsize,
dcm=dcm,
detector_motion=detector_motion,
zebra_fast_grid_scan=zebra_fast_grid_scan,
flux=flux,
oav=oav,
pin_tip_detection=pin_tip_detection,
s4_slit_gaps=s4_slit_gaps,
undulator=undulator,
xbpm_feedback=xbpm_feedback,
zebra=zebra,
robot=robot,
sample_shutter=sample_shutter,
fastcs_eiger=fastcs_eiger,
)
initial_beamsize = yield from bps.rd(transfocator.current_vertical_size_rbv)

Expand Down Expand Up @@ -214,6 +217,7 @@ def grid_detect_then_xray_centre_with_callbacks():
parameters=grid_common_params,
xrc_params_type=SpecifiedThreeDGridScan,
construct_beamline_specific=construct_i04_specific_features,
use_fastcs_eiger=False,
oav_config=oav_config,
)

Expand Down Expand Up @@ -271,6 +275,7 @@ def create_gridscan_callbacks() -> tuple[
def construct_i04_specific_features(
xrc_composite: GridDetectThenXRayCentreComposite,
xrc_parameters: SpecifiedThreeDGridScan,
_, # Needed until fastcs eiger is always used, see https://github.com/DiamondLightSource/mx-bluesky/pull/1436/
) -> BeamlineSpecificFGSFeatures:
"""
Get all the information needed to do the i04 XRC flyscan.
Expand Down
6 changes: 4 additions & 2 deletions src/mx_bluesky/common/device_setup_plans/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from dodal.devices.detector.detector_motion import DetectorMotion, ShutterState
from dodal.devices.eiger import EigerDetector
from dodal.devices.mx_phase1.beamstop import Beamstop, BeamstopPositions
from ophyd_async.fastcs.eiger import EigerDetector as FastCSEiger

from mx_bluesky.common.device_setup_plans.position_detector import (
set_detector_z_position,
Expand All @@ -15,7 +16,7 @@

def start_preparing_data_collection_then_do_plan(
beamstop: Beamstop,
eiger: EigerDetector,
eiger: EigerDetector | FastCSEiger,
detector_motion: DetectorMotion,
detector_distance_mm: float | None,
plan_to_run: Generator[Msg, None, None],
Expand All @@ -32,7 +33,8 @@ def start_preparing_data_collection_then_do_plan(
"""

def wrapped_plan():
yield from bps.abs_set(eiger.do_arm, 1, group=group) # type: ignore # Fix types in ophyd-async (https://github.com/DiamondLightSource/mx-bluesky/issues/855)
if isinstance(eiger, EigerDetector):
yield from bps.abs_set(eiger.do_arm, 1, group=group) # type: ignore # Fix types in ophyd-async (https://github.com/DiamondLightSource/mx-bluesky/issues/855)
yield from bps.abs_set(
beamstop.selected_pos, BeamstopPositions.DATA_COLLECTION, group=group
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
XrcResult,
get_full_processing_results,
)
from dodal.plans.configure_arm_trigger_and_disarm_detector import (
configure_and_arm_detector,
)
from ophyd_async.core import (
DetectorTrigger,
TriggerInfo,
)

from mx_bluesky.common.experiment_plans.inner_plans.do_fgs import (
ZOCALO_STAGE_GROUP,
Expand Down Expand Up @@ -58,7 +65,11 @@ class BeamlineSpecificFGSFeatures:
get_xrc_results_from_zocalo: bool


def generic_tidy(xrc_composite: FlyScanEssentialDevices, wait=True) -> MsgGenerator:
def generic_tidy(
xrc_composite: FlyScanEssentialDevices,
use_fastcs_eiger: bool, # Needed until fastcs eiger is always used, see https://github.com/DiamondLightSource/mx-bluesky/pull/1436/
wait=True,
) -> MsgGenerator:
"""Tidy Zocalo and turn off Eiger dev/shm. Ran after the beamline-specific tidy plan"""

LOGGER.info("Tidying up Zocalo")
Expand All @@ -70,7 +81,11 @@ def generic_tidy(xrc_composite: FlyScanEssentialDevices, wait=True) -> MsgGenera
LOGGER.info("Turning off Eiger dev/shm streaming")
# Fix types in ophyd-async (https://github.com/DiamondLightSource/mx-bluesky/issues/855)
yield from bps.abs_set(
xrc_composite.eiger.odin.fan.dev_shm_enable, # type: ignore
(
xrc_composite.eiger.odin.fan.dev_shm_enable # old eiger
if not use_fastcs_eiger
else xrc_composite.fastcs_eiger.odin.fan_dev_shm_enable # fastcs_eiger, requires https://github.com/bluesky/ophyd-async/pull/1127
),
0,
group=group,
)
Expand Down Expand Up @@ -135,6 +150,7 @@ def common_flyscan_xray_centre(
composite: FlyScanEssentialDevices,
parameters: SpecifiedThreeDGridScan,
beamline_specific: BeamlineSpecificFGSFeatures,
use_fastcs_eiger: bool, # Needed until fastcs_eiger is always used, see https://github.com/DiamondLightSource/mx-bluesky/pull/1436/
) -> MsgGenerator:
"""Main entry point of the MX-Bluesky x-ray centering flyscan

Expand All @@ -159,7 +175,7 @@ def common_flyscan_xray_centre(

def _overall_tidy():
yield from beamline_specific.tidy_plan()
yield from generic_tidy(composite)
yield from generic_tidy(composite, use_fastcs_eiger=use_fastcs_eiger)

def _decorated_flyscan():
@bpp.set_run_key_decorator(PlanNameConstants.GRIDSCAN_OUTER)
Expand All @@ -184,7 +200,12 @@ def run_gridscan_and_tidy(
yield from bps.stage(
fgs_composite.zocalo, group=ZOCALO_STAGE_GROUP
) # connect to zocalo and make sure the queue is clear
yield from run_gridscan(fgs_composite, params, beamline_specific)
yield from run_gridscan(
fgs_composite,
params,
beamline_specific,
use_fastcs_eiger=use_fastcs_eiger,
)

LOGGER.info("Grid scan finished")

Expand All @@ -193,7 +214,8 @@ def run_gridscan_and_tidy(

yield from run_gridscan_and_tidy(composite, parameters, beamline_specific)

composite.eiger.set_detector_parameters(parameters.detector_params)
if not use_fastcs_eiger:
composite.eiger.set_detector_parameters(parameters.detector_params)
yield from _decorated_flyscan()


Expand Down Expand Up @@ -262,6 +284,7 @@ def run_gridscan(
fgs_composite: FlyScanEssentialDevices,
parameters: SpecifiedThreeDGridScan,
beamline_specific: BeamlineSpecificFGSFeatures,
use_fastcs_eiger: bool, # Needed until fastcs eiger is always used, see https://github.com/DiamondLightSource/mx-bluesky/pull/1436/
):
# Currently gridscan only works for omega 0, see https://github.com/DiamondLightSource/mx-bluesky/issues/410
with TRACER.start_span("moving_omega_to_0"):
Expand All @@ -282,13 +305,28 @@ def run_gridscan(
else:
raise e

if use_fastcs_eiger:
LOGGER.info("Preparing fastCS eiger")
yield from configure_and_arm_detector(
eiger=fgs_composite.fastcs_eiger,
detector_params=parameters.detector_params,
trigger_info=TriggerInfo(
number_of_events=parameters.detector_params.num_images_per_trigger,
trigger=DetectorTrigger.EDGE_TRIGGER,
deadtime=0.0001,
),
group=PlanGroupCheckpointConstants.GRID_READY_FOR_DC,
)
LOGGER.info("Waiting for arming to finish")
yield from bps.wait(PlanGroupCheckpointConstants.GRID_READY_FOR_DC)
yield from bps.stage(fgs_composite.eiger, wait=True)
if use_fastcs_eiger:
yield from bps.kickoff(fgs_composite.fastcs_eiger, wait=True) # fastcs eiger
else:
yield from bps.stage(fgs_composite.eiger, wait=True) # old eiger

yield from kickoff_and_complete_gridscan(
beamline_specific.fgs_motors,
fgs_composite.eiger,
fgs_composite.fastcs_eiger if use_fastcs_eiger else fgs_composite.eiger,
fgs_composite.synchrotron,
[parameters.scan_points_first_grid, parameters.scan_points_second_grid],
plan_during_collection=beamline_specific.read_during_collection_plan,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from bluesky.preprocessors import subs_decorator
from bluesky.utils import MsgGenerator
from dodal.devices.backlight import InOut
from dodal.devices.eiger import EigerDetector
from dodal.devices.oav.oav_parameters import OAVParameters

from mx_bluesky.common.device_setup_plans.manipulate_sample import (
Expand Down Expand Up @@ -63,16 +62,18 @@ def grid_detect_then_xray_centre(
parameters: GridCommon,
xrc_params_type: type[SpecifiedThreeDGridScan],
construct_beamline_specific: ConstructBeamlineSpecificFeatures,
use_fastcs_eiger: bool, # Needed until fastcs eiger is always used, see https://github.com/DiamondLightSource/mx-bluesky/pull/1436/
oav_config: str = OavConstants.OAV_CONFIG_JSON,
) -> MsgGenerator:
"""
A plan which combines the collection of snapshots from the OAV and the determination
of the grid dimensions to use for the following grid scan.
"""

eiger: EigerDetector = composite.eiger

eiger.set_detector_parameters(parameters.detector_params)
if use_fastcs_eiger:
eiger = composite.fastcs_eiger
else:
eiger = composite.eiger
eiger.set_detector_parameters(parameters.detector_params)

oav_params = OAVParameters("xrayCentring", oav_config)

Expand All @@ -87,6 +88,7 @@ def plan_to_perform():
oav_params,
xrc_params_type,
construct_beamline_specific,
use_fastcs_eiger=use_fastcs_eiger,
),
parameters,
)
Expand Down Expand Up @@ -118,6 +120,7 @@ def detect_grid_and_do_gridscan(
oav_params: OAVParameters,
xrc_params_type: type[SpecifiedThreeDGridScan],
construct_beamline_specific: ConstructBeamlineSpecificFeatures,
use_fastcs_eiger: bool,
):
snapshot_template = f"{parameters.detector_params.prefix}_{parameters.detector_params.run_number}_{{angle}}"

Expand Down Expand Up @@ -181,9 +184,13 @@ def run_grid_detection_plan(
xrc_params = create_parameters_for_flyscan_xray_centre(
parameters, grid_params_callback.get_grid_parameters(), xrc_params_type
)
beamline_specific = construct_beamline_specific(composite, xrc_params)
beamline_specific = construct_beamline_specific(
composite, xrc_params, use_fastcs_eiger
)

yield from common_flyscan_xray_centre(composite, xrc_params, beamline_specific)
yield from common_flyscan_xray_centre(
composite, xrc_params, beamline_specific, use_fastcs_eiger
)


class ConstructBeamlineSpecificFeatures(
Expand All @@ -193,6 +200,7 @@ def __call__(
self,
xrc_composite: TFlyScanEssentialDevices,
xrc_parameters: TSpecifiedThreeDGridScan,
use_fastcs_eiger: bool,
) -> BeamlineSpecificFGSFeatures: ...


Expand Down
18 changes: 14 additions & 4 deletions src/mx_bluesky/common/experiment_plans/inner_plans/do_fgs.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
)
from dodal.log import LOGGER
from dodal.plan_stubs.check_topup import check_topup_and_wait_if_necessary
from ophyd_async.fastcs.eiger import EigerDetector as FastCSEiger
from scanspec.core import AxesPoints, Axis

from mx_bluesky.common.experiment_plans.inner_plans.read_hardware import (
Expand All @@ -28,12 +29,16 @@

def _wait_for_zocalo_to_stage_then_do_fgs(
grid_scan_device: FastGridScanCommon,
detector: EigerDetector,
detector: EigerDetector | FastCSEiger,
synchrotron: Synchrotron,
during_collection_plan: Callable[[], MsgGenerator] | None = None,
):
expected_images = yield from bps.rd(grid_scan_device.expected_images)
exposure_sec_per_image = yield from bps.rd(detector.cam.acquire_time) # type: ignore # Fix types in ophyd-async (https://github.com/DiamondLightSource/mx-bluesky/issues/855)
exposure_sec_per_image = yield from (
bps.rd(detector.cam.acquire_time)
if isinstance(detector, EigerDetector) # old eiger
else bps.rd(detector.drv.detector.frame_time) # fastcs eiger
)
LOGGER.info("waiting for topup if necessary...")
yield from check_topup_and_wait_if_necessary(
synchrotron,
Expand Down Expand Up @@ -66,7 +71,8 @@ def _wait_for_zocalo_to_stage_then_do_fgs(

def kickoff_and_complete_gridscan(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The old eiger device waits for frames when we unstage. The fast-cs eiger will just immediately disarm on unstage.

For the fast-cs eiger we need to do yield from bps.complete instead - this will wait for frames with a default timeout, or the timeout specified in TriggerInfo

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good spot, thanks

gridscan: FastGridScanCommon,
detector: EigerDetector, # Once Eiger inherits from StandardDetector, use that type instead
detector: EigerDetector
| FastCSEiger, # use StandardDetector once old eiger not in use
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we can actually use StandardDetector for the type here since we use dev_shm, which is specific to Odin. Maybe we can use StandardDetector[DetectorController, OdinWriter]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's good to know, could we just use FastCSEiger? How much more general is StandardDetector[DetectorController, OdinWriter] than FastCSEiger

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well theoretically any standard detector which writes using odin could do the XRC plan, but I doubt we'll be doing this anytime soon. So yeah, can just use FastCSEiger for now

synchrotron: Synchrotron,
scan_points: list[AxesPoints[Axis]],
plan_during_collection: Callable[[], MsgGenerator] | None = None,
Expand Down Expand Up @@ -103,7 +109,11 @@ def kickoff_and_complete_gridscan(
)
@bpp.contingency_decorator(
except_plan=lambda e: (yield from bps.stop(detector)), # type: ignore # Fix types in ophyd-async (https://github.com/DiamondLightSource/mx-bluesky/issues/855)
else_plan=lambda: (yield from bps.unstage(detector, wait=True)),
else_plan=lambda: (
yield from bps.unstage(detector, wait=True) # old eiger
if isinstance(detector, EigerDetector)
else bps.complete(detector, wait=True) # fastcs eiger
),
)
def _decorated_do_fgs():
yield from _wait_for_zocalo_to_stage_then_do_fgs(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from dodal.devices.smargon import Smargon
from dodal.devices.synchrotron import Synchrotron
from dodal.devices.undulator import UndulatorInKeV
from ophyd_async.fastcs.eiger import EigerDetector as FastCSEiger

from mx_bluesky.common.parameters.constants import (
DocDescriptorNames,
Expand All @@ -30,12 +31,16 @@ def read_hardware_plan(
yield from bps.save()


def read_hardware_for_zocalo(detector: EigerDetector):
def read_hardware_for_zocalo(detector: EigerDetector | FastCSEiger):
""" "
If the RunEngine is subscribed to the ZocaloCallback, this plan will also trigger zocalo.
"""
yield from read_hardware_plan(
[detector.odin.file_writer.id], # type: ignore
[
detector.odin.file_writer.id # old eiger
if isinstance(detector, EigerDetector)
else detector.odin.id # fastcs eiger
],
DocDescriptorNames.ZOCALO_HW_READ,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ def descriptor(self, doc: EventDescriptor):
def event(self, doc: Event) -> Event:
event_descriptor = self.descriptors[doc["descriptor"]]
if event_descriptor.get("name") == DocDescriptorNames.ZOCALO_HW_READ:
filename = doc["data"]["eiger_odin_file_writer_id"]
filename = (
doc["data"].get("eiger_odin_file_writer_id")
or doc["data"]["fastcs_eiger-odin-id"]
)
for start_info in self.zocalo_info:
start_info.filename = filename
self.zocalo_interactor.run_start(start_info)
Expand Down
Loading
Loading