From efbe991ef373a7c6fc1549eb31439b734d214231 Mon Sep 17 00:00:00 2001 From: Dominic Oram Date: Thu, 17 Oct 2024 13:09:25 +0100 Subject: [PATCH] Put wavelength into ispyb earlier (#566) * Read energy pre collection too * Ispyb callback will put energy related fields into database on either hardware read --- .../read_hardware_for_setup.py | 4 +-- .../flyscan_xray_centre_plan.py | 2 +- .../experiment_plans/rotation_scan_plan.py | 2 +- .../callbacks/ispyb_callback_base.py | 36 +++++++++++++------ .../experiment_plans/test_fgs_plan.py | 2 +- .../experiment_plans/test_plan_system.py | 2 +- .../test_flyscan_xray_centre_plan.py | 2 +- .../callbacks/conftest.py | 1 + .../callbacks/rotation/test_ispyb_callback.py | 4 +++ .../xray_centre/test_ispyb_callback.py | 27 ++++++-------- 10 files changed, 49 insertions(+), 33 deletions(-) diff --git a/src/mx_bluesky/hyperion/device_setup_plans/read_hardware_for_setup.py b/src/mx_bluesky/hyperion/device_setup_plans/read_hardware_for_setup.py index 7aa36a62c..5f45e5b66 100644 --- a/src/mx_bluesky/hyperion/device_setup_plans/read_hardware_for_setup.py +++ b/src/mx_bluesky/hyperion/device_setup_plans/read_hardware_for_setup.py @@ -6,7 +6,6 @@ from dodal.devices.dcm import DCM from dodal.devices.eiger import EigerDetector from dodal.devices.flux import Flux -from dodal.devices.robot import BartRobot from dodal.devices.s4_slit_gaps import S4SlitGaps from dodal.devices.smargon import Smargon from dodal.devices.synchrotron import Synchrotron @@ -20,7 +19,7 @@ def read_hardware_pre_collection( undulator: Undulator, synchrotron: Synchrotron, s4_slit_gaps: S4SlitGaps, - robot: BartRobot, + dcm: DCM, smargon: Smargon, ): LOGGER.info("Reading status of beamline for callbacks, pre collection.") @@ -34,6 +33,7 @@ def read_hardware_pre_collection( yield from bps.read(smargon.x) yield from bps.read(smargon.y) yield from bps.read(smargon.z) + yield from bps.read(dcm.energy_in_kev) yield from bps.save() diff --git a/src/mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py b/src/mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py index 9aa8c8b3a..be39c1b50 100755 --- a/src/mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +++ b/src/mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py @@ -267,7 +267,7 @@ def run_gridscan( fgs_composite.undulator, fgs_composite.synchrotron, fgs_composite.s4_slit_gaps, - fgs_composite.robot, + fgs_composite.dcm, fgs_composite.smargon, ) diff --git a/src/mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py b/src/mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py index 8fa777189..9fb389dfc 100644 --- a/src/mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +++ b/src/mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py @@ -252,7 +252,7 @@ def _rotation_scan_plan( composite.undulator, composite.synchrotron, composite.s4_slit_gaps, - composite.robot, + composite.dcm, composite.smargon, ) diff --git a/src/mx_bluesky/hyperion/external_interaction/callbacks/ispyb_callback_base.py b/src/mx_bluesky/hyperion/external_interaction/callbacks/ispyb_callback_base.py index f8bc99b6f..39bd25461 100644 --- a/src/mx_bluesky/hyperion/external_interaction/callbacks/ispyb_callback_base.py +++ b/src/mx_bluesky/hyperion/external_interaction/callbacks/ispyb_callback_base.py @@ -5,6 +5,7 @@ from typing import TYPE_CHECKING, Any, TypeVar, cast from dodal.beamline_specific_utils.i03 import beam_size_from_aperture +from dodal.devices.detector import DetectorParams from dodal.devices.detector.det_resolution import resolution from dodal.devices.synchrotron import SynchrotronMode @@ -33,6 +34,25 @@ from event_model.documents import Event, EventDescriptor, RunStart, RunStop +def _update_based_on_energy( + doc: Event, + detector_params: DetectorParams, + data_collection_info: DataCollectionInfo, +): + """If energy has been read as part of this reading then add it into the data + collection info along with the other fields that depend on it.""" + if energy_kev := doc["data"].get("dcm-energy_in_kev", None): + energy_ev = energy_kev * 1000 + wavelength_angstroms = convert_eV_to_angstrom(energy_ev) + data_collection_info.wavelength = wavelength_angstroms + data_collection_info.resolution = resolution( + detector_params, + wavelength_angstroms, + detector_params.detector_distance, + ) + return data_collection_info + + class BaseISPyBCallback(PlanReactiveCallback): def __init__( self, @@ -109,6 +129,9 @@ def _handle_ispyb_hardware_read(self, doc) -> Sequence[ScanDataInfo]: slitgap_horizontal=doc["data"]["s4_slit_gaps_xgap"], slitgap_vertical=doc["data"]["s4_slit_gaps_ygap"], ) + hwscan_data_collection_info = _update_based_on_energy( + doc, self.params.detector_params, hwscan_data_collection_info + ) hwscan_position_info = DataCollectionPositionInfo( pos_x=float(doc["data"]["smargon-x"]), pos_y=float(doc["data"]["smargon-y"]), @@ -137,16 +160,9 @@ def _handle_ispyb_transmission_flux_read(self, doc) -> Sequence[ScanDataInfo]: if transmission := doc["data"]["attenuator-actual_transmission"]: # Ispyb wants the transmission in a percentage, we use fractions hwscan_data_collection_info.transmission = transmission * 100 - event_energy = doc["data"]["dcm-energy_in_kev"] - if event_energy: - energy_ev = event_energy * 1000 - wavelength_angstroms = convert_eV_to_angstrom(energy_ev) - hwscan_data_collection_info.wavelength = wavelength_angstroms - hwscan_data_collection_info.resolution = resolution( - self.params.detector_params, - wavelength_angstroms, - self.params.detector_params.detector_distance, - ) + hwscan_data_collection_info = _update_based_on_energy( + doc, self.params.detector_params, hwscan_data_collection_info + ) scan_data_infos = self.populate_info_for_update( hwscan_data_collection_info, None, self.params ) diff --git a/tests/system_tests/hyperion/experiment_plans/test_fgs_plan.py b/tests/system_tests/hyperion/experiment_plans/test_fgs_plan.py index 7a46974b7..54dcfbc15 100644 --- a/tests/system_tests/hyperion/experiment_plans/test_fgs_plan.py +++ b/tests/system_tests/hyperion/experiment_plans/test_fgs_plan.py @@ -127,7 +127,7 @@ def test_read_hardware_pre_collection( @bpp.run_decorator() def read_run(u, s, g, r, a, f, dcm, ap_sg, sm): yield from read_hardware_pre_collection( - undulator=u, synchrotron=s, s4_slit_gaps=g, robot=r, smargon=sm + undulator=u, synchrotron=s, s4_slit_gaps=g, dcm=dcm, smargon=sm ) yield from read_hardware_during_collection( ap_sg, a, f, dcm, fxc_composite.eiger diff --git a/tests/system_tests/hyperion/experiment_plans/test_plan_system.py b/tests/system_tests/hyperion/experiment_plans/test_plan_system.py index b0d4eb682..53d03a955 100644 --- a/tests/system_tests/hyperion/experiment_plans/test_plan_system.py +++ b/tests/system_tests/hyperion/experiment_plans/test_plan_system.py @@ -55,7 +55,7 @@ async def test_getting_data_for_ispyb(): @bpp.run_decorator() def standalone_read_hardware(und, syn, slits, robot, att, flux, ap_sg, sm): - yield from read_hardware_pre_collection(und, syn, slits, robot, smargon=sm) + yield from read_hardware_pre_collection(und, syn, slits, dcm, smargon=sm) yield from read_hardware_during_collection(ap_sg, att, flux, dcm, eiger) RE( diff --git a/tests/unit_tests/hyperion/experiment_plans/test_flyscan_xray_centre_plan.py b/tests/unit_tests/hyperion/experiment_plans/test_flyscan_xray_centre_plan.py index 77071c9a6..045458841 100644 --- a/tests/unit_tests/hyperion/experiment_plans/test_flyscan_xray_centre_plan.py +++ b/tests/unit_tests/hyperion/experiment_plans/test_flyscan_xray_centre_plan.py @@ -126,7 +126,7 @@ def ispyb_plan(test_fgs_params: ThreeDGridScan): def standalone_read_hardware_for_ispyb( und, syn, slits, robot, attn, fl, dcm, ap_sg, sm, det ): - yield from read_hardware_pre_collection(und, syn, slits, robot, sm) + yield from read_hardware_pre_collection(und, syn, slits, dcm, sm) yield from read_hardware_during_collection(ap_sg, attn, fl, dcm, det) return standalone_read_hardware_for_ispyb diff --git a/tests/unit_tests/hyperion/external_interaction/callbacks/conftest.py b/tests/unit_tests/hyperion/external_interaction/callbacks/conftest.py index e016c31b1..c3c3aea44 100644 --- a/tests/unit_tests/hyperion/external_interaction/callbacks/conftest.py +++ b/tests/unit_tests/hyperion/external_interaction/callbacks/conftest.py @@ -172,6 +172,7 @@ class TestData(OavGridSnapshotTestEvents): "smargon-x": 0.158435435, "smargon-y": 0.023547354, "smargon-z": 0.00345684712, + "dcm-energy_in_kev": 11.105, }, "timestamps": {"det1": 1666604299.8220396, "det2": 1666604299.8235943}, "seq_num": 1, diff --git a/tests/unit_tests/hyperion/external_interaction/callbacks/rotation/test_ispyb_callback.py b/tests/unit_tests/hyperion/external_interaction/callbacks/rotation/test_ispyb_callback.py index 9a42e3b80..7bbc285d0 100644 --- a/tests/unit_tests/hyperion/external_interaction/callbacks/rotation/test_ispyb_callback.py +++ b/tests/unit_tests/hyperion/external_interaction/callbacks/rotation/test_ispyb_callback.py @@ -141,6 +141,8 @@ def test_hardware_read_events( "synchrotronmode": "User", "undulatorgap1": 1.234, "comments": "Sample position (µm): (158, 24, 3) test ", + "resolution": 1.1830593328548429, + "wavelength": 1.1164718451643736, }, ) expected_data = TestData.test_event_document_pre_data_collection["data"] @@ -318,5 +320,7 @@ def test_comment_correct_after_hardware_read( "synchrotronmode": "User", "undulatorgap1": 1.234, "comments": "Sample position (µm): (158, 24, 3) a lovely unit test ", + "resolution": 1.1830593328548429, + "wavelength": 1.1164718451643736, }, ) diff --git a/tests/unit_tests/hyperion/external_interaction/callbacks/xray_centre/test_ispyb_callback.py b/tests/unit_tests/hyperion/external_interaction/callbacks/xray_centre/test_ispyb_callback.py index 845b5cf44..d5fda80ad 100644 --- a/tests/unit_tests/hyperion/external_interaction/callbacks/xray_centre/test_ispyb_callback.py +++ b/tests/unit_tests/hyperion/external_interaction/callbacks/xray_centre/test_ispyb_callback.py @@ -86,29 +86,24 @@ def test_hardware_read_event_3d(self, mock_ispyb_conn): ) callback.activity_gated_event(TestData.test_event_document_pre_data_collection) mx_acq.upsert_data_collection_group.assert_not_called() + expected_upsert = { + "parentid": TEST_DATA_COLLECTION_GROUP_ID, + "slitgaphorizontal": 0.1234, + "slitgapvertical": 0.2345, + "synchrotronmode": "User", + "undulatorgap1": 1.234, + "resolution": 1.1830593328548429, + "wavelength": 1.1164718451643736, + } assert_upsert_call_with( mx_acq.upsert_data_collection.mock_calls[0], mx_acq.get_data_collection_params(), - { - "parentid": TEST_DATA_COLLECTION_GROUP_ID, - "id": TEST_DATA_COLLECTION_IDS[0], - "slitgaphorizontal": 0.1234, - "slitgapvertical": 0.2345, - "synchrotronmode": "User", - "undulatorgap1": 1.234, - }, + {"id": TEST_DATA_COLLECTION_IDS[0], **expected_upsert}, ) assert_upsert_call_with( mx_acq.upsert_data_collection.mock_calls[1], mx_acq.get_data_collection_params(), - { - "parentid": TEST_DATA_COLLECTION_GROUP_ID, - "id": TEST_DATA_COLLECTION_IDS[1], - "slitgaphorizontal": 0.1234, - "slitgapvertical": 0.2345, - "synchrotronmode": "User", - "undulatorgap1": 1.234, - }, + {"id": TEST_DATA_COLLECTION_IDS[1], **expected_upsert}, ) def test_flux_read_events_3d(self, mock_ispyb_conn):