Skip to content

Commit

Permalink
I24 serial: Add some detector specific params in parameter model and …
Browse files Browse the repository at this point in the history
…beam center calculation (#708)

* Add lut file locations

* Start adding an example of detector params in model

* Trying to differentiate between detectors

* Some comments

* Move pilatus params to dodal

* Tidy up the parameters

* pin dodal

* Fix linting

* Save some old changes

* Fix tests

* Maybe if I add the file

* Pin dodal

* Fix test

* Try a dumb fix

* Remove casting

* Try something dumb again

* An untidy new try

* Remove mock

* Tidy up

* New calculation for beam center

* Add docstring

* Rething the beam center calculation and remove messy DetectorParams

* Also fix the dcm code broken by dodal branch

* Fix the tests

* Fix test in CI

* And two others

* Update dodal pin
  • Loading branch information
noemifrisina authored Jan 17, 2025
1 parent b4f7195 commit 1d79b9f
Show file tree
Hide file tree
Showing 17 changed files with 244 additions and 103 deletions.
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ dependencies = [
"matplotlib",
"nexgen",
"numpy",
"opencv-python", # Needed for I24 ssx moveonclick. To be changed to headless once this is moved to separate ui.
"opencv-python", # Needed for I24 ssx moveonclick. To be changed to headless once this is moved to separate ui.
"opentelemetry-distro",
"opentelemetry-exporter-otlp",
"pydantic",
Expand All @@ -46,7 +46,7 @@ dependencies = [
"ophyd == 1.9.0",
"ophyd-async >= 0.8a5",
"bluesky >= 1.13",
"dls-dodal @ git+https://github.com/DiamondLightSource/dodal.git@413aa34578c29b85f52944c29a76e248ab0eb87c",
"dls-dodal @ git+https://github.com/DiamondLightSource/dodal.git@main",
]


Expand Down
6 changes: 3 additions & 3 deletions src/mx_bluesky/beamlines/i24/serial/dcid.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import os
import subprocess
from functools import lru_cache
from typing import Literal

import bluesky.plan_stubs as bps
import requests
Expand All @@ -18,6 +17,7 @@
from mx_bluesky.beamlines.i24.serial.log import SSX_LOGGER
from mx_bluesky.beamlines.i24.serial.parameters import (
BeamSettings,
DetectorName,
ExtruderParameters,
FixedTargetParameters,
)
Expand Down Expand Up @@ -50,7 +50,7 @@ def read_beam_info_from_hardware(
dcm: DCM,
mirrors: FocusMirrorsMode,
beam_center: DetectorBeamCenter,
detector_name: Literal["eiger", "pilatus"],
detector_name: DetectorName,
):
""" Read the beam information from hardware.
Expand All @@ -59,7 +59,7 @@ def read_beam_info_from_hardware(
mirrors (FocusMirrorMode): The device describing the focus mirror mode settings.
beam_center (DetectorBeamCenter): A device to set and read the beam center on \
the detector.
detector_name (Literal["eiger", "pilatus"]): The detector currently in use.
detector_name (DetectorName): The detector currently in use.
Returns:
BeamSettings parameter model.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
log_on_entry,
)
from mx_bluesky.beamlines.i24.serial.parameters import ExtruderParameters
from mx_bluesky.beamlines.i24.serial.parameters.constants import BEAM_CENTER_LUT_FILES
from mx_bluesky.beamlines.i24.serial.setup_beamline import Pilatus, caget, caput, pv
from mx_bluesky.beamlines.i24.serial.setup_beamline import setup_beamline as sup
from mx_bluesky.beamlines.i24.serial.setup_beamline.setup_detector import (
Expand Down Expand Up @@ -213,8 +214,14 @@ def main_extruder_plan(
dcid: DCID,
start_time: datetime,
) -> MsgGenerator:
beam_center_pixels = sup.compute_beam_center_position_from_lut(
BEAM_CENTER_LUT_FILES[parameters.detector_name],
parameters.detector_distance_mm,
parameters.detector_size_constants,
)
yield from sup.set_detector_beam_center_plan(
beam_center_device, parameters.detector_name
beam_center_device,
beam_center_pixels,
)

# Setting up the beamline
Expand Down Expand Up @@ -288,7 +295,6 @@ def main_extruder_plan(
SSX_LOGGER.info("Using Eiger detector")

SSX_LOGGER.debug(f"Creating the directory for the collection in {filepath}.")
Path(filepath).mkdir(parents=True, exist_ok=True)

caput(pv.eiger_seqID, int(caget(pv.eiger_seqID)) + 1)
SSX_LOGGER.info(f"Eiger quickshot setup: filepath {filepath}")
Expand Down Expand Up @@ -495,6 +501,8 @@ def run_extruder_plan(
parameters: ExtruderParameters = yield from read_parameters(
detector_stage, attenuator
)
# Create collection directory
parameters.collection_directory.mkdir(parents=True, exist_ok=True)

beam_center_device = sup.get_beam_center_device(parameters.detector_name)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
)
from mx_bluesky.beamlines.i24.serial.log import SSX_LOGGER, log_on_entry
from mx_bluesky.beamlines.i24.serial.parameters import FixedTargetParameters
from mx_bluesky.beamlines.i24.serial.parameters.constants import BEAM_CENTER_LUT_FILES
from mx_bluesky.beamlines.i24.serial.setup_beamline import caget, cagetstring, caput, pv
from mx_bluesky.beamlines.i24.serial.setup_beamline import setup_beamline as sup
from mx_bluesky.beamlines.i24.serial.setup_beamline.setup_zebra_plans import (
Expand Down Expand Up @@ -410,7 +411,6 @@ def start_i24(
SSX_LOGGER.info("Using Eiger detector")

SSX_LOGGER.debug(f"Creating the directory for the collection in {filepath}.")
Path(filepath).mkdir(parents=True, exist_ok=True)

SSX_LOGGER.info(f"Triggered Eiger setup: filepath {filepath}")
SSX_LOGGER.info(f"Triggered Eiger setup: filename {filename}")
Expand Down Expand Up @@ -547,8 +547,14 @@ def main_fixed_target_plan(
) -> MsgGenerator:
SSX_LOGGER.info("Running a chip collection on I24")

beam_center_pixels = sup.compute_beam_center_position_from_lut(
BEAM_CENTER_LUT_FILES[parameters.detector_name],
parameters.detector_distance_mm,
parameters.detector_size_constants,
)
yield from sup.set_detector_beam_center_plan(
beam_center_device, parameters.detector_name
beam_center_device,
beam_center_pixels,
)

SSX_LOGGER.info("Getting Program Dictionary")
Expand Down Expand Up @@ -697,6 +703,9 @@ def run_fixed_target_plan(
detector_stage, attenuator
)

# Create collection directory
parameters.collection_directory.mkdir(parents=True, exist_ok=True)

if parameters.chip_map:
upload_chip_map_to_geobrick(pmac, parameters.chip_map)

Expand Down
3 changes: 2 additions & 1 deletion src/mx_bluesky/beamlines/i24/serial/parameters/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from mx_bluesky.beamlines.i24.serial.parameters.constants import SSXType
from mx_bluesky.beamlines.i24.serial.parameters.constants import DetectorName, SSXType
from mx_bluesky.beamlines.i24.serial.parameters.experiment_parameters import (
BeamSettings,
ChipDescription,
Expand All @@ -13,6 +13,7 @@

__all__ = [
"SSXType",
"DetectorName",
"BeamSettings",
"ExtruderParameters",
"ChipDescription",
Expand Down
18 changes: 13 additions & 5 deletions src/mx_bluesky/beamlines/i24/serial/parameters/constants.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
from enum import Enum
from enum import StrEnum
from os import environ
from pathlib import Path

from mx_bluesky.beamlines.i24.serial.log import _read_visit_directory_from_file


class SSXType(Enum):
class SSXType(StrEnum):
FIXED = "Serial Fixed"
EXTRUDER = "Serial Jet"


BEAM_CENTER_POS: dict[str, list] = {
"eiger": [1600.0, 1697.4],
"pilatus": [1284.7, 1308.6],
class DetectorName(StrEnum):
EIGER = "eiger"
PILATUS = "pilatus"


# TODO figue sth out for tests
LUT_FILES_PATH = Path("/dls_sw/i24/software/daq_configuration/lookup")

BEAM_CENTER_LUT_FILES = {
DetectorName.EIGER: LUT_FILES_PATH / "DetDistToBeamXYConverterE9M.txt",
DetectorName.PILATUS: LUT_FILES_PATH / "DetDistToBeamXYConverterP6M.txt",
}


Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import json
from abc import abstractmethod
from pathlib import Path
from typing import Literal

import numpy as np
from dodal.devices.detector.det_dim_constants import (
EIGER2_X_9M_SIZE,
PILATUS_6M_SIZE,
DetectorSizeConstants,
)
from pydantic import BaseModel, ConfigDict, computed_field, field_validator

from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import (
ChipType,
MappingType,
PumpProbeSetting,
)
from mx_bluesky.beamlines.i24.serial.parameters.constants import SSXType
from mx_bluesky.beamlines.i24.serial.parameters.constants import (
DetectorName,
SSXType,
)


class SerialExperiment(BaseModel):
Expand All @@ -22,7 +29,7 @@ class SerialExperiment(BaseModel):
filename: str
exposure_time_s: float
detector_distance_mm: float
detector_name: Literal["eiger", "pilatus"]
detector_name: DetectorName
transmission: float

@field_validator("visit", mode="before")
Expand All @@ -34,7 +41,16 @@ def _parse_visit(cls, visit: str | Path):

@property
def collection_directory(self) -> Path:
return Path(self.visit) / self.directory
directory = Path(self.visit) / self.directory
return directory

@property
def detector_size_constants(self) -> DetectorSizeConstants:
return (
EIGER2_X_9M_SIZE
if self.detector_name is DetectorName.EIGER
else PILATUS_6M_SIZE
)


class LaserExperiment(BaseModel):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
from pathlib import Path
from time import sleep

import bluesky.plan_stubs as bps
from dodal.beamlines import i24
from dodal.devices.detector.det_dim_constants import DetectorSizeConstants
from dodal.devices.i24.aperture import Aperture, AperturePositions
from dodal.devices.i24.beam_center import DetectorBeamCenter
from dodal.devices.i24.beamstop import Beamstop, BeamstopPositions
from dodal.devices.i24.dual_backlight import BacklightPositions, DualBacklight
from dodal.devices.i24.i24_detector_motion import DetectorMotion
from dodal.devices.util.lookup_tables import (
linear_interpolation_lut,
parse_lookup_table,
)

from mx_bluesky.beamlines.i24.serial.log import SSX_LOGGER
from mx_bluesky.beamlines.i24.serial.parameters.constants import BEAM_CENTER_POS
from mx_bluesky.beamlines.i24.serial.setup_beamline import pv
from mx_bluesky.beamlines.i24.serial.setup_beamline.ca import caget, caput

Expand All @@ -21,6 +26,35 @@ def get_beam_center_device(detector_in_use: str) -> DetectorBeamCenter:
return i24.pilatus_beam_center()


def compute_beam_center_position_from_lut(
lut_path: Path,
detector_distance_mm: float,
det_size_constants: DetectorSizeConstants,
) -> tuple[float, float]:
"""Calculate the beam center position for the detector distance \
using the values in the lookup table for the conversion.
"""
lut_values = parse_lookup_table(lut_path.as_posix())

calc_x = linear_interpolation_lut(lut_values[0], lut_values[1])
beam_x_mm = calc_x(detector_distance_mm)
beam_x = (
beam_x_mm
* det_size_constants.det_size_pixels.width
/ det_size_constants.det_dimension.width
)

calc_y = linear_interpolation_lut(lut_values[0], lut_values[2])
beam_y_mm = calc_y(detector_distance_mm)
beam_y = (
beam_y_mm
* det_size_constants.det_size_pixels.height
/ det_size_constants.det_dimension.height
)

return beam_x, beam_y


def setup_beamline_for_collection_plan(
aperture: Aperture,
backlight: DualBacklight,
Expand Down Expand Up @@ -55,22 +89,17 @@ def move_detector_stage_to_position_plan(

def set_detector_beam_center_plan(
beam_center_device: DetectorBeamCenter,
detector_name: str,
beam_center_pixels: tuple[float, float],
group: str = "set_beamcenter",
wait: bool = True,
):
"""A small temporary plan to set up the beam center on the detector in use."""
# NOTE This will be removed once the detectors are using ophyd_async devices
# See https://github.com/DiamondLightSource/mx-bluesky/issues/62
SSX_LOGGER.debug(
f"Set beam center on {detector_name} detector: {BEAM_CENTER_POS[detector_name]}"
)
yield from bps.abs_set(
beam_center_device.beam_x, BEAM_CENTER_POS[detector_name][0], group=group
)
yield from bps.abs_set(
beam_center_device.beam_y, BEAM_CENTER_POS[detector_name][1], group=group
)
beam_position_x, beam_position_y = beam_center_pixels
SSX_LOGGER.info(f"Setting beam center to: {beam_position_x}, {beam_position_y}")
yield from bps.abs_set(beam_center_device.beam_x, beam_position_x, group=group)
yield from bps.abs_set(beam_center_device.beam_y, beam_position_y, group=group)
if wait:
yield from bps.wait(group=group)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from dodal.devices.util.adjuster_plans import lookup_table_adjuster
from dodal.devices.util.lookup_tables import (
linear_interpolation_lut,
parse_lookup_table,
)

from mx_bluesky.common.utils.log import LOGGER
Expand Down Expand Up @@ -106,7 +107,9 @@ def adjust_dcm_pitch_roll_vfm_from_lut(
bragg_deg = energy_to_bragg_angle(energy_kev, d_spacing_a)
LOGGER.info(f"Target Bragg angle = {bragg_deg} degrees")
dcm_pitch_adjuster = lookup_table_adjuster(
linear_interpolation_lut(undulator_dcm.pitch_energy_table_path),
linear_interpolation_lut(
*parse_lookup_table(undulator_dcm.pitch_energy_table_path)
),
dcm.pitch_in_mrad,
bragg_deg,
)
Expand All @@ -116,7 +119,9 @@ def adjust_dcm_pitch_roll_vfm_from_lut(

# DCM Roll
dcm_roll_adjuster = lookup_table_adjuster(
linear_interpolation_lut(undulator_dcm.roll_energy_table_path),
linear_interpolation_lut(
*parse_lookup_table(undulator_dcm.roll_energy_table_path)
),
dcm.roll_in_mrad,
bragg_deg,
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#Table giving position of beam X and Y as a function of detector distance
#Units mm mm mm
# Eiger values
# distance beamY beamX (values from mosflm)
Units mm mm mm
200 119.78 127.0
1500 119.4 126.9
Loading

0 comments on commit 1d79b9f

Please sign in to comment.