Skip to content
This repository has been archived by the owner on Sep 2, 2024. It is now read-only.

Commit

Permalink
(#1275) Use new params in rotation scan plan
Browse files Browse the repository at this point in the history
  • Loading branch information
d-perl committed Apr 22, 2024
1 parent ab757d4 commit 0c16545
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 92 deletions.
22 changes: 22 additions & 0 deletions src/hyperion/device_setup_plans/manipulate_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,25 @@ def move_x_y_z(
yield from bps.abs_set(smargon.z, z, group=group)
if wait:
yield from bps.wait(group)


def move_phi_chi_omega(
smargon: Smargon,
phi: float | None = None,
chi: float | None = None,
omega: float | None = None,
wait=False,
group="move_phi_chi_omega",
):
"""Move the x, y, and z axes of the given smargon to the specified position. All
axes are optional."""

LOGGER.info(f"Moving smargon to phi, chi, omega: {(phi, chi, omega)}")
if phi:
yield from bps.abs_set(smargon.phi, phi, group=group)
if chi:
yield from bps.abs_set(smargon.chi, chi, group=group)
if omega:
yield from bps.abs_set(smargon.omega, omega, group=group)
if wait:
yield from bps.wait(group)
78 changes: 36 additions & 42 deletions src/hyperion/experiment_plans/rotation_scan_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from dodal.devices.attenuator import Attenuator
from dodal.devices.backlight import Backlight
from dodal.devices.DCM import DCM
from dodal.devices.detector import DetectorParams
from dodal.devices.detector.detector_motion import DetectorMotion
from dodal.devices.eiger import EigerDetector
from dodal.devices.flux import Flux
Expand All @@ -24,6 +23,7 @@

from hyperion.device_setup_plans.manipulate_sample import (
cleanup_sample_environment,
move_phi_chi_omega,
move_x_y_z,
setup_sample_environment,
)
Expand All @@ -41,10 +41,6 @@
)
from hyperion.log import LOGGER
from hyperion.parameters.constants import CONST
from hyperion.parameters.plan_specific.rotation_scan_internal_params import (
RotationInternalParameters,
RotationScanParams,
)
from hyperion.parameters.rotation import RotationScan
from hyperion.utils.context import device_composite_from_context

Expand Down Expand Up @@ -101,8 +97,7 @@ class RotationMotionProfile:


def calculate_motion_profile(
detector_params: DetectorParams,
expt_params: RotationScanParams,
params: RotationScan,
motor_time_to_speed_s: float,
max_velocity_deg_s: float,
) -> RotationMotionProfile:
Expand All @@ -114,19 +109,19 @@ def calculate_motion_profile(
See https://github.com/DiamondLightSource/hyperion/wiki/rotation-scan-geometry
for a simple pictorial explanation."""

direction = ROTATION_DIRECTION[expt_params.rotation_direction]
num_images = expt_params.get_num_images()
shutter_time_s = expt_params.shutter_opening_time_s
image_width_deg = detector_params.omega_increment
exposure_time_s = detector_params.exposure_time
direction = ROTATION_DIRECTION[params.rotation_direction]
num_images = params.num_images
shutter_time_s = params.shutter_opening_time_s
image_width_deg = params.rotation_increment_deg
exposure_time_s = params.exposure_time_s
motor_time_to_speed_s *= ACCELERATION_MARGIN
start_scan_deg = detector_params.omega_start
start_scan_deg = params.omega_start_deg

LOGGER.info("Calculating rotation scan motion profile:")
LOGGER.info(
f"{num_images=}, {shutter_time_s=}, {image_width_deg=}, {exposure_time_s=}, {direction=}"
)
LOGGER.info(f"{(scan_width_deg := num_images * detector_params.omega_increment)=}")
LOGGER.info(f"{(scan_width_deg := num_images * params.rotation_increment_deg)=}")
LOGGER.info(f"{(speed_for_rotation_deg_s := image_width_deg / exposure_time_s)=}")
LOGGER.info(
f"{(acceleration_offset_deg := motor_time_to_speed_s * speed_for_rotation_deg_s)=}"
Expand All @@ -135,7 +130,7 @@ def calculate_motion_profile(
f"{(start_motion_deg := start_scan_deg - (acceleration_offset_deg * direction))=}"
)
LOGGER.info(
f"{(shutter_opening_deg := speed_for_rotation_deg_s * expt_params.shutter_opening_time_s)=}"
f"{(shutter_opening_deg := speed_for_rotation_deg_s * shutter_time_s)=}"
)
LOGGER.info(f"{(total_exposure_s := num_images * exposure_time_s)=}")
LOGGER.info(
Expand All @@ -147,7 +142,7 @@ def calculate_motion_profile(
start_motion_deg=start_motion_deg,
scan_width_deg=scan_width_deg,
shutter_time_s=shutter_time_s,
direction=expt_params.rotation_direction,
direction=params.rotation_direction,
speed_for_rotation_deg_s=speed_for_rotation_deg_s,
acceleration_offset_deg=acceleration_offset_deg,
shutter_opening_deg=shutter_opening_deg,
Expand All @@ -159,7 +154,7 @@ def calculate_motion_profile(

def rotation_scan_plan(
composite: RotationScanComposite,
params: RotationInternalParameters,
params: RotationScan,
motion_values: RotationMotionProfile,
):
"""A plan to collect diffraction images from a sample continuously rotating about
Expand All @@ -170,8 +165,8 @@ def rotation_scan_plan(
@bpp.run_decorator(
md={
"subplan_name": CONST.PLAN.ROTATION_MAIN,
"zocalo_environment": params.hyperion_params.zocalo_environment,
"scan_points": [params.get_scan_points()],
"zocalo_environment": params.zocalo_environment,
"scan_points": [params.scan_points],
}
)
def _rotation_scan_plan(
Expand All @@ -188,7 +183,7 @@ def _rotation_scan_plan(
yield from bps.abs_set(
axis,
motion_values.start_motion_deg,
group="move_to_start",
group="move_to_rotation_start",
wait=True,
)
yield from setup_zebra_for_rotation(
Expand All @@ -205,8 +200,8 @@ def _rotation_scan_plan(
LOGGER.info("Wait for any previous moves...")
# wait for all the setup tasks at once
yield from bps.wait("setup_senv")
yield from bps.wait("move_x_y_z")
yield from bps.wait("move_to_start")
yield from bps.wait("move_gonio_to_start")
yield from bps.wait("move_to_rotation_start")
yield from bps.wait("setup_zebra")

# get some information for the ispyb deposition and trigger the callback
Expand Down Expand Up @@ -253,62 +248,61 @@ def cleanup_plan(composite: RotationScanComposite, max_vel: float, **kwargs):

def rotation_scan(
composite: RotationScanComposite,
parameters: RotationScan | RotationInternalParameters | Any,
parameters: RotationScan | Any,
) -> MsgGenerator:
old_parameters = (
parameters
if isinstance(parameters, RotationInternalParameters)
else parameters.old_parameters()
)

@bpp.set_run_key_decorator("rotation_scan")
@bpp.run_decorator( # attach experiment metadata to the start document
md={
"subplan_name": CONST.PLAN.ROTATION_OUTER,
CONST.TRIGGER.ZOCALO: CONST.PLAN.ROTATION_MAIN,
"hyperion_internal_parameters": parameters.json(),
"hyperion_internal_parameters": parameters.old_parameters().json(),
"activate_callbacks": [
"RotationISPyBCallback",
"RotationNexusFileCallback",
],
}
)
def rotation_scan_plan_with_stage_and_cleanup(
params: RotationInternalParameters,
params: RotationScan,
):
motor_time_to_speed = yield from bps.rd(composite.smargon.omega.acceleration)
max_vel = (
yield from bps.rd(composite.smargon.omega.max_velocity)
or DEFAULT_MAX_VELOCITY
)
motion_values = calculate_motion_profile(
params.hyperion_params.detector_params,
params.experiment_params,
params,
motor_time_to_speed,
max_vel,
)

eiger: EigerDetector = composite.eiger
eiger.set_detector_parameters(params.hyperion_params.detector_params)
eiger.set_detector_parameters(params.detector_params)

@bpp.stage_decorator([eiger])
@bpp.finalize_decorator(lambda: cleanup_plan(composite, max_vel))
def rotation_with_cleanup_and_stage(params: RotationInternalParameters):
def rotation_with_cleanup_and_stage(params: RotationScan):
LOGGER.info("setting up sample environment...")
yield from setup_sample_environment(
composite.detector_motion,
composite.backlight,
composite.attenuator,
params.experiment_params.transmission_fraction,
params.hyperion_params.detector_params.detector_distance,
params.transmission_frac,
params.detector_params.detector_distance,
)
LOGGER.info("moving to position (if specified)")
yield from move_x_y_z(
composite.smargon,
params.experiment_params.x,
params.experiment_params.y,
params.experiment_params.z,
group="move_x_y_z",
params.x_start_um,
params.y_start_um,
params.z_start_um,
group="move_gonio_to_start",
)
yield from move_phi_chi_omega(
composite.smargon,
params.phi_start_deg,
params.chi_start_deg,
group="move_gonio_to_start",
)
yield from rotation_scan_plan(
composite,
Expand All @@ -319,4 +313,4 @@ def rotation_with_cleanup_and_stage(params: RotationInternalParameters):
LOGGER.info("setting up and staging eiger...")
yield from rotation_with_cleanup_and_stage(params)

yield from rotation_scan_plan_with_stage_and_cleanup(old_parameters)
yield from rotation_scan_plan_with_stage_and_cleanup(parameters)
1 change: 0 additions & 1 deletion src/hyperion/parameters/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ class XyzAxis(str, Enum):
class HyperionParameters(BaseModel):
class Config:
arbitrary_types_allowed = True
use_enum_values = True
extra = Extra.forbid
json_encoders = {
ParameterVersion: lambda pv: str(pv),
Expand Down
12 changes: 5 additions & 7 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,7 @@
from hyperion.parameters.plan_specific.panda.panda_gridscan_internal_params import (
PandAGridscanInternalParameters,
)
from hyperion.parameters.plan_specific.rotation_scan_internal_params import (
RotationInternalParameters,
)
from hyperion.parameters.rotation import RotationScan

i03.DAQ_CONFIGURATION_PATH = "tests/test_data/test_daq_configuration"

Expand Down Expand Up @@ -217,18 +215,18 @@ def test_panda_fgs_params():

@pytest.fixture
def test_rotation_params():
return RotationInternalParameters(
return RotationScan(
**raw_params_from_file(
"tests/test_data/parameter_json_files/good_test_rotation_scan_parameters.json"
"tests/test_data/new_parameter_json_files/good_test_rotation_scan_parameters.json"
)
)


@pytest.fixture
def test_rotation_params_nomove():
return RotationInternalParameters(
return RotationScan(
**raw_params_from_file(
"tests/test_data/parameter_json_files/good_test_rotation_scan_parameters_nomove.json"
"tests/test_data/new_parameter_json_files/good_test_rotation_scan_parameters_nomove.json"
)
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"parameter_model_version": "5.0.0",
"comment": "test",
"det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt",
"storage_directory": "/tmp/dls/i03/data/2024/cm31105-4/auto/123456/",
"detector_distance_mm": 100.0,
"detector": "EIGER2_X_16M",
"demand_energy_ev": 100,
"exposure_time_s": 0.1,
"insertion_prefix": "SR03S",
"omega_start_deg": 0.0,
"file_name": "file_name",
"scan_width_deg": 180.0,
"rotation_axis": "omega",
"rotation_direction": "Negative",
"rotation_increment_deg": 0.1,
"run_number": 0,
"sample_id": 123456,
"shutter_opening_time_s": 0.6,
"visit": "cm31105-4",
"zocalo_environment": "dev_artemis",
"transmission_frac": 0.1,
"phi_start_deg": 0.47,
"chi_start_deg": 23.85,
"x_start_um": 1.0,
"y_start_um": 2.0,
"z_start_um": 3.0,
"ispyb_extras": {
"microns_per_pixel_x": 1.0,
"microns_per_pixel_y": 1.0,
"upper_left": [
10.0,
20.0,
30.0
],
"position": [
10.0,
20.0,
30.0
],
"xtal_snapshots_omega_start": [
"test_1_y",
"test_2_y",
"test_3_y"
],
"xtal_snapshots_omega_end": [
"test_1_z",
"test_2_z",
"test_3_z"
],
"xtal_snapshots": [
"test_1",
"test_2",
"test_3"
],
"beam_size_x": 1.0,
"beam_size_y": 1.0,
"focal_spot_size_x": 1.0,
"focal_spot_size_y": 1.0,
"resolution": 1.0
}
}
Loading

0 comments on commit 0c16545

Please sign in to comment.