Skip to content
Draft
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
18 changes: 16 additions & 2 deletions src/mx_bluesky/beamlines/i02_1/composites.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
from pathlib import Path

from mx_bluesky.beamlines.i02_1.parameters.gridscan import SpecifiedTwoDGridScan
from dodal.devices.aperturescatterguard import ApertureValue
from pydantic import Field

from mx_bluesky.common.parameters.components import (
DiffractionExperimentWithSample,
IspybExperimentType,
)
from mx_bluesky.common.parameters.constants import GridscanParamConstants

class I02_1FgsParams(SpecifiedTwoDGridScan): # noqa: N801

class I02_1FgsParams(DiffractionExperimentWithSample): # noqa: N801
"""For VMXm gridscans, GDA currently takes the snapshots and provides bluesky with a path, and
sends over the grid parameters"""

Expand All @@ -14,3 +21,10 @@ class I02_1FgsParams(SpecifiedTwoDGridScan): # noqa: N801
microns_per_pixel_y: float
upper_left_x: int # position of X,Y for the top left of the grid, in pixels
upper_left_y: int

# Overrides of default values in the superclass
exposure_time_s: float = Field(default=GridscanParamConstants.EXPOSURE_TIME_S)
ispyb_experiment_type: IspybExperimentType = Field(
default=IspybExperimentType.GRIDSCAN_3D
)
selected_aperture: ApertureValue | None = Field(default=ApertureValue.SMALL)
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,25 @@ def _get_scan_infos(self, doc) -> Sequence[ScanDataInfo]:
For VMXm, grid information is available immediately after the plan is triggered.
"""
assert isinstance(self.params, I02_1FgsParams)
assert self.grid_scan_params
assert self.detector_params
assert self.ispyb_ids.data_collection_ids, "No current data collection"
assert self.data_collection_group_info, "No data collection group"
data = doc["data"]
scan_data_infos = []

for grid_num in range(self.params.num_grids):
omega = data.get("gonio-omega", self.params.omega_starts_deg[grid_num])
for grid_num in range(self.grid_scan_params.num_grids):
omega = data.get(
"gonio-omega", self.grid_scan_params.omega_starts_deg[grid_num]
)

ISPYB_ZOCALO_CALLBACK_LOGGER.info(
f"Generating dc info for gridplane XY, omega {omega}"
)
data_collection_number = self.params.detector_params.run_number
file_template = f"{self.params.detector_params.prefix}_{data_collection_number}_master.h5"
data_collection_number = self.detector_params.run_number
file_template = (
f"{self.detector_params.prefix}_{data_collection_number}_master.h5"
)
# Snapshots have already been taken in GDA

data_collection_info = DataCollectionInfo(
Expand All @@ -50,10 +56,10 @@ def _get_scan_infos(self, doc) -> Sequence[ScanDataInfo]:
file_template=file_template,
)
data_collection_grid_info = DataCollectionGridInfo(
dx_in_mm=self.params.x_step_size_um / 1000,
dy_in_mm=self.params.y_step_sizes_um[grid_num] / 1000,
steps_x=self.params.x_steps,
steps_y=self.params.y_steps[grid_num],
dx_in_mm=self.grid_scan_params.x_step_size_um / 1000,
dy_in_mm=self.grid_scan_params.y_step_sizes_um[grid_num] / 1000,
steps_x=self.grid_scan_params.x_steps,
steps_y=self.grid_scan_params.y_steps[grid_num],
microns_per_pixel_x=self.params.microns_per_pixel_x,
microns_per_pixel_y=self.params.microns_per_pixel_y,
snapshot_offset_x_pixel=self.params.upper_left_x,
Expand All @@ -68,7 +74,7 @@ def _get_scan_infos(self, doc) -> Sequence[ScanDataInfo]:
data_collection_id = self.ispyb_ids.data_collection_ids[0]

self.data_collection_group_info.comments = _make_comment(
self.params.x_steps, self.params.y_steps[0]
self.grid_scan_params.x_steps, self.grid_scan_params.y_steps[0]
)

self._populate_axis_info(data_collection_info, doc["data"])
Expand Down
71 changes: 40 additions & 31 deletions src/mx_bluesky/beamlines/i02_1/i02_1_gridscan_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from mx_bluesky.beamlines.i02_1.external_interaction.callbacks.gridscan.ispyb_callback import (
GridscanISPyBCallback,
)
from mx_bluesky.beamlines.i02_1.parameters.gridscan import SpecifiedTwoDGridScan
from mx_bluesky.beamlines.i02_1.parameters.gridscan import fast_gridscan_params
from mx_bluesky.common.experiment_plans.common_flyscan_xray_centre_plan import (
BeamlineSpecificFGSFeatures,
common_flyscan_xray_centre,
Expand All @@ -47,6 +47,7 @@
generate_start_info_from_num_grids,
)
from mx_bluesky.common.parameters.components import (
DiffractionExperiment,
IspybExperimentType,
get_param_version,
)
Expand All @@ -57,23 +58,27 @@
from mx_bluesky.common.parameters.device_composites import (
FlyScanEssentialDevices,
)
from mx_bluesky.common.parameters.gridscan import GridScanParams, PositiveFloat
from mx_bluesky.common.parameters.gridscan import (
GridScanParams,
PositiveFloat,
create_detector_params,
)
from mx_bluesky.common.utils.log import LOGGER

DEFAULT_BOX_SIZE_UM = 2


def create_gridscan_callbacks(
params: I02_1FgsParams,
grid_scan_params: GridScanParams,
) -> tuple[GridscanNexusFileCallback, GridscanISPyBCallback]:
return (
GridscanNexusFileCallback(param_type=SpecifiedTwoDGridScan),
GridscanNexusFileCallback(param_type=I02_1FgsParams),
GridscanISPyBCallback(
param_type=I02_1FgsParams,
emit=ZocaloCallback(
PlanNameConstants.DO_FGS,
EnvironmentConstants.ZOCALO_ENV,
lambda: generate_start_info_from_num_grids(params),
lambda: generate_start_info_from_num_grids(grid_scan_params),
),
),
)
Expand All @@ -94,7 +99,8 @@ class I021FlyScanXRayCentreComposite(FlyScanEssentialDevices[XYZWrappedOmegaStag

def construct_i02_1_specific_features(
fgs_composite: I021FlyScanXRayCentreComposite,
parameters: SpecifiedTwoDGridScan,
params: DiffractionExperiment,
grid_scan_params: GridScanParams,
) -> BeamlineSpecificFGSFeatures:
signals_to_read_pre_flyscan = [
fgs_composite.synchrotron.synchrotron_mode,
Expand All @@ -113,13 +119,14 @@ def construct_i02_1_specific_features(
fgs_composite.eiger.ispyb_detector_id,
]

fgs_params = fast_gridscan_params(params, grid_scan_params)
return construct_beamline_specific_fast_gridscan_features(
partial(_zebra_triggering_setup),
partial(_tidy_plan, fgs_composite, group="flyscan_zebra_tidy", wait=True),
partial(
set_flyscan_params_plan,
fgs_composite.zebra_fast_grid_scan,
parameters.fast_gridscan_params,
fgs_params,
),
fgs_composite.zebra_fast_grid_scan,
signals_to_read_pre_flyscan,
Expand Down Expand Up @@ -171,19 +178,15 @@ class ExternalGridScanParams(BaseModel):
omega_start_deg: int


def get_internal_params(params: ExternalGridScanParams) -> I02_1FgsParams:
return I02_1FgsParams(
y_starts_um=[params.y_start_um],
x_start_um=params.x_start_um,
z_starts_um=[params.z_start_um],
omega_starts_deg=[params.omega_start_deg],
def get_internal_params(
params: ExternalGridScanParams,
) -> tuple[I02_1FgsParams, GridScanParams]:
fgs_params = I02_1FgsParams(
sample_id=params.sample_id,
visit=params.visit,
parameter_model_version=get_param_version(),
file_name=params.file_name,
storage_directory=params.storage_directory,
x_steps=params.x_steps,
y_steps=[params.y_steps],
path_to_xtal_snapshot=params.snapshot_directory,
beam_size_x=params.beam_size_x,
beam_size_y=params.beam_size_y,
Expand All @@ -193,11 +196,20 @@ def get_internal_params(params: ExternalGridScanParams) -> I02_1FgsParams:
upper_left_y=params.upper_left_y,
detector_distance_mm=params.detector_distance_mm,
ispyb_experiment_type=IspybExperimentType.SAD,
use_roi_mode=False,
)

grid_scan_params = GridScanParams(
omega_starts_deg=[params.omega_start_deg],
x_start_um=params.x_start_um,
y_starts_um=[params.y_start_um],
z_starts_um=[params.z_start_um],
x_steps=params.x_steps,
y_steps=[params.y_steps],
x_step_size_um=params.x_step_size_um,
y_step_sizes_um=params.y_step_sizes_um,
use_roi_mode=False,
box_size_um=DEFAULT_BOX_SIZE_UM,
)
return fgs_params, grid_scan_params


def i02_1_gridscan_plan(
Expand All @@ -206,26 +218,23 @@ def i02_1_gridscan_plan(
) -> MsgGenerator:
"""BlueAPI entry point for i02-1 grid scans"""

params = get_internal_params(parameters)
params, grid_scan_params = get_internal_params(parameters)

beamline_specific = construct_i02_1_specific_features(composite, params)
callbacks = create_gridscan_callbacks(params)
grid_scan_params = GridScanParams(
omega_starts_deg=params.omega_starts_deg,
x_start_um=params.x_start_um,
y_starts_um=params.y_starts_um,
z_starts_um=params.z_starts_um,
x_steps=params.x_steps,
y_steps=params.y_steps,
x_step_size_um=params.x_step_size_um,
y_step_sizes_um=params.y_step_sizes_um,
beamline_specific = construct_i02_1_specific_features(
composite, params, grid_scan_params
)
callbacks = create_gridscan_callbacks(grid_scan_params)
detector_params = create_detector_params(params)

@bpp.subs_decorator(callbacks)
@ispyb_activation_decorator(params)
@ispyb_activation_decorator(params, grid_scan_params, detector_params)
def decorated_flyscan_plan():
yield from common_flyscan_xray_centre(
composite, params, grid_scan_params, beamline_specific
composite,
params,
detector_params,
grid_scan_params,
beamline_specific,
)

yield from decorated_flyscan_plan()
54 changes: 17 additions & 37 deletions src/mx_bluesky/beamlines/i02_1/parameters/gridscan.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,21 @@
from dodal.devices.beamlines.i02_1.fast_grid_scan import ZebraGridScanParamsTwoD
from pydantic import model_validator

from mx_bluesky.common.parameters.components import SplitScan, WithOptionalEnergyChange
from mx_bluesky.common.parameters.gridscan import SpecifiedGrids
from mx_bluesky.common.parameters.components import DiffractionExperiment
from mx_bluesky.common.parameters.gridscan import GridScanParams


class SpecifiedTwoDGridScan(
SpecifiedGrids[ZebraGridScanParamsTwoD],
SplitScan,
WithOptionalEnergyChange,
):
"""Parameters representing a so-called 2D grid scan, which consists of doing a
gridscan in X and Y."""

@property
def fast_gridscan_params(self) -> ZebraGridScanParamsTwoD:
return ZebraGridScanParamsTwoD(
x_steps=self.x_steps,
y_steps=self.y_steps[0],
x_step_size_mm=self.x_step_size_um / 1000,
y_step_size_mm=self.y_step_sizes_um[0] / 1000,
x_start_mm=self.x_start_um / 1000,
y1_start_mm=self.y_starts_um[0] / 1000,
z1_start_mm=self.z_starts_um[0] / 1000,
set_stub_offsets=self._set_stub_offsets,
transmission_fraction=0.5,
dwell_time_ms=self.exposure_time_s * 1000,
)

@model_validator(mode="after")
def validate_y_axes(self):
_err_str = "must be length 1 for 2D scans"
if len(self.y_steps) != 1:
raise ValueError(f"{self.y_steps=} {_err_str}")
if len(self.y_step_sizes_um) != 1:
raise ValueError(f"{self.y_step_sizes_um=} {_err_str}")
if len(self.omega_starts_deg) != 1:
raise ValueError(f"{self.omega_starts_deg=} {_err_str}")

return self
def fast_gridscan_params(
params: DiffractionExperiment, grid_scan_params: GridScanParams
) -> ZebraGridScanParamsTwoD:
return ZebraGridScanParamsTwoD(
x_steps=grid_scan_params.x_steps,
y_steps=grid_scan_params.y_steps[0],
x_step_size_mm=grid_scan_params.x_step_size_um / 1000,
y_step_size_mm=grid_scan_params.y_step_sizes_um[0] / 1000,
x_start_mm=grid_scan_params.x_start_um / 1000,
y1_start_mm=grid_scan_params.y_starts_um[0] / 1000,
z1_start_mm=grid_scan_params.z_starts_um[0] / 1000,
set_stub_offsets=False,
transmission_fraction=0.5,
dwell_time_ms=params.exposure_time_s * 1000,
)
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,10 @@
from mx_bluesky.common.external_interaction.callbacks.grid.utils import (
generate_start_info_from_omega_map,
)
from mx_bluesky.common.parameters.components import get_param_version
from mx_bluesky.common.parameters.components import (
DiffractionExperimentWithSample,
get_param_version,
)
from mx_bluesky.common.parameters.constants import (
EnvironmentConstants,
GridscanParamConstants,
Expand All @@ -84,8 +87,10 @@
)
from mx_bluesky.common.parameters.gridscan import (
GenericGrid,
GridDetectionParams,
GridScanParams,
SpecifiedThreeDGridScan,
create_detector_params,
fast_gridscan_params,
)
from mx_bluesky.common.preprocessors.preprocessors import (
Expand Down Expand Up @@ -164,27 +169,27 @@ def i04_default_grid_detect_and_xray_centre(
"""

composite = GridDetectThenXRayCentreComposite(
eiger,
synchrotron,
smargon,
aperture_scatterguard,
attenuator,
zocalo,
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,
gonio=smargon,
aperture_scatterguard=aperture_scatterguard,
attenuator=attenuator,
zocalo=zocalo,
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,
)
initial_beamsize = yield from bps.rd(transfocator.current_vertical_size_rbv)

Expand Down Expand Up @@ -229,7 +234,11 @@ def grid_detect_then_xray_centre_with_callbacks():
grid_scan_params = yield from grid_detect_then_xray_centre(
composite=composite,
parameters=grid_common_params,
grid_detection_params=GridDetectionParams(),
xrc_params_type=SpecifiedThreeDGridScan,
detector_params_factory=lambda: create_detector_params(
grid_common_params
),
construct_beamline_specific=construct_i04_specific_features,
oav_config=oav_config,
)
Expand Down Expand Up @@ -299,7 +308,7 @@ def create_gridscan_callbacks() -> tuple[

def construct_i04_specific_features(
xrc_composite: GridDetectThenXRayCentreComposite,
xrc_parameters: SpecifiedThreeDGridScan,
xrc_parameters: DiffractionExperimentWithSample,
grid_scan_params: GridScanParams,
) -> BeamlineSpecificFGSFeatures:
"""
Expand Down
Loading
Loading