Source code for sm_bluesky.beamlines.i10.plans.align_slits

from collections.abc import Hashable

from bluesky.plan_stubs import abs_set, mv, wait
from dodal.beamlines.i10 import (
    det_slits,
    diffractometer,
    sample_stage,
    slits,
)
from dodal.common.types import MsgGenerator
from dodal.devices.slits import Slits
from ophyd_async.core import StandardReadable

from sm_bluesky.common.math_functions import cal_range_num
from sm_bluesky.common.plan_stubs import move_motor_with_look_up
from sm_bluesky.common.plans import (
    StatPosition,
    align_slit_with_look_up,
    step_scan_and_move_fit,
)
from sm_bluesky.log import LOGGER

from ..configuration.default_setting import (
    RASOR_DEFAULT_DET,
)

"""I10 has fix/solid slit on a motor, this store the rough motor opening
 position against slit size in um"""

DSD = {"5000": 14.3, "1000": 19.3, "500": 26.5, "100": 29.3, "50": 34.3}
DSU = {"5000": 16.7, "1000": 21.7, "500": 25.674, "100": 31.7, "50": 36.7}


[docs] def move_dsu( size: float, slit_table: dict[str, float] = DSU, use_motor_position: bool = False, wait: bool = True, group: Hashable | None = None, ) -> MsgGenerator: """Move up stream detector slit either by it size in slit motor table or by motor position.""" yield from move_motor_with_look_up( slit=det_slits().upstream, size=size, motor_table=slit_table, use_motor_position=use_motor_position, wait=wait, group=group, )
[docs] def move_dsd( size: float, slit_table: dict[str, float] = DSD, use_motor_position: bool = False, wait: bool = True, group: Hashable | None = None, ) -> MsgGenerator: """Move down stream detector slit either by it size in slit motor table or by motor position.""" yield from move_motor_with_look_up( slit=det_slits().downstream, size=size, motor_table=slit_table, use_motor_position=use_motor_position, wait=wait, group=group, )
[docs] def align_dsu(size: float, det: StandardReadable | None = None) -> MsgGenerator: """Align the up stream detector slit""" if det is None: det = get_rasor_default_det() yield from align_slit_with_look_up( motor=det_slits().upstream, size=size, slit_table=DSU, det=det, centre_type=StatPosition.COM, )
[docs] def align_dsd( size: float, det: StandardReadable | None = None, ) -> MsgGenerator: """Align the down stream detector slit""" if det is None: det = get_rasor_default_det() yield from align_slit_with_look_up( motor=det_slits().downstream, size=size, slit_table=DSD, det=det, centre_type=StatPosition.COM, )
def align_pa_slit(dsd_size: float, dsu_size: float) -> MsgGenerator: """Align both detector slits""" yield from move_dsd(5000, wait=True) yield from align_dsu(dsu_size) yield from align_dsd(dsd_size) def align_s5s6(det: StandardReadable | None = None) -> MsgGenerator: """ Plan to align the s5s6 slits with the straight through beam and RASOR detector, it define where all the motor should be and call align slits Parameters ---------- det (optional): StandardReadable Detector that use for the alignments, default is rasor photodiode. """ if det is None: det = get_rasor_default_det() slit = slits() yield from move_to_direct_beam_position() yield from align_slit( det=det, slit=slit.s5, x_scan_size=0.1, x_final_size=0.65, x_range=2, x_open_size=2, x_cen=0, y_scan_size=0.1, y_final_size=1.3, y_open_size=4, y_range=2, y_cen=0, ) LOGGER.info("Aligning s6") yield from align_slit( det=det, slit=slit.s6, x_scan_size=0.1, x_final_size=0.45, x_range=2, x_open_size=4, x_cen=0, y_scan_size=0.1, y_final_size=0.6, y_open_size=4, y_range=2, y_cen=0, ) def align_slit( det: StandardReadable, slit: Slits, x_scan_size: float, x_final_size: float, x_open_size: float, y_scan_size: float, y_final_size: float, y_open_size: float, x_range: float, x_cen: float, y_range: float, y_cen: float, centre_type: StatPosition = StatPosition.COM, ) -> MsgGenerator: """ Plan to align a pair of standard x-y slits, it does a pair of slits scan and go to the centre of mass by default. Parameters ---------- det: StandardReadable Detector to be use for alignment. slit: Slits, x-y slits. x_scan_size: float, The size of the x slit use for alignment. x_final_size: float, The size of the x slit to set to after alignment. x_open_size: float, The size of the x slit during y slit alignment. y_scan_size: float, The size of the y slit use for alignment. y_final_size: float, The size of the y slit to set to after alignment. y_open_size: float, The size of the y slit during x slit alignment. x_range: float, The x slit range, range is the distant from the centre. e.g. a range of 1 with centre at 0 will cover -1 to 1. x_cen: float, The best guess of x slit centre. y_range: float, The y slit range. y_cen: float, The best guess of y slit centre. centre_type: StatPosition = StatPosition.COM Where to move the slits, it goes to centre of mass by default. see StatPosition for other options. """ group_wait = "slits group" yield from abs_set(slit.x_gap, x_scan_size, group=group_wait) yield from abs_set(slit.y_gap, y_open_size, group=group_wait) LOGGER.info(f"Moving to starting position for {slit.x_centre.name} alignment.") yield from wait(group=group_wait) yield from mv(slit.y_centre, y_cen, group=group_wait) # type: ignore start_pos, end_pos, num = cal_range_num(x_cen, x_range, x_scan_size) yield from step_scan_and_move_fit( det=det, motor=slit.x_centre, detname_suffix="value", start=start_pos, end=end_pos, fitted_loc=centre_type, num=num, ) yield from abs_set(slit.y_gap, y_scan_size, group=group_wait) yield from abs_set(slit.x_gap, x_open_size, group=group_wait) LOGGER.info(f"Moving to starting position for {slit.y_centre.name} alignment.") yield from wait(group=group_wait) start_pos, end_pos, num = cal_range_num(y_cen, y_range, y_scan_size) yield from step_scan_and_move_fit( det=det, motor=slit.y_centre, detname_suffix="value", start=start_pos, end=end_pos, fitted_loc=centre_type, num=num, ) yield from abs_set(slit.x_gap, x_final_size, group=group_wait) yield from abs_set(slit.y_gap, y_final_size, group=group_wait) yield from wait(group=group_wait) def move_to_direct_beam_position() -> MsgGenerator: """Remove everything in the way of the beam""" diff = diffractometer() s_stage = sample_stage() group_wait = "diff group A" yield from abs_set(diff.tth, 0, group=group_wait) yield from abs_set(diff.th, 0, group=group_wait) # type: ignore # See: https://github.com/bluesky/bluesky/issues/1809 yield from abs_set(s_stage.y, -3, group=group_wait) # type: ignore yield from wait(group=group_wait) def get_rasor_default_det() -> StandardReadable: """Return default detector and its name.""" det = RASOR_DEFAULT_DET return det