diff --git a/setup.cfg b/setup.cfg index f3250ea50..d22974ede 100644 --- a/setup.cfg +++ b/setup.cfg @@ -45,7 +45,7 @@ install_requires = ophyd-async >= 0.3a5 bluesky >= 1.13.0a3 blueapi >= 0.4.3-a1 - dls-dodal @ git+https://github.com/DiamondLightSource/dodal.git@4123dada042d62a750194d7c715662a3690cf25c + dls-dodal @ git+https://github.com/DiamondLightSource/dodal.git@ba2e0da424cf7a82e724f278b668987575cf8a52 [options.entry_points] console_scripts = diff --git a/src/hyperion/__main__.py b/src/hyperion/__main__.py index 3dcfe092b..e18dd84f2 100755 --- a/src/hyperion/__main__.py +++ b/src/hyperion/__main__.py @@ -213,9 +213,7 @@ def compose_start_args(context: BlueskyContext, plan_name: str, action: Actions) if experiment_registry_entry is None: raise PlanNotFound(f"Experiment plan '{plan_name}' not found in registry.") - experiment_internal_param_type = experiment_registry_entry.get( - "internal_param_type" - ) + experiment_internal_param_type = experiment_registry_entry.get("param_type") callback_type = experiment_registry_entry.get("callback_collection_type") plan = context.plan_functions.get(plan_name) if experiment_internal_param_type is None: diff --git a/src/hyperion/experiment_plans/experiment_registry.py b/src/hyperion/experiment_plans/experiment_registry.py index e505c8764..504a95e90 100644 --- a/src/hyperion/experiment_plans/experiment_registry.py +++ b/src/hyperion/experiment_plans/experiment_registry.py @@ -1,10 +1,6 @@ from __future__ import annotations -from typing import Callable, TypedDict, Union - -from dodal.devices.fast_grid_scan import GridScanParams -from dodal.devices.panda_fast_grid_scan import PandAGridScanParams -from dodal.parameters.experiment_parameter_base import AbstractExperimentWithBeamParams +from typing import Callable, TypedDict import hyperion.experiment_plans.flyscan_xray_centre_plan as flyscan_xray_centre_plan import hyperion.experiment_plans.panda_flyscan_xray_centre_plan as panda_flyscan_xray_centre_plan @@ -26,18 +22,6 @@ RobotLoadThenCentre, ThreeDGridScan, ) -from hyperion.parameters.plan_specific.grid_scan_with_edge_detect_params import ( - GridScanWithEdgeDetectParams, -) -from hyperion.parameters.plan_specific.pin_centre_then_xray_centre_params import ( - PinCentreThenXrayCentreParams, -) -from hyperion.parameters.plan_specific.robot_load_then_center_params import ( - RobotLoadThenCentreParams, -) -from hyperion.parameters.plan_specific.rotation_scan_internal_params import ( - RotationScanParams, -) from hyperion.parameters.rotation import RotationScan @@ -51,59 +35,48 @@ def do_nothing(): class ExperimentRegistryEntry(TypedDict): setup: Callable - internal_param_type: type[ + param_type: type[ ThreeDGridScan | GridScanWithEdgeDetect | RotationScan | PinTipCentreThenXrayCentre | RobotLoadThenCentre ] - experiment_param_type: type[AbstractExperimentWithBeamParams] callbacks_factory: CallbacksFactory -EXPERIMENT_TYPES = Union[GridScanParams, RotationScanParams] PLAN_REGISTRY: dict[str, ExperimentRegistryEntry] = { "panda_flyscan_xray_centre": { "setup": panda_flyscan_xray_centre_plan.create_devices, - "internal_param_type": ThreeDGridScan, - "experiment_param_type": PandAGridScanParams, + "param_type": ThreeDGridScan, "callbacks_factory": create_gridscan_callbacks, }, "flyscan_xray_centre": { "setup": flyscan_xray_centre_plan.create_devices, - "internal_param_type": ThreeDGridScan, - "experiment_param_type": GridScanParams, + "param_type": ThreeDGridScan, "callbacks_factory": create_gridscan_callbacks, }, "grid_detect_then_xray_centre": { "setup": grid_detect_then_xray_centre_plan.create_devices, - "internal_param_type": GridScanWithEdgeDetect, - "experiment_param_type": GridScanWithEdgeDetectParams, + "param_type": GridScanWithEdgeDetect, "callbacks_factory": create_gridscan_callbacks, }, "rotation_scan": { "setup": rotation_scan_plan.create_devices, - "internal_param_type": RotationScan, - "experiment_param_type": RotationScanParams, + "param_type": RotationScan, "callbacks_factory": create_rotation_callbacks, }, "pin_tip_centre_then_xray_centre": { "setup": pin_centre_then_xray_centre_plan.create_devices, - "internal_param_type": PinTipCentreThenXrayCentre, - "experiment_param_type": PinCentreThenXrayCentreParams, + "param_type": PinTipCentreThenXrayCentre, "callbacks_factory": create_gridscan_callbacks, }, "robot_load_then_centre": { "setup": robot_load_then_centre_plan.create_devices, - "internal_param_type": RobotLoadThenCentre, - "experiment_param_type": RobotLoadThenCentreParams, + "param_type": RobotLoadThenCentre, "callbacks_factory": create_robot_load_and_centre_callbacks, }, } -EXPERIMENT_NAMES = list(PLAN_REGISTRY.keys()) -EXPERIMENT_TYPE_LIST = [p["experiment_param_type"] for p in PLAN_REGISTRY.values()] -EXPERIMENT_TYPE_DICT = dict(zip(EXPERIMENT_NAMES, EXPERIMENT_TYPE_LIST)) class PlanNotFound(Exception): diff --git a/src/hyperion/experiment_plans/flyscan_xray_centre_plan.py b/src/hyperion/experiment_plans/flyscan_xray_centre_plan.py index b336f1af2..204eb89f5 100755 --- a/src/hyperion/experiment_plans/flyscan_xray_centre_plan.py +++ b/src/hyperion/experiment_plans/flyscan_xray_centre_plan.py @@ -165,6 +165,7 @@ def kickoff_and_complete_gridscan( synchrotron: Synchrotron, zocalo_environment: str, scan_points: list[AxesPoints[Axis]], + scan_start_indices: list[int], ): @TRACER.start_as_current_span(CONST.PLAN.DO_FGS) @bpp.set_run_key_decorator(CONST.PLAN.DO_FGS) @@ -173,6 +174,7 @@ def kickoff_and_complete_gridscan( "subplan_name": CONST.PLAN.DO_FGS, "zocalo_environment": zocalo_environment, "scan_points": scan_points, + "scan_start_indices": scan_start_indices, } ) @bpp.contingency_decorator( @@ -261,10 +263,8 @@ def run_gridscan( fgs_composite.eiger, fgs_composite.synchrotron, parameters.zocalo_environment, - [ - parameters.old_parameters().get_scan_points(1), - parameters.old_parameters().get_scan_points(2), - ], + [parameters.scan_points_first_grid, parameters.scan_points_second_grid], + parameters.scan_indices, ) yield from bps.abs_set(fgs_motors.z_steps, 0, wait=False) @@ -349,7 +349,7 @@ def flyscan_xray_centre( at any point in it. Args: - parameters (FGSInternalParameters): The parameters to run the scan. + parameters (ThreeDGridScan): The parameters to run the scan. Returns: Generator: The plan for the gridscan @@ -363,7 +363,7 @@ def flyscan_xray_centre( md={ "subplan_name": CONST.PLAN.GRIDSCAN_OUTER, CONST.TRIGGER.ZOCALO: CONST.PLAN.DO_FGS, - "hyperion_internal_parameters": parameters.old_parameters().json(), + "hyperion_parameters": parameters.json(), "activate_callbacks": [ "GridscanNexusFileCallback", ], diff --git a/src/hyperion/experiment_plans/panda_flyscan_xray_centre_plan.py b/src/hyperion/experiment_plans/panda_flyscan_xray_centre_plan.py index 52ac5bc69..0764f91ed 100755 --- a/src/hyperion/experiment_plans/panda_flyscan_xray_centre_plan.py +++ b/src/hyperion/experiment_plans/panda_flyscan_xray_centre_plan.py @@ -126,10 +126,8 @@ def run_gridscan( fgs_composite.eiger, fgs_composite.synchrotron, parameters.zocalo_environment, - [ - parameters.old_parameters().get_scan_points(1), - parameters.old_parameters().get_scan_points(2), - ], + [parameters.scan_points_first_grid, parameters.scan_points_second_grid], + parameters.scan_indices, ) yield from bps.abs_set(fgs_motors.z_steps, 0, wait=False) @@ -266,7 +264,7 @@ def panda_flyscan_xray_centre( at any point in it. Args: - parameters (FGSInternalParameters): The parameters to run the scan. + parameters (ThreeDGridScan): The parameters to run the scan. Returns: Generator: The plan for the gridscan @@ -281,7 +279,7 @@ def panda_flyscan_xray_centre( md={ "subplan_name": CONST.PLAN.GRIDSCAN_OUTER, CONST.TRIGGER.ZOCALO: CONST.PLAN.DO_FGS, - "hyperion_internal_parameters": parameters.old_parameters().json(), + "hyperion_parameters": parameters.json(), "activate_callbacks": [ "GridscanNexusFileCallback", ], diff --git a/src/hyperion/experiment_plans/rotation_scan_plan.py b/src/hyperion/experiment_plans/rotation_scan_plan.py index ca2c5bb52..5e3405ce6 100644 --- a/src/hyperion/experiment_plans/rotation_scan_plan.py +++ b/src/hyperion/experiment_plans/rotation_scan_plan.py @@ -254,7 +254,7 @@ def rotation_scan( md={ "subplan_name": CONST.PLAN.ROTATION_OUTER, CONST.TRIGGER.ZOCALO: CONST.PLAN.ROTATION_MAIN, - "hyperion_internal_parameters": parameters.old_parameters().json(), + "hyperion_parameters": parameters.json(), "activate_callbacks": [ "RotationISPyBCallback", "RotationNexusFileCallback", diff --git a/src/hyperion/external_interaction/callbacks/common/ispyb_mapping.py b/src/hyperion/external_interaction/callbacks/common/ispyb_mapping.py index 35a6a8dad..e26d6d635 100644 --- a/src/hyperion/external_interaction/callbacks/common/ispyb_mapping.py +++ b/src/hyperion/external_interaction/callbacks/common/ispyb_mapping.py @@ -20,15 +20,14 @@ get_current_time_string, ) from hyperion.log import ISPYB_LOGGER +from hyperion.parameters.components import DiffractionExperimentWithSample -def populate_data_collection_group( - experiment_type: str, detector_params: DetectorParams, ispyb_params: IspybParams -): +def populate_data_collection_group(params: DiffractionExperimentWithSample): dcg_info = DataCollectionGroupInfo( - visit_string=get_visit_string(ispyb_params, detector_params), - experiment_type=experiment_type, - sample_id=ispyb_params.sample_id, + visit_string=params.visit, + experiment_type=params.ispyb_experiment_type.value, + sample_id=params.sample_id, ) return dcg_info @@ -47,38 +46,33 @@ def populate_remaining_data_collection_info( comment, data_collection_group_id, data_collection_info: DataCollectionInfo, - detector_params, - ispyb_params, + params: DiffractionExperimentWithSample, ): - data_collection_info.visit_string = get_visit_string(ispyb_params, detector_params) + data_collection_info.visit_string = params.visit data_collection_info.parent_id = data_collection_group_id - data_collection_info.sample_id = ispyb_params.sample_id + data_collection_info.sample_id = params.sample_id data_collection_info.detector_id = I03_EIGER_DETECTOR data_collection_info.axis_start = data_collection_info.omega_start - data_collection_info.focal_spot_size_at_samplex = ispyb_params.focal_spot_size_x - data_collection_info.focal_spot_size_at_sampley = ispyb_params.focal_spot_size_y - data_collection_info.beamsize_at_samplex = ispyb_params.beam_size_x - data_collection_info.beamsize_at_sampley = ispyb_params.beam_size_y data_collection_info.comments = comment - data_collection_info.detector_distance = detector_params.detector_distance - data_collection_info.exp_time = detector_params.exposure_time - data_collection_info.imgdir = detector_params.directory - data_collection_info.imgprefix = detector_params.prefix + data_collection_info.detector_distance = params.detector_params.detector_distance + data_collection_info.exp_time = params.detector_params.exposure_time + data_collection_info.imgdir = params.detector_params.directory + data_collection_info.imgprefix = params.detector_params.prefix data_collection_info.imgsuffix = EIGER_FILE_SUFFIX # Both overlap and n_passes included for backwards compatibility, # planned to be removed later data_collection_info.n_passes = 1 data_collection_info.overlap = 0 data_collection_info.start_image_number = 1 - beam_position = detector_params.get_beam_position_mm( - detector_params.detector_distance + beam_position = params.detector_params.get_beam_position_mm( + params.detector_params.detector_distance ) data_collection_info.xbeam = beam_position[0] data_collection_info.ybeam = beam_position[1] data_collection_info.start_time = get_current_time_string() # temporary file template until nxs filewriting is integrated and we can use # that file name - data_collection_info.file_template = f"{detector_params.prefix}_{data_collection_info.data_collection_number}_master.h5" + data_collection_info.file_template = f"{params.detector_params.prefix}_{data_collection_info.data_collection_number}_master.h5" return data_collection_info diff --git a/src/hyperion/external_interaction/callbacks/ispyb_callback_base.py b/src/hyperion/external_interaction/callbacks/ispyb_callback_base.py index f13d5e300..7d0b6705b 100644 --- a/src/hyperion/external_interaction/callbacks/ispyb_callback_base.py +++ b/src/hyperion/external_interaction/callbacks/ispyb_callback_base.py @@ -4,6 +4,8 @@ from collections.abc import Sequence from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, TypeVar +from dodal.beamline_specific_utils.i03 import beam_size_from_aperture +from dodal.devices.aperturescatterguard import SingleAperturePosition from dodal.devices.detector.det_resolution import resolution from dodal.devices.synchrotron import SynchrotronMode @@ -25,14 +27,8 @@ ) from hyperion.external_interaction.ispyb.ispyb_utils import get_ispyb_config from hyperion.log import ISPYB_LOGGER, set_dcgid_tag +from hyperion.parameters.components import DiffractionExperimentWithSample from hyperion.parameters.constants import CONST -from hyperion.parameters.internal_parameters import InternalParameters -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanInternalParameters, -) -from hyperion.parameters.plan_specific.rotation_scan_internal_params import ( - RotationInternalParameters, -) from hyperion.utils.utils import convert_eV_to_angstrom from .logging_callback import format_doc_for_log @@ -54,9 +50,7 @@ def __init__( ISPYB_LOGGER.debug("Initialising ISPyB callback") super().__init__(log=ISPYB_LOGGER, emit=emit) self._oav_snapshot_event_idx: int = 0 - self.params: GridscanInternalParameters | RotationInternalParameters | None = ( - None - ) + self.params: DiffractionExperimentWithSample | None = None self.ispyb: StoreInIspyb self.descriptors: Dict[str, EventDescriptor] = {} self.ispyb_config = get_ispyb_config() @@ -115,7 +109,15 @@ def _handle_ispyb_hardware_read(self, doc) -> Sequence[ScanDataInfo]: synchrotron_mode := doc["data"]["synchrotron-synchrotron_mode"], SynchrotronMode, ) + aperture_size = SingleAperturePosition( + **doc["data"]["aperture_scatterguard-selected_aperture"] + ) + beamsize = beam_size_from_aperture(aperture_size) hwscan_data_collection_info = DataCollectionInfo( + beamsize_at_samplex=beamsize.x_um, + beamsize_at_sampley=beamsize.y_um, + focal_spot_size_at_samplex=beamsize.x_um, + focal_spot_size_at_sampley=beamsize.y_um, undulator_gap1=doc["data"]["undulator-current_gap"], synchrotron_mode=synchrotron_mode.value, slitgap_horizontal=doc["data"]["s4_slit_gaps_xgap"], @@ -186,9 +188,9 @@ def _handle_ispyb_transmission_flux_read(self, doc) -> Sequence[ScanDataInfo]: wavelength_angstroms = convert_eV_to_angstrom(energy_ev) hwscan_data_collection_info.wavelength = wavelength_angstroms hwscan_data_collection_info.resolution = resolution( - self.params.hyperion_params.detector_params, + self.params.detector_params, wavelength_angstroms, - self.params.hyperion_params.detector_params.detector_distance, + self.params.detector_params.detector_distance, ) scan_data_infos = self.populate_info_for_update( hwscan_data_collection_info, self.params @@ -200,7 +202,7 @@ def _handle_ispyb_transmission_flux_read(self, doc) -> Sequence[ScanDataInfo]: def populate_info_for_update( self, event_sourced_data_collection_info: DataCollectionInfo, - params: InternalParameters, + params: DiffractionExperimentWithSample, ) -> Sequence[ScanDataInfo]: pass diff --git a/src/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py b/src/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py index 72c638d47..fd226936f 100644 --- a/src/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +++ b/src/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py @@ -25,9 +25,7 @@ from hyperion.log import ISPYB_LOGGER, set_dcgid_tag from hyperion.parameters.components import IspybExperimentType from hyperion.parameters.constants import CONST -from hyperion.parameters.plan_specific.rotation_scan_internal_params import ( - RotationInternalParameters, -) +from hyperion.parameters.rotation import RotationScan if TYPE_CHECKING: from event_model.documents import Event, RunStart, RunStop @@ -56,7 +54,7 @@ def __init__( emit: Callable[..., Any] | None = None, ) -> None: super().__init__(emit=emit) - self.last_sample_id: str | None = None + self.last_sample_id: int | None = None self.ispyb_ids: IspybIds = IspybIds() def activity_gated_start(self, doc: RunStart): @@ -64,57 +62,32 @@ def activity_gated_start(self, doc: RunStart): ISPYB_LOGGER.info( "ISPyB callback recieved start document with experiment parameters." ) - json_params = doc.get("hyperion_internal_parameters") - self.params = RotationInternalParameters.from_json(json_params) + self.params = RotationScan.from_json(doc.get("hyperion_parameters")) dcgid = ( self.ispyb_ids.data_collection_group_id - if ( - self.params.hyperion_params.ispyb_params.sample_id - == self.last_sample_id - ) + if (self.params.sample_id == self.last_sample_id) else None ) - n_images = self.params.experiment_params.get_num_images() - if n_images < 200: - ISPYB_LOGGER.info( - f"Collection has {n_images} images - treating as a screening collection - new DCG" - ) + if ( + self.params.ispyb_experiment_type + == IspybExperimentType.CHARACTERIZATION + ): + ISPYB_LOGGER.info("Screening collection - using new DCG") dcgid = None self.last_sample_id = None else: ISPYB_LOGGER.info( - f"Collection has {n_images} images - treating as a genuine dataset - storing sampleID to bundle images" - ) - self.last_sample_id = self.params.hyperion_params.ispyb_params.sample_id - experiment_type = ( - self.params.hyperion_params.ispyb_params.ispyb_experiment_type - ) - if experiment_type: - self.ispyb = StoreInIspyb( - self.ispyb_config, - IspybExperimentType(experiment_type), - ) - else: - self.ispyb = StoreInIspyb( - self.ispyb_config, IspybExperimentType.ROTATION + f"Collection is {self.params.ispyb_experiment_type} - storing sampleID to bundle images" ) + self.last_sample_id = self.params.sample_id + self.ispyb = StoreInIspyb(self.ispyb_config) ISPYB_LOGGER.info("Beginning ispyb deposition") - data_collection_group_info = populate_data_collection_group( - self.ispyb.experiment_type, - self.params.hyperion_params.detector_params, - self.params.hyperion_params.ispyb_params, - ) + data_collection_group_info = populate_data_collection_group(self.params) data_collection_info = populate_data_collection_info_for_rotation( - self.params.hyperion_params.ispyb_params, - self.params.hyperion_params.detector_params, - self.params, + self.params ) data_collection_info = populate_remaining_data_collection_info( - COMMENT_FOR_ROTATION_SCAN, - dcgid, - data_collection_info, - self.params.hyperion_params.detector_params, - self.params.hyperion_params.ispyb_params, + COMMENT_FOR_ROTATION_SCAN, dcgid, data_collection_info, self.params ) data_collection_info.parent_id = dcgid scan_data_info = ScanDataInfo( @@ -134,12 +107,12 @@ def populate_info_for_update( assert ( self.ispyb_ids.data_collection_ids ), "Expect an existing DataCollection to update" - params = cast(RotationInternalParameters, params) + params = cast(RotationScan, params) return [ ScanDataInfo( data_collection_info=event_sourced_data_collection_info, data_collection_position_info=populate_data_collection_position_info( - params.hyperion_params.ispyb_params + params.ispyb_params ), data_collection_id=self.ispyb_ids.data_collection_ids[0], ) diff --git a/src/hyperion/external_interaction/callbacks/rotation/ispyb_mapping.py b/src/hyperion/external_interaction/callbacks/rotation/ispyb_mapping.py index 78d70bf5f..0a84c3bb7 100644 --- a/src/hyperion/external_interaction/callbacks/rotation/ispyb_mapping.py +++ b/src/hyperion/external_interaction/callbacks/rotation/ispyb_mapping.py @@ -4,25 +4,19 @@ get_xtal_snapshots, ) from hyperion.external_interaction.ispyb.data_model import DataCollectionInfo +from hyperion.parameters.rotation import RotationScan -def populate_data_collection_info_for_rotation( - ispyb_params, detector_params, full_params -): +def populate_data_collection_info_for_rotation(params: RotationScan): info = DataCollectionInfo( - omega_start=detector_params.omega_start, - data_collection_number=detector_params.run_number, # type:ignore # the validator always makes this int - n_images=full_params.experiment_params.get_num_images(), - axis_range=full_params.experiment_params.image_width, - axis_end=( - full_params.experiment_params.omega_start - + full_params.experiment_params.rotation_angle - ), - kappa_start=full_params.experiment_params.chi_start, + omega_start=params.omega_start_deg, + data_collection_number=params.detector_params.run_number, # type:ignore # the validator always makes this int + n_images=params.num_images, + axis_range=params.rotation_increment_deg, + axis_end=(params.omega_start_deg + params.scan_width_deg), + kappa_start=params.kappa_start_deg, + ) + (info.xtal_snapshot1, info.xtal_snapshot2, info.xtal_snapshot3) = ( + get_xtal_snapshots(params.ispyb_params) ) - ( - info.xtal_snapshot1, - info.xtal_snapshot2, - info.xtal_snapshot3, - ) = get_xtal_snapshots(ispyb_params) return info diff --git a/src/hyperion/external_interaction/callbacks/rotation/nexus_callback.py b/src/hyperion/external_interaction/callbacks/rotation/nexus_callback.py index 50f5f8074..b06ee7461 100644 --- a/src/hyperion/external_interaction/callbacks/rotation/nexus_callback.py +++ b/src/hyperion/external_interaction/callbacks/rotation/nexus_callback.py @@ -12,9 +12,7 @@ from hyperion.external_interaction.nexus.write_nexus import NexusWriter from hyperion.log import NEXUS_LOGGER from hyperion.parameters.constants import CONST -from hyperion.parameters.plan_specific.rotation_scan_internal_params import ( - RotationInternalParameters, -) +from hyperion.parameters.rotation import RotationScan from ..logging_callback import format_doc_for_log @@ -38,7 +36,6 @@ class RotationNexusFileCallback(PlanReactiveCallback): def __init__(self) -> None: super().__init__(NEXUS_LOGGER) self.run_uid: str | None = None - self.parameters: RotationInternalParameters | None = None self.writer: NexusWriter | None = None self.descriptors: Dict[str, EventDescriptor] = {} @@ -47,7 +44,6 @@ def activity_gated_descriptor(self, doc: EventDescriptor): def activity_gated_event(self, doc: Event): event_descriptor = self.descriptors.get(doc["descriptor"]) - assert isinstance(self.parameters, RotationInternalParameters) if event_descriptor is None: NEXUS_LOGGER.warning( f"Rotation Nexus handler {self} received event doc {format_doc_for_log(doc)} and " @@ -84,14 +80,20 @@ def activity_gated_event(self, doc: Event): def activity_gated_start(self, doc: RunStart): if doc.get("subplan_name") == CONST.PLAN.ROTATION_OUTER: self.run_uid = doc.get("uid") - json_params = doc.get("hyperion_internal_parameters") + json_params = doc.get("hyperion_parameters") NEXUS_LOGGER.info( f"Nexus writer received start document with experiment parameters {json_params}" ) - self.parameters = RotationInternalParameters.from_json(json_params) + parameters = RotationScan.from_json(json_params) NEXUS_LOGGER.info("Setting up nexus file...") + det_size = ( + parameters.detector_params.detector_size_constants.det_size_pixels + ) + shape = (parameters.num_images, det_size.width, det_size.height) self.writer = NexusWriter( - self.parameters, - self.parameters.get_scan_points(), - self.parameters.get_data_shape(), + parameters, + shape, + parameters.scan_points, + omega_start_deg=parameters.omega_start_deg, + chi_start_deg=parameters.chi_start_deg or 0, ) diff --git a/src/hyperion/external_interaction/callbacks/xray_centre/ispyb_callback.py b/src/hyperion/external_interaction/callbacks/xray_centre/ispyb_callback.py index d3de739e7..a539e402a 100644 --- a/src/hyperion/external_interaction/callbacks/xray_centre/ispyb_callback.py +++ b/src/hyperion/external_interaction/callbacks/xray_centre/ispyb_callback.py @@ -2,9 +2,10 @@ from collections.abc import Sequence from time import time -from typing import TYPE_CHECKING, Any, Callable, List, cast +from typing import TYPE_CHECKING, Any, Callable, List import numpy as np +from blueapi.core import MsgGenerator from bluesky import preprocessors as bpp from dodal.devices.zocalo.zocalo_results import ZOCALO_READING_PLAN_NAME @@ -31,27 +32,24 @@ StoreInIspyb, ) from hyperion.log import ISPYB_LOGGER, set_dcgid_tag -from hyperion.parameters.components import IspybExperimentType from hyperion.parameters.constants import CONST -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanInternalParameters, +from hyperion.parameters.gridscan import ( + GridCommon, + GridScanWithEdgeDetect, + ThreeDGridScan, ) if TYPE_CHECKING: from event_model import Event, RunStart, RunStop -def ispyb_activation_wrapper(plan_generator, parameters): +def ispyb_activation_wrapper(plan_generator: MsgGenerator, parameters): return bpp.run_wrapper( plan_generator, md={ "activate_callbacks": ["GridscanISPyBCallback"], "subplan_name": CONST.PLAN.GRID_DETECT_AND_DO_GRIDSCAN, - "hyperion_internal_parameters": ( - parameters.old_parameters() - if callable(getattr(parameters, "old_parameters", 0)) - else parameters - ).json(), + "hyperion_parameters": parameters.json(), }, ) @@ -77,7 +75,6 @@ def __init__( emit: Callable[..., Any] | None = None, ) -> None: super().__init__(emit=emit) - self.params: GridscanInternalParameters self.ispyb: StoreInIspyb self.ispyb_ids: IspybIds = IspybIds() self._start_of_fgs_uid: str | None = None @@ -92,16 +89,11 @@ def activity_gated_start(self, doc: RunStart): "ISPyB callback recieved start document with experiment parameters and " f"uid: {self.uid_to_finalize_on}" ) - json_params = doc.get("hyperion_internal_parameters") - self.params = GridscanInternalParameters.from_json(json_params) - self.ispyb = StoreInIspyb( - self.ispyb_config, IspybExperimentType.GRIDSCAN_3D - ) - data_collection_group_info = populate_data_collection_group( - self.ispyb.experiment_type, - self.params.hyperion_params.detector_params, - self.params.hyperion_params.ispyb_params, + self.params = GridCommon.from_json( + doc.get("hyperion_parameters"), allow_extras=True ) + self.ispyb = StoreInIspyb(self.ispyb_config) + data_collection_group_info = populate_data_collection_group(self.params) scan_data_infos = [ ScanDataInfo( @@ -109,21 +101,17 @@ def activity_gated_start(self, doc: RunStart): None, None, populate_xy_data_collection_info( - self.params.hyperion_params.detector_params, + self.params.detector_params, ), - self.params.hyperion_params.detector_params, - self.params.hyperion_params.ispyb_params, + self.params, ), ), ScanDataInfo( data_collection_info=populate_remaining_data_collection_info( None, None, - populate_xz_data_collection_info( - self.params.hyperion_params.detector_params - ), - self.params.hyperion_params.detector_params, - self.params.hyperion_params.ispyb_params, + populate_xz_data_collection_info(self.params.detector_params), + self.params, ) ), ] @@ -176,16 +164,17 @@ def activity_gated_event(self, doc: Event): return doc def populate_info_for_update( - self, event_sourced_data_collection_info: DataCollectionInfo, params + self, + event_sourced_data_collection_info: DataCollectionInfo, + params: ThreeDGridScan | GridScanWithEdgeDetect, ) -> Sequence[ScanDataInfo]: - params = cast(GridscanInternalParameters, params) assert ( self.ispyb_ids.data_collection_ids ), "Expect at least one valid data collection to record scan data" xy_scan_data_info = ScanDataInfo( data_collection_info=event_sourced_data_collection_info, data_collection_position_info=populate_data_collection_position_info( - params.hyperion_params.ispyb_params + params.ispyb_params ), data_collection_id=self.ispyb_ids.data_collection_ids[0], ) @@ -199,7 +188,7 @@ def populate_info_for_update( xz_scan_data_info = ScanDataInfo( data_collection_info=event_sourced_data_collection_info, data_collection_position_info=populate_data_collection_position_info( - params.hyperion_params.ispyb_params + params.ispyb_params ), data_collection_id=data_collection_id, ) diff --git a/src/hyperion/external_interaction/callbacks/xray_centre/ispyb_mapping.py b/src/hyperion/external_interaction/callbacks/xray_centre/ispyb_mapping.py index 3a5c53bde..1c1521c85 100644 --- a/src/hyperion/external_interaction/callbacks/xray_centre/ispyb_mapping.py +++ b/src/hyperion/external_interaction/callbacks/xray_centre/ispyb_mapping.py @@ -1,6 +1,7 @@ from __future__ import annotations import numpy +from dodal.devices.detector import DetectorParams from dodal.devices.oav import utils as oav_utils from hyperion.external_interaction.ispyb.data_model import ( @@ -9,7 +10,7 @@ ) -def populate_xz_data_collection_info(detector_params) -> DataCollectionInfo: +def populate_xz_data_collection_info(detector_params: DetectorParams): assert ( detector_params.omega_start is not None and detector_params.run_number is not None @@ -25,14 +26,13 @@ def populate_xz_data_collection_info(detector_params) -> DataCollectionInfo: return info -def populate_xy_data_collection_info(detector_params): - info = DataCollectionInfo( +def populate_xy_data_collection_info(detector_params: DetectorParams): + return DataCollectionInfo( omega_start=detector_params.omega_start, data_collection_number=detector_params.run_number, axis_range=0, axis_end=detector_params.omega_start, ) - return info def construct_comment_for_gridscan(grid_info: DataCollectionGridInfo) -> str: diff --git a/src/hyperion/external_interaction/callbacks/xray_centre/nexus_callback.py b/src/hyperion/external_interaction/callbacks/xray_centre/nexus_callback.py index 3960d25b4..08f9f2c51 100644 --- a/src/hyperion/external_interaction/callbacks/xray_centre/nexus_callback.py +++ b/src/hyperion/external_interaction/callbacks/xray_centre/nexus_callback.py @@ -13,9 +13,7 @@ from hyperion.external_interaction.nexus.write_nexus import NexusWriter from hyperion.log import NEXUS_LOGGER from hyperion.parameters.constants import CONST -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanInternalParameters, -) +from hyperion.parameters.gridscan import ThreeDGridScan if TYPE_CHECKING: from event_model.documents import Event, EventDescriptor, RunStart @@ -48,18 +46,27 @@ def __init__(self) -> None: def activity_gated_start(self, doc: RunStart): if doc.get("subplan_name") == CONST.PLAN.GRIDSCAN_OUTER: - json_params = doc.get("hyperion_internal_parameters") + json_params = doc.get("hyperion_parameters") NEXUS_LOGGER.info( f"Nexus writer received start document with experiment parameters {json_params}" ) - parameters = GridscanInternalParameters.from_json(json_params) - nexus_data_1 = parameters.get_nexus_info(1) - nexus_data_2 = parameters.get_nexus_info(2) - self.nexus_writer_1 = NexusWriter(parameters, **nexus_data_1) + parameters = ThreeDGridScan.from_json(json_params) + d_size = parameters.detector_params.detector_size_constants.det_size_pixels + grid_n_img_1 = parameters.scan_indices[1] + grid_n_img_2 = parameters.num_images - grid_n_img_1 + data_shape_1 = (grid_n_img_1, d_size.width, d_size.height) + data_shape_2 = (grid_n_img_2, d_size.width, d_size.height) + run_number_2 = parameters.detector_params.run_number + 1 + self.nexus_writer_1 = NexusWriter( + parameters, data_shape_1, parameters.scan_points_first_grid + ) self.nexus_writer_2 = NexusWriter( parameters, - **nexus_data_2, - vds_start_index=nexus_data_1["data_shape"][0], + data_shape_2, + parameters.scan_points_second_grid, + run_number=run_number_2, + vds_start_index=parameters.scan_indices[1], + omega_start_deg=90, ) self.run_start_uid = doc.get("uid") diff --git a/src/hyperion/external_interaction/ispyb/data_model.py b/src/hyperion/external_interaction/ispyb/data_model.py index bcf04d081..e898d0860 100644 --- a/src/hyperion/external_interaction/ispyb/data_model.py +++ b/src/hyperion/external_interaction/ispyb/data_model.py @@ -8,7 +8,7 @@ class DataCollectionGroupInfo: visit_string: str experiment_type: str - sample_id: Optional[str] + sample_id: Optional[int] sample_barcode: Optional[str] = None @@ -27,7 +27,7 @@ class DataCollectionInfo: parent_id: Optional[int] = None visit_string: Optional[str] = None - sample_id: Optional[str] = None + sample_id: Optional[int] = None detector_id: Optional[int] = None axis_start: Optional[float] = None focal_spot_size_at_samplex: Optional[float] = None diff --git a/src/hyperion/external_interaction/ispyb/ispyb_dataclass.py b/src/hyperion/external_interaction/ispyb/ispyb_dataclass.py index 79062fa82..537dc400b 100644 --- a/src/hyperion/external_interaction/ispyb/ispyb_dataclass.py +++ b/src/hyperion/external_interaction/ispyb/ispyb_dataclass.py @@ -10,10 +10,6 @@ "position": [0, 0, 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"], - "beam_size_x": 0.1, - "beam_size_y": 0.1, - "focal_spot_size_x": 0.0, - "focal_spot_size_y": 0.0, "comment": "Descriptive comment.", } @@ -21,19 +17,12 @@ class IspybParams(BaseModel): visit_path: str position: np.ndarray - - beam_size_x: float - beam_size_y: float - focal_spot_size_x: float - focal_spot_size_y: float comment: str - - sample_id: Optional[str] = None + sample_id: Optional[int] = None # Optional from GDA as populated by Ophyd xtal_snapshots_omega_start: Optional[list[str]] = None xtal_snapshots_omega_end: Optional[list[str]] = None - ispyb_experiment_type: Optional[str] = None class Config: diff --git a/src/hyperion/external_interaction/ispyb/ispyb_store.py b/src/hyperion/external_interaction/ispyb/ispyb_store.py index d64b64136..6f90a8330 100755 --- a/src/hyperion/external_interaction/ispyb/ispyb_store.py +++ b/src/hyperion/external_interaction/ispyb/ispyb_store.py @@ -22,7 +22,6 @@ get_session_id_from_visit, ) from hyperion.log import ISPYB_LOGGER -from hyperion.parameters.components import IspybExperimentType from hyperion.tracing import TRACER if TYPE_CHECKING: @@ -39,14 +38,9 @@ class IspybIds(BaseModel): class StoreInIspyb(ABC): - def __init__(self, ispyb_config: str, experiment_type: IspybExperimentType) -> None: + def __init__(self, ispyb_config: str) -> None: self.ISPYB_CONFIG_PATH: str = ispyb_config self._data_collection_group_id: int | None - self._experiment_type = experiment_type - - @property - def experiment_type(self) -> str: - return self._experiment_type.value def begin_deposition( self, diff --git a/src/hyperion/external_interaction/nexus/write_nexus.py b/src/hyperion/external_interaction/nexus/write_nexus.py index 9247f67ed..ef97d17fe 100644 --- a/src/hyperion/external_interaction/nexus/write_nexus.py +++ b/src/hyperion/external_interaction/nexus/write_nexus.py @@ -13,68 +13,50 @@ from nexgen.nxs_utils import Attenuator, Beam, Detector, Goniometer, Source from nexgen.nxs_write.nxmx_writer import NXmxFileWriter from numpy.typing import DTypeLike +from scanspec.core import AxesPoints from hyperion.external_interaction.nexus.nexus_utils import ( create_detector_parameters, create_goniometer_axes, get_start_and_predicted_end_time, ) -from hyperion.parameters.internal_parameters import ( - HyperionParameters, - InternalParameters, -) +from hyperion.parameters.components import DiffractionExperimentWithSample class NexusWriter: def __init__( self, - parameters: InternalParameters, - scan_points: dict, + parameters: DiffractionExperimentWithSample, data_shape: tuple[int, int, int], - omega_start: float | None = None, + scan_points: AxesPoints, + *, run_number: int | None = None, + omega_start_deg: float = 0, + chi_start_deg: float = 0, vds_start_index: int = 0, ) -> None: self.beam: Optional[Beam] = None self.attenuator: Optional[Attenuator] = None self.scan_points: dict = scan_points self.data_shape: tuple[int, int, int] = data_shape - hyperion_parameters: HyperionParameters = ( - parameters.hyperion_params # type:ignore - ) - self.omega_start: float = ( - omega_start - if omega_start - else hyperion_parameters.detector_params.omega_start - ) - assert hyperion_parameters.detector_params.run_number is not None self.run_number: int = ( - run_number if run_number else hyperion_parameters.detector_params.run_number - ) - self.detector: Detector = create_detector_parameters( - hyperion_parameters.detector_params + run_number if run_number else parameters.detector_params.run_number ) + self.detector: Detector = create_detector_parameters(parameters.detector_params) self.source: Source = Source(get_beamline_name("S03")) - self.directory: Path = Path(hyperion_parameters.detector_params.directory) - self.filename: str = hyperion_parameters.detector_params.prefix + self.directory: Path = Path(parameters.storage_directory) + self.filename: str = parameters.file_name self.start_index: int = vds_start_index - self.full_num_of_images: int = ( - hyperion_parameters.detector_params.num_triggers - * hyperion_parameters.detector_params.num_images_per_trigger - ) - self.full_filename: str = hyperion_parameters.detector_params.full_filename + self.full_num_of_images: int = parameters.num_images + self.full_filename: str = parameters.detector_params.full_filename self.nexus_file: Path = ( self.directory / f"{self.filename}_{self.run_number}.nxs" ) self.master_file: Path = ( self.directory / f"{self.filename}_{self.run_number}_master.h5" ) - try: - chi = parameters.experiment_params.chi_start - except Exception: - chi = 0.0 self.goniometer: Goniometer = create_goniometer_axes( - self.omega_start, self.scan_points, chi=chi + omega_start_deg, self.scan_points, chi=chi_start_deg ) def create_nexus_file(self, bit_depth: DTypeLike): diff --git a/src/hyperion/parameters/components.py b/src/hyperion/parameters/components.py index efa731615..cf805655b 100644 --- a/src/hyperion/parameters/components.py +++ b/src/hyperion/parameters/components.py @@ -1,6 +1,7 @@ from __future__ import annotations import datetime +import json from abc import abstractmethod from enum import StrEnum from pathlib import Path @@ -127,6 +128,15 @@ def _validate_version(cls, version: ParameterVersion): ), f"Parameter version too new! This version of hyperion uses {PARAMETER_VERSION}" return version + @classmethod + def from_json(cls, input: str | None, *, allow_extras: bool = False): + assert input is not None + if allow_extras: + cls.Config.extra = Extra.ignore + params = cls(**json.loads(input)) + cls.Config.extra = Extra.forbid + return params + class DiffractionExperiment(HyperionParameters): """For all experiments which use beam""" @@ -148,7 +158,7 @@ class DiffractionExperiment(HyperionParameters): detector_distance_mm: float | None = Field(default=None, gt=0) demand_energy_ev: float | None = Field(default=None, gt=0) run_number: int | None = Field(default=None, ge=0) - ispyb_experiment_type: IspybExperimentType | None = None + ispyb_experiment_type: IspybExperimentType storage_directory: str @property @@ -201,6 +211,9 @@ class WithSample(BaseModel): sample_pin: int | None = None +class DiffractionExperimentWithSample(DiffractionExperiment, WithSample): ... + + class WithOavCentring(BaseModel): oav_centring_file: str = Field(default=CONST.I03.OAV_CENTRING_FILE) @@ -240,10 +253,6 @@ class Config: extra = Extra.forbid position: list[float] | NDArray = Field(default=np.array([0, 0, 0])) - beam_size_x: float - beam_size_y: float - focal_spot_size_x: float - focal_spot_size_y: float xtal_snapshots_omega_start: list[str] | None = None xtal_snapshots_omega_end: list[str] | None = None xtal_snapshots: list[str] | None = None diff --git a/src/hyperion/parameters/gridscan.py b/src/hyperion/parameters/gridscan.py index c7ee0f804..49006f11f 100644 --- a/src/hyperion/parameters/gridscan.py +++ b/src/hyperion/parameters/gridscan.py @@ -17,40 +17,20 @@ GridscanIspybParams, ) from hyperion.parameters.components import ( - DiffractionExperiment, + DiffractionExperimentWithSample, + IspybExperimentType, OptionalGonioAngleStarts, SplitScan, TemporaryIspybExtras, WithOavCentring, - WithSample, WithScan, XyzStarts, ) from hyperion.parameters.constants import CONST -from hyperion.parameters.plan_specific.grid_scan_with_edge_detect_params import ( - GridScanWithEdgeDetectInternalParameters, - GridScanWithEdgeDetectParams, -) -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanHyperionParameters, - GridscanInternalParameters, - OddYStepsException, -) -from hyperion.parameters.plan_specific.panda.panda_gridscan_internal_params import ( - PandAGridscanInternalParameters, -) -from hyperion.parameters.plan_specific.pin_centre_then_xray_centre_params import ( - PinCentreThenXrayCentreInternalParameters, - PinCentreThenXrayCentreParams, -) -from hyperion.parameters.plan_specific.robot_load_then_center_params import ( - RobotLoadThenCentreHyperionParameters, - RobotLoadThenCentreInternalParameters, -) class GridCommon( - DiffractionExperiment, OptionalGonioAngleStarts, WithSample, WithOavCentring + DiffractionExperimentWithSample, OptionalGonioAngleStarts, WithOavCentring ): grid_width_um: float = Field(default=CONST.PARAM.GRIDSCAN.WIDTH_UM) exposure_time_s: float = Field(default=CONST.PARAM.GRIDSCAN.EXPOSURE_TIME_S) @@ -62,6 +42,9 @@ class GridCommon( set_stub_offsets: bool = Field(default=False) use_panda: bool = Field(default=CONST.I03.USE_PANDA_FOR_GRIDSCAN) use_gpu: bool = Field(default=CONST.I03.USE_GPU_FOR_GRIDSCAN_ANALYSIS) + ispyb_experiment_type: IspybExperimentType = Field( + default=IspybExperimentType.GRIDSCAN_3D + ) # field rather than inherited to make it easier to track when it can be removed: ispyb_extras: TemporaryIspybExtras @@ -70,12 +53,8 @@ def ispyb_params(self): return GridscanIspybParams( visit_path=str(self.visit_directory), position=np.array(self.ispyb_extras.position), - beam_size_x=self.ispyb_extras.beam_size_x, - beam_size_y=self.ispyb_extras.beam_size_y, - focal_spot_size_x=self.ispyb_extras.focal_spot_size_x, - focal_spot_size_y=self.ispyb_extras.focal_spot_size_y, comment=self.comment, - sample_id=str(self.sample_id), + sample_id=self.sample_id, xtal_snapshots_omega_start=self.ispyb_extras.xtal_snapshots_omega_start or [], xtal_snapshots_omega_end=self.ispyb_extras.xtal_snapshots_omega_end or [], @@ -116,77 +95,21 @@ def detector_params(self): **optional_args, ) - # Can be removed in #1277 - def old_gridscan_hyperion_params(self, experiment_type): - return GridscanHyperionParameters( - zocalo_environment=self.zocalo_environment, - beamline=self.beamline, - insertion_prefix=self.insertion_prefix, - experiment_type=experiment_type, - detector_params=self.detector_params, - ispyb_params=self.ispyb_params, - ) - -class GridScanWithEdgeDetect(GridCommon, WithSample): - # Can be removed in #1277 - def old_parameters(self) -> GridScanWithEdgeDetectInternalParameters: - return GridScanWithEdgeDetectInternalParameters( - params_version="0.0.0", - hyperion_params=self.old_gridscan_hyperion_params( - "pin_centre_then_xray_centre" - ), - experiment_params=GridScanWithEdgeDetectParams( - transmission_fraction=self.transmission_frac, - exposure_time=self.exposure_time_s, - snapshot_dir=str(self.snapshot_directory), - detector_distance=self.detector_distance_mm, # type: ignore #TODO: deal with None - omega_start=self.omega_start_deg or CONST.PARAM.GRIDSCAN.OMEGA_1, - grid_width_microns=self.grid_width_um, - ), - ) +class GridScanWithEdgeDetect(GridCommon): ... class PinTipCentreThenXrayCentre(GridCommon): tip_offset_um: float = 0 - # Can be removed in #1277 - def old_parameters(self) -> PinCentreThenXrayCentreInternalParameters: - return PinCentreThenXrayCentreInternalParameters( - params_version=str(self.parameter_model_version), # type: ignore - hyperion_params=self.old_gridscan_hyperion_params( - "pin_centre_then_xray_centre" - ), - experiment_params=PinCentreThenXrayCentreParams( - transmission_fraction=self.transmission_frac, - tip_offset_microns=self.tip_offset_um, - exposure_time=self.exposure_time_s, - snapshot_dir=str(self.snapshot_directory), - detector_distance=self.detector_distance_mm, # type: ignore #TODO: deal with None - omega_start=self.omega_start_deg or CONST.PARAM.GRIDSCAN.OMEGA_1, - grid_width_microns=self.grid_width_um, - ), - ) - -class RobotLoadThenCentre(GridCommon, WithSample): +class RobotLoadThenCentre(GridCommon): def pin_centre_then_xray_centre_params(self): params = PinTipCentreThenXrayCentre(**self.dict()) return params - # Can be removed in #1277 - def old_parameters(self) -> RobotLoadThenCentreInternalParameters: - return RobotLoadThenCentreInternalParameters( - hyperion_params=self.old_gridscan_hyperion_params( - "robot_load_then_xray_centre" - ), - experiment_params=RobotLoadThenCentreHyperionParameters( - detector_distance=self.detector_distance_mm, # type: ignore #TODO: deal with None - ), - ) - -class SpecifiedGridScan(GridCommon, XyzStarts, WithScan, WithSample): +class SpecifiedGridScan(GridCommon, XyzStarts, WithScan): """A specified grid scan is one which has defined values for the start position, grid and box sizes, etc., as opposed to parameters for a plan which will create those parameters at some point (e.g. through optical pin detection).""" @@ -231,6 +154,10 @@ def FGS_params(self) -> GridScanParams: @property def panda_FGS_params(self) -> PandAGridScanParams: + if self.y_steps % 2 and self.z_steps > 0: + raise OddYStepsException( + "The number of Y steps must be even for a PandA gridscan" + ) return PandAGridScanParams( x_steps=self.x_steps, y_steps=self.y_steps, @@ -250,23 +177,21 @@ def panda_FGS_params(self) -> PandAGridScanParams: @property def grid_1_spec(self): - x_end = self.x_start_um + self.x_step_size_um * self.x_steps - y1_end = self.y_start_um + self.y_step_size_um * self.y_steps + x_end = self.x_start_um + self.x_step_size_um * (self.x_steps - 1) + y1_end = self.y_start_um + self.y_step_size_um * (self.y_steps - 1) grid_1_x = Line("sam_x", self.x_start_um, x_end, self.x_steps) grid_1_y = Line("sam_y", self.y_start_um, y1_end, self.y_steps) - grid_1_omega = Static("omega", self.grid1_omega_deg) grid_1_z = Static("sam_z", self.z_start_um) - return grid_1_x.zip(grid_1_z).zip(grid_1_omega) * ~grid_1_y + return grid_1_y.zip(grid_1_z) * ~grid_1_x @property def grid_2_spec(self): - x_end = self.x_start_um + self.x_step_size_um * self.x_steps - z2_end = self.z2_start_um + self.z_step_size_um * self.z_steps + x_end = self.x_start_um + self.x_step_size_um * (self.x_steps - 1) + z2_end = self.z2_start_um + self.z_step_size_um * (self.z_steps - 1) grid_2_x = Line("sam_x", self.x_start_um, x_end, self.x_steps) grid_2_z = Line("sam_z", self.z2_start_um, z2_end, self.z_steps) - grid_2_omega = Static("omega", self.grid2_omega_deg) grid_2_y = Static("sam_y", self.y2_start_um) - return grid_2_x.zip(grid_2_y).zip(grid_2_omega) * ~grid_2_z + return grid_2_z.zip(grid_2_y) * ~grid_2_x @property def scan_indices(self): @@ -287,33 +212,19 @@ def scan_points(self): """A list of all the points in the scan_spec.""" return ScanPath(self.scan_spec.calculate()).consume().midpoints + @property + def scan_points_first_grid(self): + """A list of all the points in the first grid scan.""" + return ScanPath(self.grid_1_spec.calculate()).consume().midpoints + + @property + def scan_points_second_grid(self): + """A list of all the points in the second grid scan.""" + return ScanPath(self.grid_2_spec.calculate()).consume().midpoints + @property def num_images(self) -> int: return len(self.scan_points["sam_x"]) - # Can be removed in #1277 - def old_parameters(self): - return GridscanInternalParameters( - params_version=str(self.parameter_model_version), # type: ignore - hyperion_params=self.old_gridscan_hyperion_params("flyscan_xray_centre"), - experiment_params=self.FGS_params, - ) - # Can be removed in #1277 - def panda_old_parameters(self): - if self.y_steps % 2 and self.z_steps > 0: - raise OddYStepsException( - "The number of Y steps must be even for a PandA gridscan" - ) - return PandAGridscanInternalParameters( - params_version=str(self.parameter_model_version), # type: ignore - hyperion_params=GridscanHyperionParameters( - zocalo_environment=self.zocalo_environment, - beamline=self.beamline, - insertion_prefix=self.insertion_prefix, - experiment_type="flyscan_xray_centre", - detector_params=self.detector_params, - ispyb_params=self.ispyb_params, - ), - experiment_params=self.panda_FGS_params, - ) +class OddYStepsException(Exception): ... diff --git a/src/hyperion/parameters/internal_parameters.py b/src/hyperion/parameters/internal_parameters.py deleted file mode 100644 index ba578061d..000000000 --- a/src/hyperion/parameters/internal_parameters.py +++ /dev/null @@ -1,175 +0,0 @@ -import json -from abc import abstractmethod -from typing import Any - -from dodal.devices.eiger import DetectorParams -from dodal.parameters.experiment_parameter_base import AbstractExperimentWithBeamParams -from pydantic import BaseModel, root_validator -from semver import Version - -from hyperion.external_interaction.ispyb.ispyb_dataclass import IspybParams - - -class ParameterVersion(Version): - @classmethod - def _parse(cls, version): - return cls.parse(version) - - @classmethod - def __get_validators__(cls): - """Return a list of validator methods for pydantic models.""" - yield cls._parse - - @classmethod - def __modify_schema__(cls, field_schema): - """Inject/mutate the pydantic field schema in-place.""" - field_schema.update(examples=["1.0.2", "2.15.3-alpha", "21.3.15-beta+12345"]) - - -class HyperionParameters(BaseModel): - zocalo_environment: str - beamline: str - insertion_prefix: str - experiment_type: str - detector_params: DetectorParams - ispyb_params: IspybParams - - class Config: - arbitrary_types_allowed = True - json_encoders = { - **DetectorParams.Config.json_encoders, - **IspybParams.Config.json_encoders, - } - - -def flatten_dict(d: dict, parent_items: dict = {}) -> dict: - """Flatten a dictionary assuming all keys are unique.""" - items: dict = {} - for k, v in d.items(): - if isinstance(v, dict): - flattened_subdict = flatten_dict(v, items) - items.update(flattened_subdict) - else: - if ( - k in items - or k in parent_items - and (items.get(k) or parent_items.get(k)) != v - ): - raise Exception( - f"Duplicate keys '{k}' in input parameters with differing values " - f"'{v}' and '{(items.get(k) or parent_items.get(k))}'!" - ) - items[k] = v - return items - - -def fetch_subdict_from_bucket( - list_of_keys: list[str], bucket: dict[str, Any] -) -> dict[str, Any]: - return {key: value for key, value in bucket.items() if key in list_of_keys} - - -def extract_experiment_params_from_flat_dict( - experiment_param_class, flat_params: dict[str, Any] -): - # Use __fields__ to get inherited attributes from BaseModels - experiment_field_keys = list(experiment_param_class.__fields__.keys()) - - experiment_params_args = fetch_subdict_from_bucket( - experiment_field_keys, flat_params - ) - return experiment_params_args - - -def get_extracted_experiment_and_flat_hyperion_params( - experiment_param_class, flat_params: dict[str, Any] -): - return { - "experiment_params": extract_experiment_params_from_flat_dict( - experiment_param_class, flat_params - ), - "hyperion_params": flat_params, - } - - -def extract_hyperion_params_from_flat_dict( - external_params: dict[str, Any], - hyperion_param_key_definitions: tuple[list[str], list[str], list[str]], -) -> dict[str, Any]: - all_params_bucket = flatten_dict(external_params) - - ( - hyperion_param_field_keys, - detector_field_keys, - ispyb_field_keys, - ) = hyperion_param_key_definitions - - hyperion_params_args: dict[str, Any] = fetch_subdict_from_bucket( - hyperion_param_field_keys, all_params_bucket - ) - detector_params_args: dict[str, Any] = fetch_subdict_from_bucket( - detector_field_keys, all_params_bucket - ) - ispyb_params_args: dict[str, Any] = fetch_subdict_from_bucket( - ispyb_field_keys, all_params_bucket - ) - hyperion_params_args["ispyb_params"] = ispyb_params_args - hyperion_params_args["detector_params"] = detector_params_args - - return hyperion_params_args - - -class InternalParameters(BaseModel): - params_version: ParameterVersion - - class Config: - use_enum_values = True - arbitrary_types_allowed = True - json_encoders = { - ParameterVersion: lambda pv: str(pv), - } - - @classmethod - def from_json(cls, data): - return cls(**(json.loads(data))) - - @root_validator(pre=True) - def _preprocess_all(cls, values): - values["hyperion_params"] = flatten_dict(values) - return values - - @staticmethod - def _hyperion_param_key_definitions(): - hyperion_param_field_keys = [ - "zocalo_environment", - "beamline", - "insertion_prefix", - "experiment_type", - ] - detector_field_keys = list(DetectorParams.__annotations__.keys()) - # not an annotation but specified as field encoder in DetectorParams: - detector_field_keys.append("detector") - ispyb_field_keys = list(IspybParams.__annotations__.keys()) - return hyperion_param_field_keys, detector_field_keys, ispyb_field_keys - - @abstractmethod - def _preprocess_experiment_params( - cls, - experiment_params: dict[str, Any], - ) -> AbstractExperimentWithBeamParams: ... - - @abstractmethod - def _preprocess_hyperion_params( - cls, all_params: dict[str, Any], values: dict[str, Any] - ) -> HyperionParameters: ... - - @abstractmethod - def get_scan_points(cls) -> dict[str, list]: - """Get points of the scan as calculated by scanspec.""" - ... - - @abstractmethod - def get_data_shape(cls) -> tuple[int, int, int]: - """Get the shape of the data resulting from the experiment specified by - these parameters.""" - ... diff --git a/src/hyperion/parameters/plan_specific/__init__.py b/src/hyperion/parameters/plan_specific/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/hyperion/parameters/plan_specific/grid_scan_with_edge_detect_params.py b/src/hyperion/parameters/plan_specific/grid_scan_with_edge_detect_params.py deleted file mode 100644 index 41f8a77b8..000000000 --- a/src/hyperion/parameters/plan_specific/grid_scan_with_edge_detect_params.py +++ /dev/null @@ -1,107 +0,0 @@ -from __future__ import annotations - -from typing import Any - -import numpy as np -from dodal.devices.detector import TriggerMode -from dodal.parameters.experiment_parameter_base import AbstractExperimentWithBeamParams -from pydantic import validator - -from hyperion.external_interaction.ispyb.ispyb_dataclass import GridscanIspybParams -from hyperion.parameters.constants import CONST -from hyperion.parameters.internal_parameters import ( - HyperionParameters, - InternalParameters, - extract_experiment_params_from_flat_dict, - extract_hyperion_params_from_flat_dict, -) -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanHyperionParameters, -) - - -class GridScanWithEdgeDetectParams(AbstractExperimentWithBeamParams): - """ - Holder class for the parameters of a grid scan that uses edge detection to detect the grid. - """ - - exposure_time: float - snapshot_dir: str - detector_distance: float - omega_start: float - - # This is the correct grid size for single pin - grid_width_microns: float = 600 - - # Whether to set the stub offsets after centering - set_stub_offsets: bool = False - - # Distance for the smargon to accelerate into the grid and decelerate out of the grid when using the panda - run_up_distance_mm: float = CONST.HARDWARE.PANDA_FGS_RUN_UP_DEFAULT - - use_panda: bool = False - - def get_num_images(self): - return 0 - - -class GridScanWithEdgeDetectInternalParameters(InternalParameters): - experiment_params: GridScanWithEdgeDetectParams - hyperion_params: GridscanHyperionParameters - - class Config: - arbitrary_types_allowed = True - json_encoders = { - **HyperionParameters.Config.json_encoders, - } - - def __init__(self, **args): - super().__init__(**args) - - @staticmethod - def _hyperion_param_key_definitions() -> tuple[list[str], list[str], list[str]]: - ( - hyperion_param_field_keys, - detector_field_keys, - ispyb_field_keys, - ) = InternalParameters._hyperion_param_key_definitions() - ispyb_field_keys += list(GridscanIspybParams.__annotations__.keys()) - return hyperion_param_field_keys, detector_field_keys, ispyb_field_keys - - @validator("experiment_params", pre=True) - def _preprocess_experiment_params( - cls, - experiment_params: dict[str, Any], - ): - if isinstance(experiment_params, GridScanWithEdgeDetectParams): - return experiment_params - return GridScanWithEdgeDetectParams( - **extract_experiment_params_from_flat_dict( - GridScanWithEdgeDetectParams, experiment_params - ) - ) - - @validator("hyperion_params", pre=True) - def _preprocess_hyperion_params( - cls, all_params: dict[str, Any], values: dict[str, Any] - ): - if isinstance(all_params["hyperion_params"], GridscanHyperionParameters): - return all_params["hyperion_params"] - experiment_params: GridScanWithEdgeDetectParams = values["experiment_params"] - all_params["num_images"] = experiment_params.get_num_images() - all_params["position"] = np.array(all_params["position"]) - all_params["omega_increment"] = 0 - all_params["num_triggers"] = all_params["num_images"] - all_params["num_images_per_trigger"] = 1 - all_params["trigger_mode"] = TriggerMode.FREE_RUN - return GridscanHyperionParameters( - **extract_hyperion_params_from_flat_dict( - all_params, cls._hyperion_param_key_definitions() - ) - ) - - def get_data_shape(self): - raise TypeError("Data shape does not apply to this type of experiment!") - - def get_scan_points(self): - raise TypeError("Scan points do not apply to this type of experiment!") diff --git a/src/hyperion/parameters/plan_specific/gridscan_internal_params.py b/src/hyperion/parameters/plan_specific/gridscan_internal_params.py deleted file mode 100644 index 22ffcff7f..000000000 --- a/src/hyperion/parameters/plan_specific/gridscan_internal_params.py +++ /dev/null @@ -1,144 +0,0 @@ -from __future__ import annotations - -from typing import Any - -import numpy as np -from dodal.devices.detector import DetectorParams, TriggerMode -from dodal.devices.fast_grid_scan import GridAxis, GridScanParams -from pydantic import validator -from scanspec.core import Path as ScanPath -from scanspec.specs import Line - -from hyperion.external_interaction.ispyb.ispyb_dataclass import ( - GRIDSCAN_ISPYB_PARAM_DEFAULTS, - GridscanIspybParams, -) -from hyperion.parameters.internal_parameters import ( - HyperionParameters, - InternalParameters, - extract_experiment_params_from_flat_dict, - extract_hyperion_params_from_flat_dict, -) -from hyperion.utils.utils import number_of_frames_from_scan_spec - - -class OddYStepsException(Exception): - pass - - -class GridscanHyperionParameters(HyperionParameters): - ispyb_params: GridscanIspybParams = GridscanIspybParams( - **GRIDSCAN_ISPYB_PARAM_DEFAULTS - ) - - class Config: - arbitrary_types_allowed = True - json_encoders = { - **DetectorParams.Config.json_encoders, - **GridscanIspybParams.Config.json_encoders, - } - - -class GridscanInternalParameters(InternalParameters): - experiment_params: GridScanParams - hyperion_params: GridscanHyperionParameters - - class Config: - arbitrary_types_allowed = True - json_encoders = { - **GridscanHyperionParameters.Config.json_encoders, - } - - @staticmethod - def _hyperion_param_key_definitions() -> tuple[list[str], list[str], list[str]]: - ( - hyperion_param_field_keys, - detector_field_keys, - ispyb_field_keys, - ) = InternalParameters._hyperion_param_key_definitions() - ispyb_field_keys += list(GridscanIspybParams.__annotations__.keys()) - return hyperion_param_field_keys, detector_field_keys, ispyb_field_keys - - @validator("experiment_params", pre=True) - def _preprocess_experiment_params( - cls, - experiment_params: dict[str, Any], - ): - if isinstance(experiment_params, GridScanParams): - return experiment_params - return GridScanParams( - **extract_experiment_params_from_flat_dict( - GridScanParams, experiment_params - ) - ) - - @validator("hyperion_params", pre=True) - def _preprocess_hyperion_params( - cls, all_params: dict[str, Any], values: dict[str, Any] - ): - if isinstance(all_params.get("hyperion_params"), GridscanHyperionParameters): - return all_params["hyperion_params"] - experiment_params: GridScanParams = values["experiment_params"] - all_params["num_images"] = experiment_params.get_num_images() - all_params["position"] = np.array(all_params["position"]) - all_params["omega_increment"] = 0 - all_params["num_triggers"] = all_params["num_images"] - all_params["num_images_per_trigger"] = 1 - all_params["trigger_mode"] = TriggerMode.FREE_RUN - hyperion_param_dict = extract_hyperion_params_from_flat_dict( - all_params, cls._hyperion_param_key_definitions() - ) - return GridscanHyperionParameters(**hyperion_param_dict) - - def get_scan_points(self, scan_number: int) -> dict: - """Get the scan points for the first or second gridscan: scan number must be - 1 or 2""" - - def create_line(name: str, axis: GridAxis): - return Line(name, axis.start, axis.end, axis.full_steps) - - if scan_number == 1: - x_line = create_line("sam_x", self.experiment_params.x_axis) - y_line = create_line("sam_y", self.experiment_params.y_axis) - spec = y_line * ~x_line - elif scan_number == 2: - x_line = create_line("sam_x", self.experiment_params.x_axis) - z_line = create_line("sam_z", self.experiment_params.z_axis) - spec = z_line * ~x_line - else: - raise Exception("Cannot provide scan points for other scans than 1 or 2") - - scan_path = ScanPath(spec.calculate()) - return scan_path.consume().midpoints - - def get_data_shape(self, scan_points: dict) -> tuple[int, int, int]: - size = ( - self.hyperion_params.detector_params.detector_size_constants.det_size_pixels - ) - return (number_of_frames_from_scan_spec(scan_points), size.width, size.height) - - def get_omega_start(self, scan_number: int) -> float: - assert ( - scan_number == 1 or scan_number == 2 - ), "Cannot provide parameters for other scans than 1 or 2" - detector_params = self.hyperion_params.detector_params - return detector_params.omega_start + 90 * (scan_number - 1) - - def get_run_number(self, scan_number: int) -> int: - assert ( - scan_number == 1 or scan_number == 2 - ), "Cannot provide parameters for other scans than 1 or 2" - detector_params = self.hyperion_params.detector_params - return detector_params.run_number + (scan_number - 1) - - def get_nexus_info(self, scan_number: int) -> dict: - """Returns a dict of info necessary for initialising NexusWriter, containing: - data_shape, scan_points, omega_start, filename - """ - scan_points = self.get_scan_points(scan_number) - return { - "data_shape": self.get_data_shape(scan_points), - "scan_points": scan_points, - "omega_start": self.get_omega_start(scan_number), - "run_number": self.get_run_number(scan_number), - } diff --git a/src/hyperion/parameters/plan_specific/panda/panda_gridscan_internal_params.py b/src/hyperion/parameters/plan_specific/panda/panda_gridscan_internal_params.py deleted file mode 100644 index b75eed7cc..000000000 --- a/src/hyperion/parameters/plan_specific/panda/panda_gridscan_internal_params.py +++ /dev/null @@ -1,135 +0,0 @@ -from __future__ import annotations - -from typing import Any - -import numpy as np -from dodal.devices.detector import TriggerMode -from dodal.devices.fast_grid_scan import GridAxis -from dodal.devices.panda_fast_grid_scan import PandAGridScanParams -from pydantic import validator -from scanspec.core import Path as ScanPath -from scanspec.specs import Line - -from hyperion.external_interaction.ispyb.ispyb_dataclass import ( - GridscanIspybParams, -) -from hyperion.parameters.internal_parameters import ( - InternalParameters, - extract_experiment_params_from_flat_dict, - extract_hyperion_params_from_flat_dict, -) -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanHyperionParameters, - OddYStepsException, -) -from hyperion.utils.utils import number_of_frames_from_scan_spec - - -class PandAGridscanInternalParameters(InternalParameters): - experiment_params: PandAGridScanParams - hyperion_params: GridscanHyperionParameters - - class Config: - arbitrary_types_allowed = True - json_encoders = { - **GridscanHyperionParameters.Config.json_encoders, - } - - @staticmethod - def _hyperion_param_key_definitions() -> tuple[list[str], list[str], list[str]]: - ( - hyperion_param_field_keys, - detector_field_keys, - ispyb_field_keys, - ) = InternalParameters._hyperion_param_key_definitions() - ispyb_field_keys += list(GridscanIspybParams.__annotations__.keys()) - return hyperion_param_field_keys, detector_field_keys, ispyb_field_keys - - @validator("experiment_params", pre=True) - def _preprocess_experiment_params( - cls, - experiment_params: dict[str, Any], - ): - if isinstance(experiment_params, PandAGridScanParams): - return experiment_params - # Panda not configured to run a half complete snake so enforce even rows on first grid - # See https://github.com/DiamondLightSource/hyperion/wiki/PandA-constant%E2%80%90motion-scanning#motion-program-summary - if experiment_params["y_steps"] % 2 and experiment_params["z_steps"] > 0: - raise OddYStepsException("The number of Y steps must be even") - - return PandAGridScanParams( - **extract_experiment_params_from_flat_dict( - PandAGridScanParams, experiment_params - ) - ) - - @validator("hyperion_params", pre=True) - def _preprocess_hyperion_params( - cls, all_params: dict[str, Any], values: dict[str, Any] - ): - if isinstance(all_params.get("hyperion_params"), GridscanHyperionParameters): - return all_params["hyperion_params"] - experiment_params: PandAGridScanParams = values["experiment_params"] - all_params["num_images"] = experiment_params.get_num_images() - all_params["position"] = np.array(all_params["position"]) - all_params["omega_increment"] = 0 - all_params["num_triggers"] = all_params["num_images"] - all_params["num_images_per_trigger"] = 1 - all_params["trigger_mode"] = TriggerMode.FREE_RUN - hyperion_param_dict = extract_hyperion_params_from_flat_dict( - all_params, cls._hyperion_param_key_definitions() - ) - return GridscanHyperionParameters(**hyperion_param_dict) - - def get_scan_points(self, scan_number: int) -> dict: - """Get the scan points for the first or second gridscan: scan number must be - 1 or 2""" - - def create_line(name: str, axis: GridAxis): - return Line(name, axis.start, axis.end, axis.full_steps) - - if scan_number == 1: - x_line = create_line("sam_x", self.experiment_params.x_axis) - y_line = create_line("sam_y", self.experiment_params.y_axis) - spec = y_line * ~x_line - elif scan_number == 2: - x_line = create_line("sam_x", self.experiment_params.x_axis) - z_line = create_line("sam_z", self.experiment_params.z_axis) - spec = z_line * ~x_line - else: - raise Exception("Cannot provide scan points for other scans than 1 or 2") - - scan_path = ScanPath(spec.calculate()) - return scan_path.consume().midpoints - - def get_data_shape(self, scan_points: dict) -> tuple[int, int, int]: - size = ( - self.hyperion_params.detector_params.detector_size_constants.det_size_pixels - ) - return (number_of_frames_from_scan_spec(scan_points), size.width, size.height) - - def get_omega_start(self, scan_number: int) -> float: - assert ( - scan_number == 1 or scan_number == 2 - ), "Cannot provide parameters for other scans than 1 or 2" - detector_params = self.hyperion_params.detector_params - return detector_params.omega_start + 90 * (scan_number - 1) - - def get_run_number(self, scan_number: int) -> int: - assert ( - scan_number == 1 or scan_number == 2 - ), "Cannot provide parameters for other scans than 1 or 2" - detector_params = self.hyperion_params.detector_params - return detector_params.run_number + (scan_number - 1) - - def get_nexus_info(self, scan_number: int) -> dict: - """Returns a dict of info necessary for initialising NexusWriter, containing: - data_shape, scan_points, omega_start, filename - """ - scan_points = self.get_scan_points(scan_number) - return { - "data_shape": self.get_data_shape(scan_points), - "scan_points": scan_points, - "omega_start": self.get_omega_start(scan_number), - "run_number": self.get_run_number(scan_number), - } diff --git a/src/hyperion/parameters/plan_specific/pin_centre_then_xray_centre_params.py b/src/hyperion/parameters/plan_specific/pin_centre_then_xray_centre_params.py deleted file mode 100644 index 9ac4b5f09..000000000 --- a/src/hyperion/parameters/plan_specific/pin_centre_then_xray_centre_params.py +++ /dev/null @@ -1,107 +0,0 @@ -from __future__ import annotations - -from typing import Any - -import numpy as np -from dodal.devices.detector import TriggerMode -from dodal.parameters.experiment_parameter_base import AbstractExperimentWithBeamParams -from pydantic import validator - -from hyperion.external_interaction.ispyb.ispyb_dataclass import GridscanIspybParams -from hyperion.parameters.constants import CONST -from hyperion.parameters.internal_parameters import ( - HyperionParameters, - InternalParameters, - extract_experiment_params_from_flat_dict, - extract_hyperion_params_from_flat_dict, -) -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanHyperionParameters, -) - - -class PinCentreThenXrayCentreParams(AbstractExperimentWithBeamParams): - """ - Holder class for the parameters of a plan that does a pin centre then xray centre - """ - - exposure_time: float - snapshot_dir: str - detector_distance: float - omega_start: float - - tip_offset_microns: float = 0 - oav_centring_file: str = CONST.I03.OAV_CENTRING_FILE - # Width for single pin - grid_width_microns: float = 600 - - # Whether to set the stub offsets after centering - set_stub_offsets: bool = False - - # Distance for the smargon to accelerate into the grid and decelerate out of the grid when using the panda - run_up_distance_mm: float = CONST.HARDWARE.PANDA_FGS_RUN_UP_DEFAULT - - # Use constant motion panda scans instead of fast grid scans - use_panda: bool = False - - def get_num_images(self): - return 0 - - -class PinCentreThenXrayCentreInternalParameters(InternalParameters): - experiment_params: PinCentreThenXrayCentreParams - hyperion_params: GridscanHyperionParameters - - class Config: - arbitrary_types_allowed = True - json_encoders = { - **HyperionParameters.Config.json_encoders, - } - - @staticmethod - def _hyperion_param_key_definitions() -> tuple[list[str], list[str], list[str]]: - ( - hyperion_param_field_keys, - detector_field_keys, - ispyb_field_keys, - ) = InternalParameters._hyperion_param_key_definitions() - ispyb_field_keys += list(GridscanIspybParams.__annotations__.keys()) - return hyperion_param_field_keys, detector_field_keys, ispyb_field_keys - - @validator("experiment_params", pre=True) - def _preprocess_experiment_params( - cls, - experiment_params: dict[str, Any], - ): - if isinstance(experiment_params, PinCentreThenXrayCentreParams): - return experiment_params - params_args = extract_experiment_params_from_flat_dict( - PinCentreThenXrayCentreParams, experiment_params - ) - params = PinCentreThenXrayCentreParams(**params_args) - return params - - @validator("hyperion_params", pre=True) - def _preprocess_hyperion_params( - cls, all_params: dict[str, Any], values: dict[str, Any] - ): - if isinstance(all_params.get("hyperion_params"), GridscanHyperionParameters): - return all_params["hyperion_params"] - experiment_params: PinCentreThenXrayCentreParams = values["experiment_params"] - all_params["num_images"] = experiment_params.get_num_images() - all_params["position"] = np.array(all_params["position"]) - all_params["omega_increment"] = 0 - all_params["num_triggers"] = all_params["num_images"] - all_params["num_images_per_trigger"] = 1 - all_params["trigger_mode"] = TriggerMode.FREE_RUN - return GridscanHyperionParameters( - **extract_hyperion_params_from_flat_dict( - all_params, cls._hyperion_param_key_definitions() - ) - ) - - def get_data_shape(self): - raise TypeError("Data shape does not apply to this type of experiment!") - - def get_scan_points(self): - raise TypeError("Scan points do not apply to this type of experiment!") diff --git a/src/hyperion/parameters/plan_specific/robot_load_then_center_params.py b/src/hyperion/parameters/plan_specific/robot_load_then_center_params.py deleted file mode 100644 index d1766c478..000000000 --- a/src/hyperion/parameters/plan_specific/robot_load_then_center_params.py +++ /dev/null @@ -1,116 +0,0 @@ -from __future__ import annotations - -from typing import Any, Optional - -import numpy as np -from dodal.devices.detector import DetectorParams, TriggerMode -from dodal.parameters.experiment_parameter_base import AbstractExperimentWithBeamParams -from pydantic import validator - -from hyperion.external_interaction.ispyb.ispyb_dataclass import ( - GRIDSCAN_ISPYB_PARAM_DEFAULTS, - RobotLoadIspybParams, -) -from hyperion.parameters.constants import CONST -from hyperion.parameters.internal_parameters import ( - HyperionParameters, - InternalParameters, - extract_experiment_params_from_flat_dict, - extract_hyperion_params_from_flat_dict, -) - - -class RobotLoadThenCentreHyperionParameters(HyperionParameters): - ispyb_params: RobotLoadIspybParams = RobotLoadIspybParams( # type: ignore - **GRIDSCAN_ISPYB_PARAM_DEFAULTS - ) - - class Config: - arbitrary_types_allowed = True - json_encoders = { - **DetectorParams.Config.json_encoders, - **RobotLoadIspybParams.Config.json_encoders, - } - - -class RobotLoadThenCentreParams(AbstractExperimentWithBeamParams): - """ - Holder class for the parameters of a plan that waits for robot load then does a - centre. - """ - - exposure_time: float - detector_distance: float - omega_start: float - snapshot_dir: str - - sample_puck: int - sample_pin: int - - requested_energy_kev: Optional[float] = None - - # Distance for the smargon to accelerate into the grid and decelerate out of the grid when using the panda - run_up_distance_mm: float = CONST.HARDWARE.PANDA_FGS_RUN_UP_DEFAULT - - # Use constant motion panda scans instead of fast grid scans - use_panda: bool = False - - def get_num_images(self): - return 0 - - -class RobotLoadThenCentreInternalParameters(InternalParameters): - experiment_params: RobotLoadThenCentreParams - hyperion_params: RobotLoadThenCentreHyperionParameters - - class Config: - arbitrary_types_allowed = True - json_encoders = { - **HyperionParameters.Config.json_encoders, - } - - @staticmethod - def _hyperion_param_key_definitions() -> tuple[list[str], list[str], list[str]]: - ( - hyperion_param_field_keys, - detector_field_keys, - ispyb_field_keys, - ) = InternalParameters._hyperion_param_key_definitions() - ispyb_field_keys += list(RobotLoadIspybParams.__annotations__.keys()) - return hyperion_param_field_keys, detector_field_keys, ispyb_field_keys - - @validator("experiment_params", pre=True) - def _preprocess_experiment_params( - cls, - experiment_params: dict[str, Any], - ): - return RobotLoadThenCentreParams( - **extract_experiment_params_from_flat_dict( - RobotLoadThenCentreParams, experiment_params - ) - ) - - @validator("hyperion_params", pre=True) - def _preprocess_hyperion_params( - cls, all_params: dict[str, Any], values: dict[str, Any] - ): - experiment_params: RobotLoadThenCentreParams = values["experiment_params"] - all_params["num_images"] = 0 - all_params["exposure_time"] = experiment_params.exposure_time - all_params["position"] = np.array(all_params["position"]) - all_params["omega_increment"] = 0 - all_params["num_triggers"] = all_params["num_images"] - all_params["num_images_per_trigger"] = 1 - all_params["trigger_mode"] = TriggerMode.FREE_RUN - all_params["expected_energy_ev"] = None - return RobotLoadThenCentreHyperionParameters( - **extract_hyperion_params_from_flat_dict( - all_params, cls._hyperion_param_key_definitions() - ) - ) - - def get_data_shape(self): - raise TypeError("Data shape does not apply to this type of experiment!") - - def get_scan_points(self): - raise TypeError("Scan points do not apply to this type of experiment!") diff --git a/src/hyperion/parameters/plan_specific/rotation_scan_internal_params.py b/src/hyperion/parameters/plan_specific/rotation_scan_internal_params.py deleted file mode 100644 index 900f4fb47..000000000 --- a/src/hyperion/parameters/plan_specific/rotation_scan_internal_params.py +++ /dev/null @@ -1,162 +0,0 @@ -from __future__ import annotations - -from typing import Any - -import numpy as np -from dodal.devices.detector import DetectorParams -from dodal.devices.motors import XYZLimitBundle -from dodal.devices.zebra import RotationDirection -from dodal.parameters.experiment_parameter_base import AbstractExperimentWithBeamParams -from pydantic import validator -from scanspec.core import Path as ScanPath -from scanspec.specs import Line - -from hyperion.external_interaction.ispyb.ispyb_dataclass import ( - GRIDSCAN_ISPYB_PARAM_DEFAULTS, - RotationIspybParams, -) -from hyperion.parameters.internal_parameters import ( - HyperionParameters, - InternalParameters, - extract_experiment_params_from_flat_dict, - extract_hyperion_params_from_flat_dict, -) - - -class RotationHyperionParameters(HyperionParameters): - ispyb_params: RotationIspybParams = RotationIspybParams( - **GRIDSCAN_ISPYB_PARAM_DEFAULTS - ) - - class Config: - arbitrary_types_allowed = True - json_encoders = { - **DetectorParams.Config.json_encoders, - **RotationIspybParams.Config.json_encoders, - } - - -class RotationScanParams(AbstractExperimentWithBeamParams): - """ - Holder class for the parameters of a rotation data collection. - """ - - rotation_axis: str = "omega" - rotation_angle: float = 360.0 - image_width: float = 0.1 - omega_start: float = 0.0 - phi_start: float | None = None - chi_start: float | None = None - kappa_start: float | None = None - x: float | None = None - y: float | None = None - z: float | None = None - rotation_direction: RotationDirection = RotationDirection.NEGATIVE - shutter_opening_time_s: float = 0.6 - - @validator("rotation_direction", pre=True) - def _parse_validator(cls, rotation_direction: str): - return RotationDirection(rotation_direction) - - @validator("rotation_direction", pre=True) - def _parse_direction(cls, rotation_direction: str): - return RotationDirection(rotation_direction) - - def xyz_are_valid(self, limits: XYZLimitBundle) -> bool: - """ - Validates scan location in x, y, and z - - :param limits: The motor limits against which to validate - the parameters - :return: True if the scan is valid - """ - assert ( - self.x is not None and self.y is not None and self.z is not None - ), "Validity is only defined for positions which are not None" - return ( - limits.x.is_within(self.x) - and limits.y.is_within(self.y) - and limits.z.is_within(self.z) - ) - - def get_num_images(self) -> int: - return int(self.rotation_angle / self.image_width) - - -class RotationInternalParameters(InternalParameters): - experiment_params: RotationScanParams - hyperion_params: RotationHyperionParameters - - class Config: - arbitrary_types_allowed = True - json_encoders = { - **RotationHyperionParameters.Config.json_encoders, - } - - @staticmethod - def _hyperion_param_key_definitions() -> tuple[list[str], list[str], list[str]]: - ( - hyperion_param_field_keys, - detector_field_keys, - ispyb_field_keys, - ) = InternalParameters._hyperion_param_key_definitions() - ispyb_field_keys += list(RotationIspybParams.__annotations__.keys()) - - return hyperion_param_field_keys, detector_field_keys, ispyb_field_keys - - @validator("experiment_params", pre=True) - def _preprocess_experiment_params( - cls, - experiment_params: dict[str, Any], - ): - if isinstance(experiment_params, RotationScanParams): - return experiment_params - return RotationScanParams( - **extract_experiment_params_from_flat_dict( - RotationScanParams, experiment_params - ) - ) - - @validator("hyperion_params", pre=True) - def _preprocess_hyperion_params( - cls, all_params: dict[str, Any], values: dict[str, Any] - ): - if isinstance(all_params.get("hyperion_params"), RotationHyperionParameters): - return all_params["hyperion_params"] - experiment_params: RotationScanParams = values["experiment_params"] - all_params["num_images"] = experiment_params.get_num_images() - all_params["position"] = np.array(all_params["position"]) - if ( - all_params["rotation_axis"] == "omega" - and all_params.get("rotation_increment") is not None - ): - all_params["omega_increment"] = all_params["rotation_increment"] - else: - all_params["omega_increment"] = 0 - all_params["num_triggers"] = 1 - all_params["num_images_per_trigger"] = all_params["num_images"] - return RotationHyperionParameters( - **extract_hyperion_params_from_flat_dict( - all_params, cls._hyperion_param_key_definitions() - ) - ) - - def get_scan_points(self): - scan_spec = Line( - axis="omega", - start=self.experiment_params.omega_start, - stop=( - self.experiment_params.rotation_angle - + self.experiment_params.omega_start - - self.experiment_params.image_width - ), - num=self.experiment_params.get_num_images(), - ) - scan_path = ScanPath(scan_spec.calculate()) - return scan_path.consume().midpoints - - def get_data_shape(self) -> tuple[int, int, int]: - size = ( - self.hyperion_params.detector_params.detector_size_constants.det_size_pixels - ) - return (self.experiment_params.get_num_images(), size.width, size.height) diff --git a/src/hyperion/parameters/rotation.py b/src/hyperion/parameters/rotation.py index 9671b8aa9..fd20aa265 100644 --- a/src/hyperion/parameters/rotation.py +++ b/src/hyperion/parameters/rotation.py @@ -17,29 +17,22 @@ from hyperion.external_interaction.ispyb.ispyb_dataclass import RotationIspybParams from hyperion.parameters.components import ( - DiffractionExperiment, + DiffractionExperimentWithSample, IspybExperimentType, OptionalGonioAngleStarts, OptionalXyzStarts, RotationAxis, TemporaryIspybExtras, - WithSample, WithScan, ) from hyperion.parameters.constants import CONST -from hyperion.parameters.plan_specific.rotation_scan_internal_params import ( - RotationHyperionParameters, - RotationInternalParameters, - RotationScanParams, -) class RotationScan( - DiffractionExperiment, + DiffractionExperimentWithSample, WithScan, OptionalGonioAngleStarts, OptionalXyzStarts, - WithSample, ): omega_start_deg: float = Field(default=0) # type: ignore rotation_axis: RotationAxis = Field(default=RotationAxis.OMEGA) @@ -87,12 +80,7 @@ def ispyb_params(self): # pyright: ignore return RotationIspybParams( visit_path=str(self.visit_directory), position=np.array(self.ispyb_extras.position), - beam_size_x=self.ispyb_extras.beam_size_x, - beam_size_y=self.ispyb_extras.beam_size_y, - focal_spot_size_x=self.ispyb_extras.focal_spot_size_x, - focal_spot_size_y=self.ispyb_extras.focal_spot_size_y, comment=self.comment, - sample_id=str(self.sample_id), xtal_snapshots_omega_start=self.ispyb_extras.xtal_snapshots_omega_start, xtal_snapshots_omega_end=self.ispyb_extras.xtal_snapshots_omega_end, ispyb_experiment_type=self.ispyb_experiment_type, @@ -114,32 +102,3 @@ def scan_points(self) -> AxesPoints: @property def num_images(self) -> int: return int(self.scan_width_deg / self.rotation_increment_deg) - - # Can be removed in #1277 - def old_parameters(self) -> RotationInternalParameters: - return RotationInternalParameters( - params_version=str(self.parameter_model_version), # type: ignore - experiment_params=RotationScanParams( - rotation_axis=self.rotation_axis, - rotation_angle=self.scan_width_deg, - image_width=self.rotation_increment_deg, - omega_start=self.omega_start_deg, - phi_start=self.phi_start_deg, - chi_start=self.chi_start_deg, - kappa_start=self.kappa_start_deg, - x=self.x_start_um, - y=self.y_start_um, - z=self.z_start_um, - rotation_direction=self.rotation_direction, - shutter_opening_time_s=self.shutter_opening_time_s, - transmission_fraction=self.transmission_frac, - ), - hyperion_params=RotationHyperionParameters( - zocalo_environment=self.zocalo_environment, - beamline=self.beamline, - insertion_prefix=self.insertion_prefix, - experiment_type="SAD", - detector_params=self.detector_params, - ispyb_params=self.ispyb_params, - ), - ) diff --git a/tests/conftest.py b/tests/conftest.py index 659a2dc19..34e54c9a8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -6,7 +6,7 @@ import threading from functools import partial from typing import Any, Callable, Generator, Optional, Sequence -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import MagicMock, patch import bluesky.plan_stubs as bps import pytest @@ -43,7 +43,7 @@ from ophyd.epics_motor import EpicsMotor from ophyd.sim import NullStatus from ophyd.status import DeviceStatus, Status -from ophyd_async.core import set_mock_value +from ophyd_async.core import callback_on_mock_put, set_mock_value from ophyd_async.core.async_status import AsyncStatus from ophyd_async.epics.motion.motor import Motor from scanspec.core import Path as ScanPath @@ -77,7 +77,7 @@ def raw_params_from_file(filename): def default_raw_params(): return raw_params_from_file( - "tests/test_data/new_parameter_json_files/test_gridscan_param_defaults.json" + "tests/test_data/parameter_json_files/test_gridscan_param_defaults.json" ) @@ -182,20 +182,23 @@ async def mock_good_coroutine(): return asyncio.sleep(0) -def mock_async_motor_move(motor: Motor, val, *args, **kwargs): - set_mock_value(motor.user_setpoint, val) - set_mock_value(motor.user_readback, val) - return mock_good_coroutine() # type: ignore +def pass_on_mock(motor, call_log: MagicMock | None = None): + def _pass_on_mock(value, **kwargs): + set_mock_value(motor.user_readback, value) + if call_log is not None: + call_log(value, **kwargs) + return _pass_on_mock -def patch_async_motor(motor: Motor, initial_position=0): + +def patch_async_motor( + motor: Motor, initial_position=0, call_log: MagicMock | None = None +): set_mock_value(motor.user_setpoint, initial_position) set_mock_value(motor.user_readback, initial_position) set_mock_value(motor.deadband, 0.001) set_mock_value(motor.motor_done_move, 1) - return patch.object( - motor, "_move", AsyncMock(side_effect=partial(mock_async_motor_move, motor)) - ) + return callback_on_mock_put(motor.user_setpoint, pass_on_mock(motor, call_log)) @pytest.fixture @@ -209,7 +212,7 @@ def beamline_parameters(): def test_fgs_params(): return ThreeDGridScan( **raw_params_from_file( - "tests/test_data/new_parameter_json_files/good_test_parameters.json" + "tests/test_data/parameter_json_files/good_test_parameters.json" ) ) @@ -224,7 +227,7 @@ def test_panda_fgs_params(test_fgs_params: ThreeDGridScan): def test_rotation_params(): return RotationScan( **raw_params_from_file( - "tests/test_data/new_parameter_json_files/good_test_rotation_scan_parameters.json" + "tests/test_data/parameter_json_files/good_test_rotation_scan_parameters.json" ) ) @@ -233,7 +236,7 @@ def test_rotation_params(): def test_rotation_params_nomove(): return RotationScan( **raw_params_from_file( - "tests/test_data/new_parameter_json_files/good_test_rotation_scan_parameters_nomove.json" + "tests/test_data/parameter_json_files/good_test_rotation_scan_parameters_nomove.json" ) ) @@ -438,7 +441,7 @@ def webcam(RE) -> Generator[Webcam, Any, Any]: @pytest.fixture -def aperture_scatterguard(done_status, RE): +def aperture_scatterguard(RE): AperturePositions.LARGE = SingleAperturePosition( location=ApertureFiveDimensionalLocation(0, 1, 2, 3, 4), name="Large", @@ -480,7 +483,8 @@ def aperture_scatterguard(done_status, RE): patch_async_motor(ap_sg.scatterguard.x), patch_async_motor(ap_sg.scatterguard.y), ): - RE(bps.abs_set(ap_sg, ap_sg.aperture_positions.SMALL)) # type: ignore + RE(bps.abs_set(ap_sg, ap_sg.aperture_positions.SMALL)) # type: + set_mock_value(ap_sg.aperture.small, 1) yield ap_sg @@ -496,7 +500,7 @@ def test_config_files(): @pytest.fixture def test_full_grid_scan_params(): params = raw_params_from_file( - "tests/test_data/new_parameter_json_files/good_test_grid_with_edge_detect_parameters.json" + "tests/test_data/parameter_json_files/good_test_grid_with_edge_detect_parameters.json" ) return GridScanWithEdgeDetect(**params) diff --git a/tests/system_tests/experiment_plans/test_fgs_plan.py b/tests/system_tests/experiment_plans/test_fgs_plan.py index bdd33024b..291d8b6ba 100644 --- a/tests/system_tests/experiment_plans/test_fgs_plan.py +++ b/tests/system_tests/experiment_plans/test_fgs_plan.py @@ -39,9 +39,7 @@ ) from hyperion.external_interaction.ispyb.ispyb_store import IspybIds from hyperion.parameters.constants import CONST -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanInternalParameters, -) +from hyperion.parameters.gridscan import ThreeDGridScan from ...conftest import default_raw_params from ..external_interaction.conftest import ( # noqa @@ -52,9 +50,9 @@ @pytest.fixture def params(): - params = GridscanInternalParameters(**default_raw_params()) - params.hyperion_params.beamline = CONST.SIM.BEAMLINE - params.hyperion_params.zocalo_environment = "dev_artemis" + params = ThreeDGridScan(**default_raw_params()) + params.beamline = CONST.SIM.BEAMLINE + params.zocalo_environment = "dev_artemis" yield params @@ -112,16 +110,14 @@ async def fxc_composite(): gda_beamline_parameters ) composite.aperture_scatterguard.load_aperture_positions(aperture_positions) - composite.aperture_scatterguard._set_raw_unsafe( + await composite.aperture_scatterguard._set_raw_unsafe( aperture_positions.LARGE.location - ).wait() + ) composite.eiger.cam.manual_trigger.put("Yes") composite.eiger.odin.check_odin_initialised = lambda: (True, "") composite.eiger.stage = MagicMock(return_value=Status(done=True, success=True)) composite.eiger.unstage = MagicMock(return_value=Status(done=True, success=True)) - composite.aperture_scatterguard.scatterguard.x.set_lim(-4.8, 5.7) - composite.xbpm_feedback.pos_ok.sim_put(1) # type: ignore composite.xbpm_feedback.pos_stable.sim_put(1) # type: ignore @@ -180,7 +176,7 @@ def read_run(u, s, g, r, a, f, dcm, ap_sg): def test_xbpm_feedback_decorator( RE: RunEngine, fxc_composite: FlyScanXRayCentreComposite, - params: GridscanInternalParameters, + params: ThreeDGridScan, callbacks: Tuple[GridscanNexusFileCallback, GridscanISPyBCallback], ): # This test is currently kind of more a unit test since we are faking XBPM feedback @@ -190,7 +186,7 @@ def test_xbpm_feedback_decorator( @transmission_and_xbpm_feedback_for_collection_decorator( fxc_composite.xbpm_feedback, fxc_composite.attenuator, - params.experiment_params.transmission_fraction, + params.transmission_frac, ) def decorated_plan(): yield from bps.sleep(0.1) @@ -219,7 +215,7 @@ def test_full_plan_tidies_at_end( kickoff: MagicMock, wait: MagicMock, fxc_composite: FlyScanXRayCentreComposite, - params: GridscanInternalParameters, + params: ThreeDGridScan, RE: RunEngine, callbacks: Tuple[GridscanNexusFileCallback, GridscanISPyBCallback], ): @@ -255,7 +251,7 @@ def test_full_plan_tidies_at_end_when_plan_fails( kickoff: MagicMock, wait: MagicMock, fxc_composite: FlyScanXRayCentreComposite, - params: GridscanInternalParameters, + params: ThreeDGridScan, RE: RunEngine, ): run_gridscan_and_move.side_effect = Exception() @@ -272,16 +268,15 @@ def test_GIVEN_scan_invalid_WHEN_plan_run_THEN_ispyb_entry_made_but_no_zocalo_en RE: RunEngine, fxc_composite: FlyScanXRayCentreComposite, fetch_comment: Callable, - params: GridscanInternalParameters, + params: ThreeDGridScan, callbacks: Tuple[GridscanNexusFileCallback, GridscanISPyBCallback], ): _, ispyb_cb = callbacks - params.hyperion_params.detector_params.directory = "./tmp" - params.hyperion_params.detector_params.prefix = str(uuid.uuid1()) - params.hyperion_params.ispyb_params.visit_path = "/dls/i03/data/2022/cm31105-5/" + params.storage_directory = "./tmp" + params.file_name = str(uuid.uuid1()) # Currently s03 calls anything with z_steps > 1 invalid - params.experiment_params.z_steps = 100 + params.z_steps = 100 RE(reset_positions(fxc_composite.smargon)) [RE.subscribe(cb) for cb in callbacks] @@ -304,21 +299,20 @@ def test_complete_xray_centre_plan_with_no_callbacks_falls_back_to_centre( RE: RunEngine, fxc_composite: FlyScanXRayCentreComposite, zocalo_env: None, - params: GridscanInternalParameters, + params: ThreeDGridScan, callbacks, done_status, ): fxc_composite.fast_grid_scan.kickoff = MagicMock(return_value=done_status) fxc_composite.fast_grid_scan.complete = MagicMock(return_value=done_status) - params.hyperion_params.detector_params.directory = "./tmp" - params.hyperion_params.detector_params.prefix = str(uuid.uuid1()) - params.hyperion_params.ispyb_params.visit_path = "/dls/i03/data/2022/cm31105-5/" + params.storage_directory = "./tmp" + params.file_name = str(uuid.uuid1()) - params.experiment_params.set_stub_offsets = False + params.set_stub_offsets = False # Currently s03 calls anything with z_steps > 1 invalid - params.experiment_params.z_steps = 1 + params.z_steps = 1 RE(reset_positions(fxc_composite.smargon)) @@ -342,21 +336,20 @@ def test_complete_xray_centre_plan_with_callbacks_moves_to_centre( RE: RunEngine, fxc_composite: FlyScanXRayCentreComposite, zocalo_env: None, - params: GridscanInternalParameters, + params: ThreeDGridScan, callbacks, done_status, ): fxc_composite.fast_grid_scan.kickoff = MagicMock(return_value=done_status) fxc_composite.fast_grid_scan.complete = MagicMock(return_value=done_status) - params.hyperion_params.detector_params.directory = "./tmp" - params.hyperion_params.detector_params.prefix = str(uuid.uuid1()) - params.hyperion_params.ispyb_params.visit_path = "/dls/i03/data/2022/cm31105-5/" + params.storage_directory = "./tmp" + params.file_name = str(uuid.uuid1()) - params.experiment_params.set_stub_offsets = False + params.set_stub_offsets = False # Currently s03 calls anything with z_steps > 1 invalid - params.experiment_params.z_steps = 1 + params.z_steps = 1 RE(reset_positions(fxc_composite.smargon)) diff --git a/tests/system_tests/external_interaction/callbacks/test_external_callbacks.py b/tests/system_tests/external_interaction/callbacks/test_external_callbacks.py index 712785ec1..ee95c5a43 100644 --- a/tests/system_tests/external_interaction/callbacks/test_external_callbacks.py +++ b/tests/system_tests/external_interaction/callbacks/test_external_callbacks.py @@ -30,12 +30,8 @@ ) from hyperion.log import LOGGER from hyperion.parameters.constants import CONST -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanInternalParameters, -) -from hyperion.parameters.plan_specific.rotation_scan_internal_params import ( - RotationInternalParameters, -) +from hyperion.parameters.gridscan import ThreeDGridScan +from hyperion.parameters.rotation import RotationScan from hyperion.utils.utils import convert_angstrom_to_eV from ....conftest import fake_read @@ -144,7 +140,7 @@ def plan(): async def test_external_callbacks_handle_gridscan_ispyb_and_zocalo( RE_with_external_callbacks: RunEngine, zocalo_env, - test_fgs_params: GridscanInternalParameters, + test_fgs_params: ThreeDGridScan, fake_fgs_composite: FlyScanXRayCentreComposite, done_status, zocalo_device: ZocaloResults, @@ -155,7 +151,7 @@ async def test_external_callbacks_handle_gridscan_ispyb_and_zocalo( locally at DLS.""" RE = RE_with_external_callbacks - test_fgs_params.hyperion_params.zocalo_environment = "dev_artemis" + test_fgs_params.zocalo_environment = "dev_artemis" fake_fgs_composite.aperture_scatterguard.aperture.z.user_setpoint.sim_put( # type: ignore 2 @@ -197,7 +193,7 @@ async def test_external_callbacks_handle_gridscan_ispyb_and_zocalo( @pytest.mark.s03() def test_remote_callbacks_write_to_dev_ispyb_for_rotation( RE_with_external_callbacks: RunEngine, - test_rotation_params: RotationInternalParameters, + test_rotation_params: RotationScan, fetch_comment, fetch_datacollection_attribute, undulator, @@ -206,6 +202,7 @@ def test_remote_callbacks_write_to_dev_ispyb_for_rotation( s4_slit_gaps, flux, robot, + aperture_scatterguard, fake_create_devices, ): test_wl = 0.71 @@ -214,15 +211,12 @@ def test_remote_callbacks_write_to_dev_ispyb_for_rotation( test_exp_time = 0.023 test_img_wid = 0.27 - test_rotation_params.experiment_params.image_width = test_img_wid - test_rotation_params.hyperion_params.ispyb_params.beam_size_x = test_bs_x - test_rotation_params.hyperion_params.ispyb_params.beam_size_y = test_bs_y - test_rotation_params.hyperion_params.detector_params.exposure_time = test_exp_time - test_rotation_params.hyperion_params.detector_params.expected_energy_ev = ( - convert_angstrom_to_eV(test_wl) - ) + test_rotation_params.rotation_increment_deg = test_img_wid + test_rotation_params.exposure_time_s = test_exp_time + test_rotation_params.demand_energy_ev = convert_angstrom_to_eV(test_wl) composite = RotationScanComposite( + aperture_scatterguard=aperture_scatterguard, attenuator=attenuator, backlight=fake_create_devices["backlight"], dcm=fake_create_devices["dcm"], diff --git a/tests/system_tests/external_interaction/conftest.py b/tests/system_tests/external_interaction/conftest.py index 0a2a64911..c5935fe68 100644 --- a/tests/system_tests/external_interaction/conftest.py +++ b/tests/system_tests/external_interaction/conftest.py @@ -2,7 +2,6 @@ from functools import partial from typing import Any, Callable -import dodal.devices.zocalo.zocalo_interaction import ispyb.sqlalchemy import pytest from ispyb.sqlalchemy import DataCollection, DataCollectionGroup, GridInfo, Position @@ -10,11 +9,8 @@ from sqlalchemy.orm import sessionmaker from hyperion.external_interaction.ispyb.ispyb_store import StoreInIspyb -from hyperion.parameters.components import IspybExperimentType from hyperion.parameters.constants import CONST -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanInternalParameters, -) +from hyperion.parameters.gridscan import ThreeDGridScan from ...conftest import raw_params_from_file @@ -146,32 +142,25 @@ def fetch_datacollectiongroup_attribute(sqlalchemy_sessionmaker) -> Callable: @pytest.fixture def dummy_params(): - dummy_params = GridscanInternalParameters( + dummy_params = ThreeDGridScan( **raw_params_from_file( - "tests/test_data/parameter_json_files/system_test_parameter_defaults.json" + "tests/test_data/parameter_json_files/test_gridscan_param_defaults.json" ) ) - dummy_params.hyperion_params.ispyb_params.visit_path = ( - "/dls/i03/data/2022/cm31105-5/" - ) + dummy_params.visit = "cm31105-5" return dummy_params @pytest.fixture def dummy_ispyb(dummy_params) -> StoreInIspyb: - return StoreInIspyb( - CONST.SIM.DEV_ISPYB_DATABASE_CFG, IspybExperimentType.GRIDSCAN_2D - ) + return StoreInIspyb(CONST.SIM.DEV_ISPYB_DATABASE_CFG) @pytest.fixture def dummy_ispyb_3d(dummy_params) -> StoreInIspyb: - return StoreInIspyb( - CONST.SIM.DEV_ISPYB_DATABASE_CFG, IspybExperimentType.GRIDSCAN_3D - ) + return StoreInIspyb(CONST.SIM.DEV_ISPYB_DATABASE_CFG) @pytest.fixture def zocalo_env(): os.environ["ZOCALO_CONFIG"] = "/dls_sw/apps/zocalo/live/configuration.yaml" - dodal.devices.zocalo.zocalo_interaction.DEFAULT_TIMEOUT = 5 diff --git a/tests/system_tests/external_interaction/test_ispyb_dev_connection.py b/tests/system_tests/external_interaction/test_ispyb_dev_connection.py index b2c128525..5e3bbf59a 100644 --- a/tests/system_tests/external_interaction/test_ispyb_dev_connection.py +++ b/tests/system_tests/external_interaction/test_ispyb_dev_connection.py @@ -54,7 +54,7 @@ ) from hyperion.parameters.components import IspybExperimentType from hyperion.parameters.constants import CONST -from hyperion.parameters.gridscan import GridScanWithEdgeDetect +from hyperion.parameters.gridscan import GridScanWithEdgeDetect, ThreeDGridScan from hyperion.parameters.rotation import RotationScan from hyperion.utils.utils import convert_angstrom_to_eV @@ -203,24 +203,16 @@ @pytest.fixture def dummy_data_collection_group_info(dummy_params): return populate_data_collection_group( - IspybExperimentType.GRIDSCAN_2D.value, - dummy_params.hyperion_params.detector_params, - dummy_params.hyperion_params.ispyb_params, + dummy_params, ) @pytest.fixture def dummy_scan_data_info_for_begin(dummy_params): info = populate_xy_data_collection_info( - dummy_params.hyperion_params.detector_params, - ) - info = populate_remaining_data_collection_info( - None, - None, - info, - dummy_params.hyperion_params.detector_params, - dummy_params.hyperion_params.ispyb_params, + dummy_params.detector_params, ) + info = populate_remaining_data_collection_info(None, None, info, dummy_params) return ScanDataInfo( data_collection_info=info, ) @@ -229,7 +221,7 @@ def dummy_scan_data_info_for_begin(dummy_params): @pytest.fixture def grid_detect_then_xray_centre_parameters(): json_dict = raw_params_from_file( - "tests/test_data/new_parameter_json_files/ispyb_gridscan_system_test_parameters.json" + "tests/test_data/parameter_json_files/ispyb_gridscan_system_test_parameters.json" ) return GridScanWithEdgeDetect(**json_dict) @@ -329,10 +321,8 @@ def mock_pin_tip_detect(_): ophyd_pin_tip_detection.triggered_bottom_edge, numpy.array(bottom_edge_data, dtype=numpy.uint32), ) - ( - set_mock_value( - zocalo.bbox_sizes, numpy.array([[10, 10, 10]], dtype=numpy.uint64) - ), + set_mock_value( + zocalo.bbox_sizes, numpy.array([[10, 10, 10]], dtype=numpy.uint64) ) yield from [] @@ -384,16 +374,16 @@ def mock_complete_status(): def scan_xy_data_info_for_update( - data_collection_group_id, dummy_params, scan_data_info_for_begin + data_collection_group_id, dummy_params: ThreeDGridScan, scan_data_info_for_begin ): scan_data_info_for_update = deepcopy(scan_data_info_for_begin) scan_data_info_for_update.data_collection_info.parent_id = data_collection_group_id assert dummy_params is not None scan_data_info_for_update.data_collection_grid_info = DataCollectionGridInfo( - dx_in_mm=dummy_params.experiment_params.x_step_size, - dy_in_mm=dummy_params.experiment_params.y_step_size, - steps_x=dummy_params.experiment_params.x_steps, - steps_y=dummy_params.experiment_params.y_steps, + dx_in_mm=dummy_params.x_step_size_um, + dy_in_mm=dummy_params.y_step_size_um, + steps_x=dummy_params.x_steps, + steps_y=dummy_params.y_steps, microns_per_pixel_x=1.25, microns_per_pixel_y=1.25, # cast coordinates from numpy int64 to avoid mysql type conversion issues @@ -408,27 +398,25 @@ def scan_xy_data_info_for_update( ) ) scan_data_info_for_update.data_collection_position_info = ( - populate_data_collection_position_info( - dummy_params.hyperion_params.ispyb_params - ) + populate_data_collection_position_info(dummy_params.ispyb_params) ) return scan_data_info_for_update def scan_data_infos_for_update_3d( - ispyb_ids, scan_xy_data_info_for_update, dummy_params + ispyb_ids, scan_xy_data_info_for_update, dummy_params: ThreeDGridScan ): xz_data_collection_info = populate_xz_data_collection_info( - dummy_params.hyperion_params.detector_params + dummy_params.detector_params ) - assert dummy_params.hyperion_params.ispyb_params is not None + assert dummy_params.ispyb_params is not None assert dummy_params is not None data_collection_grid_info = DataCollectionGridInfo( - dx_in_mm=dummy_params.experiment_params.x_step_size, - dy_in_mm=dummy_params.experiment_params.z_step_size, - steps_x=dummy_params.experiment_params.x_steps, - steps_y=dummy_params.experiment_params.z_steps, + dx_in_mm=dummy_params.x_step_size_um, + dy_in_mm=dummy_params.z_step_size_um, + steps_x=dummy_params.x_steps, + steps_y=dummy_params.z_steps, microns_per_pixel_x=1.25, microns_per_pixel_y=1.25, # cast coordinates from numpy int64 to avoid mysql type conversion issues @@ -441,8 +429,7 @@ def scan_data_infos_for_update_3d( construct_comment_for_gridscan(data_collection_grid_info), ispyb_ids.data_collection_group_id, xz_data_collection_info, - dummy_params.hyperion_params.detector_params, - dummy_params.hyperion_params.ispyb_params, + dummy_params, ) xz_data_collection_info.parent_id = ispyb_ids.data_collection_group_id @@ -450,9 +437,7 @@ def scan_data_infos_for_update_3d( data_collection_info=xz_data_collection_info, data_collection_grid_info=(data_collection_grid_info), data_collection_position_info=( - populate_data_collection_position_info( - dummy_params.hyperion_params.ispyb_params - ) + populate_data_collection_position_info(dummy_params.ispyb_params) ), ) return [scan_xy_data_info_for_update, scan_xz_data_info_for_update] @@ -475,7 +460,6 @@ def test_ispyb_get_comment_from_collection_correctly(fetch_comment: Callable[... def test_ispyb_deposition_comment_correct_on_failure( dummy_ispyb: StoreInIspyb, fetch_comment: Callable[..., Any], - dummy_params, dummy_data_collection_group_info, dummy_scan_data_info_for_begin, ): @@ -539,9 +523,7 @@ def test_can_store_2D_ispyb_data_correctly_when_in_error( dummy_data_collection_group_info, dummy_scan_data_info_for_begin, ): - ispyb: StoreInIspyb = StoreInIspyb( - CONST.SIM.DEV_ISPYB_DATABASE_CFG, experiment_type - ) + ispyb: StoreInIspyb = StoreInIspyb(CONST.SIM.DEV_ISPYB_DATABASE_CFG) ispyb_ids: IspybIds = ispyb.begin_deposition( dummy_data_collection_group_info, [dummy_scan_data_info_for_begin] ) @@ -623,17 +605,17 @@ def test_ispyb_deposition_in_gridscan( ) ispyb_ids = ispyb_callback.ispyb_ids - expected_values = { + DC_EXPECTED_VALUES = { "detectorid": 78, "axisstart": 0.0, "axisrange": 0, "axisend": 0, - "focalspotsizeatsamplex": 1.0, - "focalspotsizeatsampley": 1.0, + "focalspotsizeatsamplex": 20.0, + "focalspotsizeatsampley": 20.0, "slitgapvertical": 0.1, "slitgaphorizontal": 0.1, - "beamsizeatsamplex": 1, - "beamsizeatsampley": 1, + "beamsizeatsamplex": 20.0, + "beamsizeatsampley": 20.0, "transmission": 49.118, "datacollectionnumber": 1, "detectordistance": 100.0, @@ -665,11 +647,11 @@ def test_ispyb_deposition_in_gridscan( ) compare_actual_and_expected( ispyb_ids.data_collection_ids[0], - expected_values, + DC_EXPECTED_VALUES, fetch_datacollection_attribute, DATA_COLLECTION_COLUMN_MAP, ) - expected_values = { + GRIDINFO_EXPECTED_VALUES = { "gridInfoId": ispyb_ids.grid_ids[0], "dx_mm": 0.02, "dy_mm": 0.02, @@ -686,7 +668,7 @@ def test_ispyb_deposition_in_gridscan( compare_actual_and_expected( ispyb_ids.grid_ids[0], - expected_values, + GRIDINFO_EXPECTED_VALUES, fetch_datacollection_grid_attribute, GRID_INFO_COLUMN_MAP, ) @@ -697,42 +679,19 @@ def test_ispyb_deposition_in_gridscan( compare_actual_and_expected( position_id, expected_values, fetch_datacollection_position_attribute ) - expected_values = { - "detectorid": 78, - "axisstart": 90.0, - "axisrange": 0, - "axisend": 90, - "focalspotsizeatsamplex": 1.0, - "focalspotsizeatsampley": 1.0, - "slitgapvertical": 0.1, - "slitgaphorizontal": 0.1, - "beamsizeatsamplex": 1, - "beamsizeatsampley": 1, - "transmission": 49.118, - "datacollectionnumber": 2, - "detectordistance": 100.0, - "exposuretime": 0.12, - "imagedirectory": "/tmp/", - "imageprefix": "file_name", - "imagesuffix": "h5", - "numberofpasses": 1, - "overlap": 0, - "omegastart": 90, - "startimagenumber": 1, - "wavelength": 0.976254, - "xbeam": 150.0, - "ybeam": 160.0, - "xtalsnapshotfullpath1": "test_1_y", - "xtalsnapshotfullpath2": "test_2_y", - "xtalsnapshotfullpath3": "test_3_y", - "synchrotronmode": "User", - "undulatorgap1": 1.11, - "filetemplate": "file_name_2_master.h5", - "numberofimages": 20 * 11, - } + DC_EXPECTED_VALUES.update( + { + "axisstart": 90.0, + "axisend": 90.0, + "datacollectionnumber": 2, + "omegastart": 90.0, + "filetemplate": "file_name_2_master.h5", + "numberofimages": 220, + } + ) compare_actual_and_expected( ispyb_ids.data_collection_ids[1], - expected_values, + DC_EXPECTED_VALUES, fetch_datacollection_attribute, DATA_COLLECTION_COLUMN_MAP, ) @@ -750,23 +709,17 @@ def test_ispyb_deposition_in_gridscan( compare_actual_and_expected( position_id, expected_values, fetch_datacollection_position_attribute ) - expected_values = { - "gridInfoId": ispyb_ids.grid_ids[1], - "dx_mm": 0.02, - "dy_mm": 0.02, - "steps_x": 20, - "steps_y": 11, - "snapshot_offsetXPixel": 100, - "snapshot_offsetYPixel": 165, - "orientation": "horizontal", - "snaked": True, - "dataCollectionId": ispyb_ids.data_collection_ids[1], - "micronsPerPixelX": 2.87, - "micronsPerPixelY": 2.87, - } + GRIDINFO_EXPECTED_VALUES.update( + { + "gridInfoId": ispyb_ids.grid_ids[1], + "steps_y": 11.0, + "snapshot_offsetYPixel": 165.0, + "dataCollectionId": ispyb_ids.data_collection_ids[1], + } + ) compare_actual_and_expected( ispyb_ids.grid_ids[1], - expected_values, + GRIDINFO_EXPECTED_VALUES, fetch_datacollection_grid_attribute, GRID_INFO_COLUMN_MAP, ) @@ -786,6 +739,7 @@ def compare_comment( def compare_actual_and_expected( id, expected_values, fetch_datacollection_attribute, column_map: dict | None = None ): + results = "\n" for k, v in expected_values.items(): actual = fetch_datacollection_attribute( id, column_map[k.lower()] if column_map else k @@ -795,8 +749,10 @@ def compare_actual_and_expected( if isinstance(v, float): actual_v = actual == pytest.approx(v) else: - actual_v = actual == v # if this is inlined, I don't get a nice message :/ - assert actual_v, f"expected {k} {v} == {actual}" + actual_v = actual == v + if not actual_v: + results += f"expected {k} {v} == {actual}\n" + assert results == "\n", results @pytest.mark.s03 @@ -818,8 +774,8 @@ def test_ispyb_deposition_in_rotation_plan( fake_create_devices: dict[str, Any], ): test_wl = 0.71 - test_bs_x = 0.023 - test_bs_y = 0.047 + test_bs_x = 20 + test_bs_y = 20 test_exp_time = 0.023 test_img_wid = 0.27 test_undulator_current_gap = 1.12 @@ -828,8 +784,6 @@ def test_ispyb_deposition_in_rotation_plan( test_slit_gap_vert = 0.234 test_rotation_params.rotation_increment_deg = test_img_wid - test_rotation_params.ispyb_extras.beam_size_x = test_bs_x - test_rotation_params.ispyb_extras.beam_size_y = test_bs_y test_rotation_params.exposure_time_s = test_exp_time energy_ev = convert_angstrom_to_eV(test_wl) set_mock_value( @@ -886,19 +840,16 @@ def test_ispyb_deposition_in_rotation_plan( dcid = ispyb_cb.ispyb_ids.data_collection_ids[0] assert dcid is not None assert fetch_comment(dcid) == "Hyperion rotation scan" - assert fetch_datacollection_attribute(dcid, "wavelength") == test_wl - assert fetch_datacollection_attribute(dcid, "beamSizeAtSampleX") == test_bs_x - assert fetch_datacollection_attribute(dcid, "beamSizeAtSampleY") == test_bs_y - assert fetch_datacollection_attribute(dcid, "exposureTime") == test_exp_time - assert ( - fetch_datacollection_attribute(dcid, "undulatorGap1") - == test_undulator_current_gap - ) - assert ( - fetch_datacollection_attribute(dcid, "synchrotronMode") - == test_synchrotron_mode.value - ) - assert ( - fetch_datacollection_attribute(dcid, "slitGapHorizontal") == test_slit_gap_horiz - ) - assert fetch_datacollection_attribute(dcid, "slitGapVertical") == test_slit_gap_vert + + EXPECTED_VALUES = { + "wavelength": test_wl, + "beamSizeAtSampleX": test_bs_x, + "beamSizeAtSampleY": test_bs_y, + "exposureTime": test_exp_time, + "undulatorGap1": test_undulator_current_gap, + "synchrotronMode": test_synchrotron_mode.value, + "slitGapHorizontal": test_slit_gap_horiz, + "slitGapVertical": test_slit_gap_vert, + } + + compare_actual_and_expected(dcid, EXPECTED_VALUES, fetch_datacollection_attribute) diff --git a/tests/system_tests/external_interaction/test_nexgen.py b/tests/system_tests/external_interaction/test_nexgen.py index 832d5d4f3..c91b6dd25 100644 --- a/tests/system_tests/external_interaction/test_nexgen.py +++ b/tests/system_tests/external_interaction/test_nexgen.py @@ -16,9 +16,7 @@ RotationNexusFileCallback, ) from hyperion.parameters.constants import CONST -from hyperion.parameters.plan_specific.rotation_scan_internal_params import ( - RotationInternalParameters, -) +from hyperion.parameters.rotation import RotationScan from ...conftest import extract_metafile, raw_params_from_file @@ -30,15 +28,14 @@ def test_params(tmpdir): param_dict = raw_params_from_file( "tests/test_data/parameter_json_files/good_test_rotation_scan_parameters.json" ) - param_dict["hyperion_params"]["detector_params"]["directory"] = "tests/test_data" - param_dict["experiment_params"]["rotation_angle"] = 360.0 - param_dict["hyperion_params"]["detector_params"]["expected_energy_ev"] = 12700 - param_dict["experiment_params"]["rotation_angle"] = 360.0 - params = RotationInternalParameters(**param_dict) - params.experiment_params.x = 0 - params.experiment_params.y = 0 - params.experiment_params.z = 0 - params.hyperion_params.detector_params.exposure_time = 0.004 + params = RotationScan(**param_dict) + params.demand_energy_ev = 12700 + params.scan_width_deg = 360 + params.storage_directory = "tests/test_data" + params.x_start_um = 0 + params.y_start_um = 0 + params.z_start_um = 0 + params.exposure_time_s = 0.004 return params @@ -59,7 +56,7 @@ def test_params(tmpdir): ) @pytest.mark.s03 def test_rotation_nexgen( - test_params: RotationInternalParameters, + test_params: RotationScan, tmpdir, fake_create_rotation_devices: RotationScanComposite, test_data_directory, @@ -67,9 +64,9 @@ def test_rotation_nexgen( reference_file, ): meta_file = f"{prefix}_meta.h5.gz" - test_params.hyperion_params.detector_params.prefix = f"{tmpdir}/{prefix}" - test_params.hyperion_params.detector_params.directory = f"{tmpdir}" - run_number = test_params.hyperion_params.detector_params.run_number + test_params.file_name = prefix + test_params.storage_directory = f"{tmpdir}" + run_number = test_params.detector_params.run_number extract_metafile( f"{test_data_directory}/{meta_file}", f"{tmpdir}/{prefix}_{run_number}_meta.h5" @@ -150,7 +147,7 @@ def _run_imginfo(filename): def _fake_rotation_scan( - parameters: RotationInternalParameters, + parameters: RotationScan, subscription: RotationNexusFileCallback, rotation_devices: RotationScanComposite, ): diff --git a/tests/system_tests/external_interaction/test_zocalo_system.py b/tests/system_tests/external_interaction/test_zocalo_system.py index d228bf454..3aee45a24 100644 --- a/tests/system_tests/external_interaction/test_zocalo_system.py +++ b/tests/system_tests/external_interaction/test_zocalo_system.py @@ -15,9 +15,7 @@ ispyb_activation_wrapper, ) from hyperion.parameters.constants import CONST -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanInternalParameters, -) +from hyperion.parameters.gridscan import ThreeDGridScan from tests.conftest import create_dummy_scan_spec """ @@ -58,13 +56,13 @@ def fake_fgs_plan(): @pytest.fixture def run_zocalo_with_dev_ispyb( - dummy_params: GridscanInternalParameters, + dummy_params: ThreeDGridScan, dummy_ispyb_3d, RE: RunEngine, zocalo_device: ZocaloResults, ): async def inner(sample_name="", fallback=np.array([0, 0, 0])): - dummy_params.hyperion_params.detector_params.prefix = sample_name + dummy_params.file_name = sample_name _, ispyb_callback = create_gridscan_callbacks() ispyb_callback.ispyb_config = dummy_ispyb_3d.ISPYB_CONFIG_PATH RE.subscribe(ispyb_callback) @@ -77,7 +75,7 @@ def trigger_zocalo_after_fast_grid_scan(): md={ "subplan_name": CONST.PLAN.GRIDSCAN_OUTER, CONST.TRIGGER.ZOCALO: CONST.PLAN.DO_FGS, - "hyperion_internal_parameters": dummy_params.json(), + "hyperion_parameters": dummy_params.json(), } ) def inner_plan(): diff --git a/tests/test_data/hyperion_parameters.json b/tests/test_data/hyperion_parameters.json deleted file mode 100644 index 00c35a763..000000000 --- a/tests/test_data/hyperion_parameters.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "zocalo_environment": "dev_artemis", - "beamline": "BL03S", - "insertion_prefix": "SR03S", - "experiment_type": "flyscan_xray_centre", - "detector_params": { - "expected_energy_ev": 100.0, - "exposure_time": 0.1, - "directory": "/tmp/", - "prefix": "file_name", - "run_number": 0, - "detector_distance": 100.0, - "omega_start": 0.0, - "omega_increment": 0.0, - "num_images_per_trigger": 1, - "num_triggers": 60, - "use_roi_mode": false, - "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt", - "trigger_mode": 2, - "detector_size_constants": "EIGER2_X_16M", - "beam_xy_converter": null - }, - "ispyb_params": { - "visit_path": "/tmp/cm31105-4/", - "position": [ - 10.0, - 20.0, - 30.0 - ], - "beam_size_x": 1.0, - "beam_size_y": 1.0, - "focal_spot_size_x": 1.0, - "focal_spot_size_y": 1.0, - "comment": "test", - "sample_id": null, - "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" - ] - } -} \ No newline at end of file diff --git a/tests/test_data/new_parameter_json_files/good_test_grid_with_edge_detect_parameters.json b/tests/test_data/new_parameter_json_files/good_test_grid_with_edge_detect_parameters.json deleted file mode 100644 index 045f5ca8a..000000000 --- a/tests/test_data/new_parameter_json_files/good_test_grid_with_edge_detect_parameters.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "parameter_model_version": "5.0.0", - "beamline": "BL03S", - "insertion_prefix": "SR03S", - "detector": "EIGER2_X_16M", - "zocalo_environment": "devrmq", - "storage_directory": "/tmp", - "file_name": "file_name", - "run_number": 0, - "sample_id": 123456, - "use_roi_mode": false, - "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt", - "exposure_time_s": 0.1, - "detector_distance_mm": 100.0, - "omega_start_deg": 0.0, - "grid_width_um": 290.6, - "oav_centring_file": "tests/test_data/test_OAVCentring.json", - "transmission_frac": 1.0, - "visit": "cm31105-4", - "ispyb_extras": { - "position": [ - 10.0, - 20.0, - 30.0 - ], - "xtal_snapshots_omega_start": [ - "c", - "b", - "a" - ], - "xtal_snapshots_omega_end": [ - "f", - "e", - "d" - ], - "beam_size_x": 1.0, - "beam_size_y": 1.0, - "focal_spot_size_x": 1.0, - "focal_spot_size_y": 1.0 - } -} \ No newline at end of file diff --git a/tests/test_data/new_parameter_json_files/good_test_parameters.json b/tests/test_data/new_parameter_json_files/good_test_parameters.json deleted file mode 100644 index 9107e4fe2..000000000 --- a/tests/test_data/new_parameter_json_files/good_test_parameters.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "parameter_model_version": "5.0.0", - "demand_energy_ev": 100, - "comment": "test", - "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt", - "detector_distance_mm": 100.0, - "visit": "cm31105-4", - "exposure_time_s": 0.1, - "insertion_prefix": "SR03S", - "omega_start_deg": 0.0, - "file_name": "file_name", - "sample_id": 123456, - "run_number": 0, - "use_roi_mode": false, - "transmission_frac": 1.0, - "zocalo_environment": "dev_artemis", - "x_steps": 40, - "y_steps": 20, - "z_steps": 10, - "x_step_size_um": 0.1, - "y_step_size_um": 0.1, - "z_step_size_um": 0.1, - "x_start_um": 0.0, - "y_start_um": 0.0, - "y2_start_um": 0.0, - "z_start_um": 0.0, - "z2_start_um": 0.0, - "storage_directory": "/tmp/dls/i03/data/2024/cm31105-4/xraycentring/123456/", - "ispyb_extras": { - "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 - } -} \ No newline at end of file diff --git a/tests/test_data/new_parameter_json_files/good_test_pin_centre_then_xray_centre_parameters.json b/tests/test_data/new_parameter_json_files/good_test_pin_centre_then_xray_centre_parameters.json deleted file mode 100644 index ae0a8bc0d..000000000 --- a/tests/test_data/new_parameter_json_files/good_test_pin_centre_then_xray_centre_parameters.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parameter_model_version": "5.0.0", - "beamline": "BL03S", - "insertion_prefix": "SR03S", - "detector": "EIGER2_X_16M", - "zocalo_environment": "devrmq", - "storage_directory": "/tmp", - "file_name": "file_name", - "run_number": 0, - "sample_id": 123456, - "use_roi_mode": false, - "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt", - "exposure_time_s": 0.1, - "detector_distance_mm": 100.0, - "omega_start_deg": 0.0, - "tip_offset_um": 108.9, - "grid_width_um": 290.6, - "oav_centring_file": "tests/test_data/test_OAVCentring.json", - "transmission_frac": 1.0, - "visit": "cm31105-4", - "ispyb_extras": { - "position": [ - 10.0, - 20.0, - 30.0 - ], - "beam_size_x": 1.0, - "beam_size_y": 1.0, - "focal_spot_size_x": 1.0, - "focal_spot_size_y": 1.0 - } -} \ No newline at end of file diff --git a/tests/test_data/new_parameter_json_files/good_test_robot_load_params_no_energy.json b/tests/test_data/new_parameter_json_files/good_test_robot_load_params_no_energy.json deleted file mode 100644 index 30f188799..000000000 --- a/tests/test_data/new_parameter_json_files/good_test_robot_load_params_no_energy.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "parameter_model_version": "5.0.0", - "zocalo_environment": "dev_artemis", - "beamline": "BL03S", - "insertion_prefix": "SR03S", - "storage_directory": "/tmp/", - "visit": "cm31105-4", - "file_name": "file_name", - "run_number": 0, - "use_roi_mode": false, - "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt", - "omega_start_deg": 0, - "transmission_frac": 1.0, - "exposure_time_s": 0.004, - "detector_distance_mm": 255, - "sample_id": 12345, - "sample_puck": 40, - "sample_pin": 3, - "comment": "Descriptive comment.", - "ispyb_extras": { - "position": [ - 0, - 0, - 0 - ], - "beam_size_x": 0.1, - "beam_size_y": 0.1, - "focal_spot_size_x": 0.0, - "focal_spot_size_y": 0.0 - } -} \ No newline at end of file diff --git a/tests/test_data/new_parameter_json_files/good_test_rotation_scan_parameters.json b/tests/test_data/new_parameter_json_files/good_test_rotation_scan_parameters.json deleted file mode 100644 index 1ddb2cf76..000000000 --- a/tests/test_data/new_parameter_json_files/good_test_rotation_scan_parameters.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "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": { - "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 - } -} \ No newline at end of file diff --git a/tests/test_data/new_parameter_json_files/good_test_rotation_scan_parameters_nomove.json b/tests/test_data/new_parameter_json_files/good_test_rotation_scan_parameters_nomove.json deleted file mode 100644 index 0aec11668..000000000 --- a/tests/test_data/new_parameter_json_files/good_test_rotation_scan_parameters_nomove.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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, - "ispyb_extras": { - "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 - } -} \ No newline at end of file diff --git a/tests/test_data/nexus_files/rotation/ins_8_5_expected_output.txt b/tests/test_data/nexus_files/rotation/ins_8_5_expected_output.txt index a34bc90ad..a1b8b422d 100644 --- a/tests/test_data/nexus_files/rotation/ins_8_5_expected_output.txt +++ b/tests/test_data/nexus_files/rotation/ins_8_5_expected_output.txt @@ -43,7 +43,7 @@ Sweep-1 : from image 1 : Omega= 0.000 .. 0.100 Kappa= 0.000 .. 0.000 Chi= 0.000 .. 0.000 Phi= 0.000 .. 0.000 2-Theta= 0.000 .. 0.000 - to image 3600 : Omega= 360.000 .. 360.100 Kappa= 0.000 .. 0.000 Chi= 0.000 .. 0.000 Phi= 0.000 .. 0.000 2-Theta= 0.000 .. 0.000 + to image 3600 : Omega= 359.900 .. 360.000 Kappa= 0.000 .. 0.000 Chi= 0.000 .. 0.000 Phi= 0.000 .. 0.000 2-Theta= 0.000 .. 0.000 Image number 1/3600 @@ -54,8 +54,8 @@ sensor thickness [mm] = 0.450 sensor material = Si Phi-angle [degree] = 0.00000 - Omega-angle (start, end) [degree] = 0.00000 0.10003 - Oscillation-angle in Omega [degree] = 0.10003 + Omega-angle (start, end) [degree] = 0.00000 0.10000 + Oscillation-angle in Omega [degree] = 0.10000 Chi-angle [degree] = 0.00000 Pixel size in X [mm] = 0.075000 Pixel size in Y [mm] = 0.075000 diff --git a/tests/test_data/nexus_files/rotation_unicode_metafile/ins_8_5_expected_output.txt b/tests/test_data/nexus_files/rotation_unicode_metafile/ins_8_5_expected_output.txt index a34bc90ad..a1b8b422d 100644 --- a/tests/test_data/nexus_files/rotation_unicode_metafile/ins_8_5_expected_output.txt +++ b/tests/test_data/nexus_files/rotation_unicode_metafile/ins_8_5_expected_output.txt @@ -43,7 +43,7 @@ Sweep-1 : from image 1 : Omega= 0.000 .. 0.100 Kappa= 0.000 .. 0.000 Chi= 0.000 .. 0.000 Phi= 0.000 .. 0.000 2-Theta= 0.000 .. 0.000 - to image 3600 : Omega= 360.000 .. 360.100 Kappa= 0.000 .. 0.000 Chi= 0.000 .. 0.000 Phi= 0.000 .. 0.000 2-Theta= 0.000 .. 0.000 + to image 3600 : Omega= 359.900 .. 360.000 Kappa= 0.000 .. 0.000 Chi= 0.000 .. 0.000 Phi= 0.000 .. 0.000 2-Theta= 0.000 .. 0.000 Image number 1/3600 @@ -54,8 +54,8 @@ sensor thickness [mm] = 0.450 sensor material = Si Phi-angle [degree] = 0.00000 - Omega-angle (start, end) [degree] = 0.00000 0.10003 - Oscillation-angle in Omega [degree] = 0.10003 + Omega-angle (start, end) [degree] = 0.00000 0.10000 + Oscillation-angle in Omega [degree] = 0.10000 Chi-angle [degree] = 0.00000 Pixel size in X [mm] = 0.075000 Pixel size in Y [mm] = 0.075000 diff --git a/tests/test_data/parameter_json_files/bad_test_parameters_wrong_version.json b/tests/test_data/parameter_json_files/bad_test_parameters_wrong_version.json deleted file mode 100644 index ca756f036..000000000 --- a/tests/test_data/parameter_json_files/bad_test_parameters_wrong_version.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "params_version": "0.0.4", - "hyperion_params": { - "beamline": "BL03S", - "insertion_prefix": "SR03S", - "detector": "EIGER2_X_16M", - "zocalo_environment": "dev_artemis", - "experiment_type": "grid_scan", - "detector_params": { - "expected_energy_ev": 100, - "exposure_time": 0.1, - "directory": "/tmp", - "prefix": "file_name", - "run_number": 0, - "detector_distance": 100.0, - "omega_start": 0.0, - "num_images": 50, - "use_roi_mode": false, - "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt" - }, - "ispyb_params": { - "visit_path": "/tmp/cm31105-4/", - "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, - "comment": "test" - } - }, - "experiment_params": { - "x_steps": 5, - "y_steps": 10, - "z_steps": 2, - "x_step_size": 0.1, - "y_step_size": 0.1, - "z_step_size": 0.1, - "dwell_time_ms": 2, - "x_start": 0.0, - "y1_start": 0.0, - "y2_start": 0.0, - "z1_start": 0.0, - "z2_start": 0.0 - } -} \ No newline at end of file diff --git a/tests/test_data/parameter_json_files/good_test_grid_with_edge_detect_parameters.json b/tests/test_data/parameter_json_files/good_test_grid_with_edge_detect_parameters.json index 88b2bf8c4..8c28571c4 100644 --- a/tests/test_data/parameter_json_files/good_test_grid_with_edge_detect_parameters.json +++ b/tests/test_data/parameter_json_files/good_test_grid_with_edge_detect_parameters.json @@ -1,39 +1,37 @@ { - "params_version": "4.0.5", - "hyperion_params": { - "beamline": "BL03S", - "insertion_prefix": "SR03S", - "detector": "EIGER2_X_16M", - "zocalo_environment": "dev_artemis", - "experiment_type": "full_grid_scan", - "detector_params": { - "expected_energy_ev": 100, - "directory": "/tmp", - "prefix": "file_name", - "run_number": 0, - "use_roi_mode": false, - "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt" - }, - "ispyb_params": { - "visit_path": "/tmp/cm31105-4/", - "position": [ - 10.0, - 20.0, - 30.0 - ], - "beam_size_x": 1.0, - "beam_size_y": 1.0, - "focal_spot_size_x": 1.0, - "focal_spot_size_y": 1.0, - "comment": "test" - } - }, - "experiment_params": { - "snapshot_dir": "/tmp", - "exposure_time": 0.1, - "detector_distance": 100.0, - "omega_start": 0.0, - "grid_width_microns": 151, - "transmission_fraction": 1.0 + "parameter_model_version": "5.0.0", + "beamline": "BL03S", + "insertion_prefix": "SR03S", + "detector": "EIGER2_X_16M", + "zocalo_environment": "devrmq", + "storage_directory": "/tmp", + "file_name": "file_name", + "run_number": 0, + "sample_id": 123456, + "use_roi_mode": false, + "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt", + "exposure_time_s": 0.1, + "detector_distance_mm": 100.0, + "omega_start_deg": 0.0, + "grid_width_um": 290.6, + "oav_centring_file": "tests/test_data/test_OAVCentring.json", + "transmission_frac": 1.0, + "visit": "cm31105-4", + "ispyb_extras": { + "position": [ + 10.0, + 20.0, + 30.0 + ], + "xtal_snapshots_omega_start": [ + "c", + "b", + "a" + ], + "xtal_snapshots_omega_end": [ + "f", + "e", + "d" + ] } } \ No newline at end of file diff --git a/tests/test_data/parameter_json_files/good_test_parameters.json b/tests/test_data/parameter_json_files/good_test_parameters.json index 107b48611..43a4b0910 100644 --- a/tests/test_data/parameter_json_files/good_test_parameters.json +++ b/tests/test_data/parameter_json_files/good_test_parameters.json @@ -1,66 +1,51 @@ { - "params_version": "4.0.5", - "hyperion_params": { - "beamline": "BL03S", - "insertion_prefix": "SR03S", - "detector": "EIGER2_X_16M", - "zocalo_environment": "dev_artemis", - "experiment_type": "flyscan_xray_centre", - "detector_params": { - "expected_energy_ev": 100, - "directory": "/tmp/dls/i03/data/2024/cm31105-4/xraycentring/123456/", - "prefix": "file_name", - "run_number": 1, - "use_roi_mode": false, - "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt" - }, - "ispyb_params": { - "sample_id": "123456", - "visit_path": "/tmp/dls/i03/data/2024/cm31105-4", - "current_energy_ev": 100, - "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, - "comment": "test" - } - }, - "experiment_params": { - "x_steps": 5, - "y_steps": 10, - "z_steps": 2, - "x_step_size": 0.1, - "y_step_size": 0.1, - "z_step_size": 0.1, - "dwell_time_ms": 2, - "x_start": 0.0, - "y1_start": 0.0, - "y2_start": 0.0, - "z1_start": 0.0, - "z2_start": 0.0, - "exposure_time": 0.1, - "detector_distance": 100.0, - "omega_start": 0.0, - "transmission_fraction": 1.0 + "parameter_model_version": "5.0.0", + "demand_energy_ev": 100, + "comment": "test", + "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt", + "detector_distance_mm": 100.0, + "visit": "cm31105-4", + "exposure_time_s": 0.1, + "insertion_prefix": "SR03S", + "omega_start_deg": 0.0, + "file_name": "file_name", + "sample_id": 123456, + "run_number": 0, + "use_roi_mode": false, + "transmission_frac": 1.0, + "zocalo_environment": "dev_artemis", + "x_steps": 40, + "y_steps": 20, + "z_steps": 10, + "x_step_size_um": 0.1, + "y_step_size_um": 0.1, + "z_step_size_um": 0.1, + "x_start_um": 0.0, + "y_start_um": 0.0, + "y2_start_um": 0.0, + "z_start_um": 0.0, + "z2_start_um": 0.0, + "storage_directory": "/tmp/dls/i03/data/2024/cm31105-4/xraycentring/123456/", + "ispyb_extras": { + "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" + ] } } \ No newline at end of file diff --git a/tests/test_data/parameter_json_files/good_test_pin_centre_then_xray_centre_parameters.json b/tests/test_data/parameter_json_files/good_test_pin_centre_then_xray_centre_parameters.json index 3f2b63157..1baebf302 100644 --- a/tests/test_data/parameter_json_files/good_test_pin_centre_then_xray_centre_parameters.json +++ b/tests/test_data/parameter_json_files/good_test_pin_centre_then_xray_centre_parameters.json @@ -1,41 +1,28 @@ { - "params_version": "4.0.5", - "hyperion_params": { - "beamline": "BL03S", - "insertion_prefix": "SR03S", - "detector": "EIGER2_X_16M", - "zocalo_environment": "devrmq", - "experiment_type": "pin_tip_centre_then_xray_centre", - "detector_params": { - "expected_energy_ev": 100, - "directory": "/tmp", - "prefix": "file_name", - "run_number": 0, - "use_roi_mode": false, - "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt" - }, - "ispyb_params": { - "visit_path": "/tmp/cm31105-4/", - "position": [ - 10.0, - 20.0, - 30.0 - ], - "beam_size_x": 1.0, - "beam_size_y": 1.0, - "focal_spot_size_x": 1.0, - "focal_spot_size_y": 1.0, - "comment": "test" - } - }, - "experiment_params": { - "snapshot_dir": "/tmp", - "exposure_time": 0.1, - "detector_distance": 100.0, - "omega_start": 0.0, - "tip_offset_microns": 108.9, - "grid_width_microns": 290.6, - "oav_centring_file": "tests/test_data/test_OAVCentring.json", - "transmission_fraction": 1.0 + "parameter_model_version": "5.0.0", + "beamline": "BL03S", + "insertion_prefix": "SR03S", + "detector": "EIGER2_X_16M", + "zocalo_environment": "devrmq", + "storage_directory": "/tmp", + "file_name": "file_name", + "run_number": 0, + "sample_id": 123456, + "use_roi_mode": false, + "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt", + "exposure_time_s": 0.1, + "detector_distance_mm": 100.0, + "omega_start_deg": 0.0, + "tip_offset_um": 108.9, + "grid_width_um": 290.6, + "oav_centring_file": "tests/test_data/test_OAVCentring.json", + "transmission_frac": 1.0, + "visit": "cm31105-4", + "ispyb_extras": { + "position": [ + 10.0, + 20.0, + 30.0 + ] } } \ No newline at end of file diff --git a/tests/test_data/new_parameter_json_files/good_test_robot_load_params.json b/tests/test_data/parameter_json_files/good_test_robot_load_params.json similarity index 84% rename from tests/test_data/new_parameter_json_files/good_test_robot_load_params.json rename to tests/test_data/parameter_json_files/good_test_robot_load_params.json index 5bc41ad51..fd89d3e29 100644 --- a/tests/test_data/new_parameter_json_files/good_test_robot_load_params.json +++ b/tests/test_data/parameter_json_files/good_test_robot_load_params.json @@ -23,10 +23,6 @@ 0, 0, 0 - ], - "beam_size_x": 0.1, - "beam_size_y": 0.1, - "focal_spot_size_x": 0.0, - "focal_spot_size_y": 0.0 + ] } } \ No newline at end of file diff --git a/tests/test_data/parameter_json_files/good_test_rotation_scan_parameters.json b/tests/test_data/parameter_json_files/good_test_rotation_scan_parameters.json index 15dae30e2..b89e3691a 100644 --- a/tests/test_data/parameter_json_files/good_test_rotation_scan_parameters.json +++ b/tests/test_data/parameter_json_files/good_test_rotation_scan_parameters.json @@ -1,63 +1,50 @@ { - "params_version": "4.0.5", - "hyperion_params": { - "beamline": "BL03S", - "insertion_prefix": "SR03S", - "detector": "EIGER2_X_16M", - "zocalo_environment": "dev_artemis", - "experiment_type": "rotation_scan", - "detector_params": { - "expected_energy_ev": 100, - "directory": "/tmp", - "prefix": "file_name", - "run_number": 0, - "use_roi_mode": false, - "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt" - }, - "ispyb_params": { - "visit_path": "/tmp/cm31105-4/", - "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, - "comment": "test" - } - }, - "experiment_params": { - "rotation_axis": "omega", - "rotation_angle": 180.0, - "omega_start": 0.0, - "phi_start": 0.0, - "chi_start": 0, - "x": 1.0, - "transmission_fraction": 1.0, - "y": 2.0, - "z": 3.0, - "exposure_time": 0.1, - "detector_distance": 100.0, - "rotation_increment": 0.1, - "rotation_direction": "Negative", - "offset_deg": 1.0, - "shutter_opening_time_s": 0.6 + "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": { + "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" + ] } } \ No newline at end of file diff --git a/tests/test_data/parameter_json_files/good_test_rotation_scan_parameters_nomove.json b/tests/test_data/parameter_json_files/good_test_rotation_scan_parameters_nomove.json index 9e7fa633a..ca0b04c16 100644 --- a/tests/test_data/parameter_json_files/good_test_rotation_scan_parameters_nomove.json +++ b/tests/test_data/parameter_json_files/good_test_rotation_scan_parameters_nomove.json @@ -1,60 +1,45 @@ { - "params_version": "4.0.5", - "hyperion_params": { - "beamline": "BL03S", - "insertion_prefix": "SR03S", - "detector": "EIGER2_X_16M", - "zocalo_environment": "dev_artemis", - "experiment_type": "rotation_scan", - "detector_params": { - "expected_energy_ev": 100, - "directory": "/tmp/dls/i03/data/2024/cm31105-4/auto/123456/", - "prefix": "file_name", - "run_number": 1, - "use_roi_mode": false, - "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt" - }, - "ispyb_params": { - "visit_path": "/tmp/dls/i03/data/2024/cm31105-4", - "sample_id": "123456", - "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, - "comment": "test", - "ispyb_experiment_type": "SAD" - } - }, - "experiment_params": { - "transmission_fraction": 0.1, - "rotation_axis": "omega", - "rotation_angle": 180.0, - "omega_start": 0.0, - "exposure_time": 0.1, - "detector_distance": 100.0, - "rotation_increment": 0.1, - "rotation_direction": "Negative", - "offset_deg": 1.0, - "shutter_opening_time_s": 0.6 + "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, + "ispyb_extras": { + "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" + ] } } \ No newline at end of file diff --git a/tests/test_data/parameter_json_files/good_test_stepped_grid_scan_parameters.json b/tests/test_data/parameter_json_files/good_test_stepped_grid_scan_parameters.json deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/test_data/new_parameter_json_files/ispyb_gridscan_system_test_parameters.json b/tests/test_data/parameter_json_files/ispyb_gridscan_system_test_parameters.json similarity index 88% rename from tests/test_data/new_parameter_json_files/ispyb_gridscan_system_test_parameters.json rename to tests/test_data/parameter_json_files/ispyb_gridscan_system_test_parameters.json index 4bdf1d811..04ae96b43 100644 --- a/tests/test_data/new_parameter_json_files/ispyb_gridscan_system_test_parameters.json +++ b/tests/test_data/parameter_json_files/ispyb_gridscan_system_test_parameters.json @@ -33,10 +33,6 @@ "test_1_z", "test_2_z", "test_3_z" - ], - "beam_size_x": 1.0, - "beam_size_y": 1.0, - "focal_spot_size_x": 1.0, - "focal_spot_size_y": 1.0 + ] } } \ No newline at end of file diff --git a/tests/test_data/parameter_json_files/live_test_rotation_params.json b/tests/test_data/parameter_json_files/live_test_rotation_params.json deleted file mode 100644 index dda4de4b8..000000000 --- a/tests/test_data/parameter_json_files/live_test_rotation_params.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "params_version": "4.0.5", - "hyperion_params": { - "beamline": "BL03I", - "insertion_prefix": "SR03I", - "detector": "EIGER2_X_16M", - "zocalo_environment": "dev_artemis", - "experiment_type": "rotation_scan", - "detector_params": { - "expected_energy_ev": 12700, - "directory": "/dls/i03/data/2023/cm33866-3/rotation_scan_test", - "prefix": "rotation_scan_test", - "run_number": 0, - "use_roi_mode": false, - "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt" - }, - "ispyb_params": { - "visit_path": "/tmp/cm31105-4/", - "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, - "comment": "test" - } - }, - "experiment_params": { - "rotation_axis": "omega", - "transmission_fraction": 1.0, - "rotation_angle": 180.0, - "omega_start": 0.0, - "exposure_time": 0.01, - "detector_distance": 300.0, - "rotation_increment": 0.1, - "rotation_direction": "Negative", - "shutter_opening_time_s": 0.6 - } -} \ No newline at end of file diff --git a/tests/test_data/parameter_json_files/live_test_rotation_params_move_xyz.json b/tests/test_data/parameter_json_files/live_test_rotation_params_move_xyz.json deleted file mode 100644 index 5d612de0b..000000000 --- a/tests/test_data/parameter_json_files/live_test_rotation_params_move_xyz.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "params_version": "4.0.5", - "hyperion_params": { - "beamline": "BL03I", - "insertion_prefix": "SR03I", - "detector": "EIGER2_X_16M", - "zocalo_environment": "dev_artemis", - "experiment_type": "rotation_scan", - "detector_params": { - "expected_energy_ev": 12700, - "directory": "/dls/i03/data/2023/cm33866-3/rotation_scan_test", - "prefix": "rotation_scan_test", - "run_number": 0, - "use_roi_mode": false, - "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt" - }, - "ispyb_params": { - "visit_path": "/tmp/cm31105-4/", - "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, - "comment": "test" - } - }, - "experiment_params": { - "rotation_axis": "omega", - "transmission_fraction": 1.0, - "rotation_angle": 180.0, - "omega_start": 0.0, - "phi_start": 0.0, - "chi_start": 0, - "x": 0.1, - "y": 0.2, - "z": 0.3, - "exposure_time": 0.01, - "detector_distance": 300.0, - "rotation_increment": 0.1, - "rotation_direction": "Negative", - "shutter_opening_time_s": 0.6 - } -} \ No newline at end of file diff --git a/tests/test_data/parameter_json_files/panda_test_parameters.json b/tests/test_data/parameter_json_files/panda_test_parameters.json deleted file mode 100644 index 0e5a97803..000000000 --- a/tests/test_data/parameter_json_files/panda_test_parameters.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "params_version": "4.0.5", - "hyperion_params": { - "beamline": "BL03I", - "insertion_prefix": "SR03I", - "detector": "EIGER2_X_16M", - "zocalo_environment": "artemis", - "experiment_type": "panda_flyscan_xray_centre", - "detector_params": { - "expected_energy_ev": 12700, - "directory": "/tmp/dls/i03/data/2024/cm31105-4/", - "prefix": "panda_test", - "run_number": 336, - "use_roi_mode": false, - "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt" - }, - "ispyb_params": { - "expected_energy_ev": 12700, - "visit_path": "/dls/i03/data/2023/cm33866-5/", - "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, - "comment": "test" - } - }, - "experiment_params": { - "x_steps": 40, - "y_steps": 20, - "z_steps": 10, - "transmission_fraction": 1.0, - "x_step_size": 0.1, - "y_step_size": 0.1, - "z_step_size": 0.1, - "x_start": 0.0, - "y1_start": 0.0, - "y2_start": 0.0, - "z1_start": 0.0, - "z2_start": 0.0, - "detector_distance": 100.0, - "omega_start": 0.0, - "exposure_time": 0.1, - "set_stub_offsets": true, - "run_up_distance_mm": 0.1 - } -} \ No newline at end of file diff --git a/tests/test_data/parameter_json_files/system_test_parameter_defaults.json b/tests/test_data/parameter_json_files/system_test_parameter_defaults.json deleted file mode 100644 index c558ddd45..000000000 --- a/tests/test_data/parameter_json_files/system_test_parameter_defaults.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "params_version": "4.0.5", - "hyperion_params": { - "zocalo_environment": "dev_artemis", - "beamline": "BL03S", - "insertion_prefix": "SR03S", - "experiment_type": "flyscan_xray_centre", - "detector_params": { - "expected_energy_ev": 100, - "directory": "/tmp/", - "prefix": "file_name", - "run_number": 0, - "use_roi_mode": false, - "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt" - }, - "ispyb_params": { - "visit_path": "/tmp/cm31105-4", - "position": [ - 0, - 0, - 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" - ], - "beam_size_x": 0.1, - "beam_size_y": 0.1, - "focal_spot_size_x": 0.0, - "focal_spot_size_y": 0.0, - "comment": "Descriptive comment.", - "sample_id": null - } - }, - "experiment_params": { - "transmission_fraction": 1.0, - "x_steps": 40, - "y_steps": 20, - "z_steps": 10, - "x_step_size": 0.1, - "y_step_size": 0.1, - "z_step_size": 0.1, - "dwell_time_ms": 2, - "x_start": 0.0, - "y1_start": 0.0, - "y2_start": 0.0, - "z1_start": 0.0, - "z2_start": 0.0, - "detector_distance": 100.0, - "omega_start": 0.0, - "exposure_time": 0.1, - "set_stub_offsets": true - } -} \ No newline at end of file diff --git a/tests/test_data/new_parameter_json_files/test_gridscan_param_defaults.json b/tests/test_data/parameter_json_files/test_gridscan_param_defaults.json similarity index 89% rename from tests/test_data/new_parameter_json_files/test_gridscan_param_defaults.json rename to tests/test_data/parameter_json_files/test_gridscan_param_defaults.json index e9c8c555a..0ed8fd614 100644 --- a/tests/test_data/new_parameter_json_files/test_gridscan_param_defaults.json +++ b/tests/test_data/parameter_json_files/test_gridscan_param_defaults.json @@ -43,10 +43,6 @@ "test_1_z", "test_2_z", "test_3_z" - ], - "beam_size_x": 0.1, - "beam_size_y": 0.1, - "focal_spot_size_x": 0.0, - "focal_spot_size_y": 0.0 + ] } } \ No newline at end of file diff --git a/tests/test_data/parameter_json_files/test_internal_parameter_defaults.json b/tests/test_data/parameter_json_files/test_internal_parameter_defaults.json deleted file mode 100644 index 2c2ee3fbc..000000000 --- a/tests/test_data/parameter_json_files/test_internal_parameter_defaults.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "params_version": "4.0.5", - "hyperion_params": { - "zocalo_environment": "dev_artemis", - "beamline": "BL03S", - "insertion_prefix": "SR03S", - "experiment_type": "flyscan_xray_centre", - "detector_params": { - "expected_energy_ev": 100, - "directory": "/tmp/", - "prefix": "file_name", - "run_number": 0, - "use_roi_mode": false, - "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt" - }, - "ispyb_params": { - "expected_energy_ev": 100, - "visit_path": "/tmp/cm31105-4", - "position": [ - 0, - 0, - 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" - ], - "beam_size_x": 0.1, - "beam_size_y": 0.1, - "focal_spot_size_x": 0.0, - "focal_spot_size_y": 0.0, - "comment": "Descriptive comment.", - "sample_id": null - } - }, - "experiment_params": { - "transmission_fraction": 1.0, - "x_steps": 40, - "y_steps": 20, - "z_steps": 10, - "x_step_size": 0.1, - "y_step_size": 0.1, - "z_step_size": 0.1, - "dwell_time_ms": 2, - "x_start": 0.0, - "y1_start": 0.0, - "y2_start": 0.0, - "z1_start": 0.0, - "z2_start": 0.0, - "detector_distance": 100.0, - "omega_start": 0.0, - "exposure_time": 0.1, - "set_stub_offsets": true - } -} \ No newline at end of file diff --git a/tests/test_data/parameter_json_files/test_parameter_defaults_2d.json b/tests/test_data/parameter_json_files/test_parameter_defaults_2d.json deleted file mode 100644 index 404188095..000000000 --- a/tests/test_data/parameter_json_files/test_parameter_defaults_2d.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "params_version": "4.0.5", - "hyperion_params": { - "zocalo_environment": "dev_artemis", - "beamline": "BL03S", - "insertion_prefix": "SR03S", - "experiment_type": "flyscan_xray_centre", - "detector_params": { - "expected_energy_ev": 100, - "directory": "/tmp/", - "prefix": "file_name", - "run_number": 0, - "use_roi_mode": false, - "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt" - }, - "ispyb_params": { - "visit_path": "/tmp/cm31105-4", - "position": [ - 0, - 0, - 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" - ], - "beam_size_x": 0.1, - "beam_size_y": 0.1, - "focal_spot_size_x": 0.0, - "focal_spot_size_y": 0.0, - "comment": "Descriptive comment.", - "sample_id": "364758" - } - }, - "experiment_params": { - "transmission_fraction": 1.0, - "x_steps": 40, - "y_steps": 20, - "z_steps": 0, - "x_step_size": 0.1, - "y_step_size": 0.1, - "z_step_size": 0, - "dwell_time_ms": 2, - "x_start": 0.0, - "y1_start": 0.0, - "y2_start": 0.0, - "z1_start": 0.0, - "z2_start": 0.0, - "detector_distance": 100.0, - "omega_start": 0.0, - "exposure_time": 0.1, - "set_stub_offsets": true - } -} \ No newline at end of file diff --git a/tests/test_data/parameter_json_files/test_parameters.json b/tests/test_data/parameter_json_files/test_parameters.json deleted file mode 100644 index 9d5a6610e..000000000 --- a/tests/test_data/parameter_json_files/test_parameters.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "params_version": "4.0.5", - "hyperion_params": { - "beamline": "BL03S", - "insertion_prefix": "SR03S", - "detector": "EIGER2_X_16M", - "zocalo_environment": "dev_artemis", - "experiment_type": "flyscan_xray_centre", - "detector_params": { - "expected_energy_ev": 100, - "directory": "/tmp", - "prefix": "file_name", - "run_number": 0, - "use_roi_mode": false, - "det_dist_to_beam_converter_path": "tests/test_data/test_lookup_table.txt" - }, - "ispyb_params": { - "visit_path": "/tmp/cm31105-4/", - "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, - "comment": "test" - } - }, - "experiment_params": { - "transmission_fraction": 1.0, - "x_steps": 5, - "y_steps": 10, - "z_steps": 2, - "x_step_size": 0.1, - "y_step_size": 0.1, - "z_step_size": 0.1, - "dwell_time_ms": 2, - "x_start": 0.0, - "y1_start": 0.0, - "y2_start": 0.0, - "z1_start": 0.0, - "z2_start": 0.0, - "exposure_time": 0.1, - "detector_distance": 100.0, - "omega_start": 0.0 - } -} \ No newline at end of file diff --git a/tests/unit_tests/experiment_plans/conftest.py b/tests/unit_tests/experiment_plans/conftest.py index e5e19dbf9..83ac2161c 100644 --- a/tests/unit_tests/experiment_plans/conftest.py +++ b/tests/unit_tests/experiment_plans/conftest.py @@ -42,6 +42,12 @@ def make_event_doc(data, descriptor="abc123") -> Event: "synchrotron-synchrotron_mode": SynchrotronMode.USER, "s4_slit_gaps_xgap": 0, "s4_slit_gaps_ygap": 0, + "aperture_scatterguard-selected_aperture": { + "name": "Robot_load", + "GDA_name": "ROBOT_LOAD", + "radius_microns": None, + "location": (15, 16, 2, 18, 19), + }, } BASIC_POST_SETUP_DOC = { @@ -70,7 +76,7 @@ def run_generic_ispyb_handler_setup( ispyb_handler.activity_gated_start( { "subplan_name": CONST.PLAN.GRIDSCAN_OUTER, - "hyperion_internal_parameters": params.old_parameters().json(), + "hyperion_parameters": params.json(), } # type: ignore ) ispyb_handler.activity_gated_descriptor( diff --git a/tests/unit_tests/experiment_plans/test_experiment_registry.py b/tests/unit_tests/experiment_plans/test_experiment_registry.py index 5464e7336..941cc0511 100644 --- a/tests/unit_tests/experiment_plans/test_experiment_registry.py +++ b/tests/unit_tests/experiment_plans/test_experiment_registry.py @@ -1,7 +1,5 @@ from inspect import getfullargspec -from dodal.parameters.experiment_parameter_base import AbstractExperimentParameterBase - import hyperion.experiment_plans as plan_module from hyperion.experiment_plans import __all__ as exposed_plans from hyperion.experiment_plans.experiment_registry import PLAN_REGISTRY, do_nothing @@ -10,13 +8,7 @@ def test_experiment_registry_param_types(): for plan in PLAN_REGISTRY.keys(): - assert issubclass( - PLAN_REGISTRY[plan]["experiment_param_type"], - AbstractExperimentParameterBase, - ) - assert issubclass( - PLAN_REGISTRY[plan]["internal_param_type"], HyperionParameters - ) + assert issubclass(PLAN_REGISTRY[plan]["param_type"], HyperionParameters) def test_exposed_plans_in_reg(): @@ -29,7 +21,7 @@ def test_param_types_in_registry_match_plan(): plan_function = getattr(plan_module, plan) plan_args = getfullargspec(plan_function) param_arg_type = plan_args.annotations["parameters"] - assert PLAN_REGISTRY[plan]["internal_param_type"].__name__ in param_arg_type + assert PLAN_REGISTRY[plan]["param_type"].__name__ in param_arg_type def test_do_nothing(): diff --git a/tests/unit_tests/experiment_plans/test_flyscan_xray_centre_plan.py b/tests/unit_tests/experiment_plans/test_flyscan_xray_centre_plan.py index 59e9e8990..8bab276dd 100644 --- a/tests/unit_tests/experiment_plans/test_flyscan_xray_centre_plan.py +++ b/tests/unit_tests/experiment_plans/test_flyscan_xray_centre_plan.py @@ -87,7 +87,7 @@ def ispyb_plan(test_fgs_params): @bpp.run_decorator( # attach experiment metadata to the start document md={ "subplan_name": CONST.PLAN.GRIDSCAN_OUTER, - "hyperion_internal_parameters": test_fgs_params.json(), + "hyperion_parameters": test_fgs_params.json(), } ) def standalone_read_hardware_for_ispyb( @@ -199,6 +199,12 @@ def test_read_hardware_for_ispyb_updates_from_ophyd_devices( xgap_test_value = 0.1234 ygap_test_value = 0.2345 + ap_sg_test_value = { + "name": "Small", + "GDA_name": "SMALL_APERTURE", + "radius_microns": 20, + "location": (10, 11, 2, 13, 14), + } fake_fgs_composite.s4_slit_gaps.xgap.user_readback.sim_put(xgap_test_value) # type: ignore fake_fgs_composite.s4_slit_gaps.ygap.user_readback.sim_put(ygap_test_value) # type: ignore flux_test_value = 10.0 @@ -248,6 +254,7 @@ def test_read_hardware_for_ispyb_updates_from_ophyd_devices( "synchrotron-synchrotron_mode": synchrotron_test_value.value, "s4_slit_gaps_xgap": xgap_test_value, "s4_slit_gaps_ygap": ygap_test_value, + 'aperture_scatterguard-selected_aperture': ap_sg_test_value }, ) assert_event( @@ -499,9 +506,10 @@ def test_waits_for_motion_program( fake_fgs_composite.synchrotron, "zocalo environment", [ - test_fgs_params.old_parameters().get_scan_points(1), - test_fgs_params.old_parameters().get_scan_points(2), + test_fgs_params.scan_points_first_grid, + test_fgs_params.scan_points_second_grid, ], + test_fgs_params.scan_indices, ) ) fgs.KICKOFF_TIMEOUT = 1 @@ -514,9 +522,10 @@ def test_waits_for_motion_program( fake_fgs_composite.synchrotron, "zocalo environment", [ - test_fgs_params.old_parameters().get_scan_points(1), - test_fgs_params.old_parameters().get_scan_points(2), + test_fgs_params.scan_points_first_grid, + test_fgs_params.scan_points_second_grid, ], + test_fgs_params.scan_indices, ) ) assert res.exit_status == "success" @@ -845,6 +854,7 @@ def test_kickoff_and_complete_gridscan_triggers_zocalo( fake_fgs_composite.synchrotron, zocalo_env, scan_points=create_dummy_scan_spec(x_steps, y_steps, z_steps), + scan_start_indices=[0, x_steps * y_steps], ) ) diff --git a/tests/unit_tests/experiment_plans/test_panda_flyscan_xray_centre_plan.py b/tests/unit_tests/experiment_plans/test_panda_flyscan_xray_centre_plan.py index 91e28f1c3..74c115f6f 100644 --- a/tests/unit_tests/experiment_plans/test_panda_flyscan_xray_centre_plan.py +++ b/tests/unit_tests/experiment_plans/test_panda_flyscan_xray_centre_plan.py @@ -6,8 +6,8 @@ import bluesky.preprocessors as bpp import numpy as np import pytest -from bluesky import Msg from bluesky.run_engine import RunEngine +from bluesky.utils import Msg from dodal.devices.detector.det_dim_constants import ( EIGER2_X_4M_DIMENSION, EIGER_TYPE_EIGER2_X_4M, @@ -82,7 +82,7 @@ def ispyb_plan(test_panda_fgs_params): @bpp.run_decorator( # attach experiment metadata to the start document md={ "subplan_name": CONST.PLAN.GRIDSCAN_OUTER, - "hyperion_internal_parameters": test_panda_fgs_params.json(), + "hyperion_parameters": test_panda_fgs_params.json(), } ) def standalone_read_hardware_for_ispyb( @@ -141,7 +141,12 @@ def test_read_hardware_for_ispyb_updates_from_ophyd_devices( fake_fgs_composite.attenuator.actual_transmission.sim_put( # type: ignore transmission_test_value ) - + ap_sg_test_value = { + "name": "Small", + "GDA_name": "SMALL_APERTURE", + "radius_microns": 20, + "location": (10, 11, 2, 13, 14), + } xgap_test_value = 0.1234 ygap_test_value = 0.2345 fake_fgs_composite.s4_slit_gaps.xgap.user_readback.sim_put(xgap_test_value) # type: ignore @@ -185,6 +190,7 @@ def test_read_hardware_for_ispyb_updates_from_ophyd_devices( "synchrotron-synchrotron_mode": synchrotron_test_value.value, "s4_slit_gaps_xgap": xgap_test_value, "s4_slit_gaps_ygap": ygap_test_value, + 'aperture_scatterguard-selected_aperture': ap_sg_test_value, }, ) assert_event( diff --git a/tests/unit_tests/experiment_plans/test_pin_centre_then_xray_centre_plan.py b/tests/unit_tests/experiment_plans/test_pin_centre_then_xray_centre_plan.py index d7ea54d2d..232ccf8dd 100644 --- a/tests/unit_tests/experiment_plans/test_pin_centre_then_xray_centre_plan.py +++ b/tests/unit_tests/experiment_plans/test_pin_centre_then_xray_centre_plan.py @@ -19,7 +19,7 @@ @pytest.fixture def test_pin_centre_then_xray_centre_params(): params = raw_params_from_file( - "tests/test_data/new_parameter_json_files/good_test_pin_centre_then_xray_centre_parameters.json" + "tests/test_data/parameter_json_files/good_test_pin_centre_then_xray_centre_parameters.json" ) return PinTipCentreThenXrayCentre(**params) diff --git a/tests/unit_tests/experiment_plans/test_wait_for_robot_load_then_centre.py b/tests/unit_tests/experiment_plans/test_wait_for_robot_load_then_centre.py index f7c6c4abb..ee79cc70d 100644 --- a/tests/unit_tests/experiment_plans/test_wait_for_robot_load_then_centre.py +++ b/tests/unit_tests/experiment_plans/test_wait_for_robot_load_then_centre.py @@ -1,3 +1,4 @@ +from pathlib import Path from unittest.mock import MagicMock, patch import pytest @@ -43,19 +44,17 @@ def robot_load_composite( @pytest.fixture -def robot_load_then_centre_params_no_energy(): +def robot_load_then_centre_params(): params = raw_params_from_file( - "tests/test_data/new_parameter_json_files/good_test_robot_load_params_no_energy.json" + "tests/test_data/parameter_json_files/good_test_robot_load_params.json" ) return RobotLoadThenCentre(**params) @pytest.fixture -def robot_load_then_centre_params(): - params = raw_params_from_file( - "tests/test_data/new_parameter_json_files/good_test_robot_load_params.json" - ) - return RobotLoadThenCentre(**params) +def robot_load_then_centre_params_no_energy(robot_load_then_centre_params): + robot_load_then_centre_params.demand_energy_ev = None + return robot_load_then_centre_params def dummy_set_energy_plan(energy, composite): @@ -346,7 +345,7 @@ async def test_when_take_snapshots_called_then_filename_and_directory_set_and_de oav.snapshot.trigger = MagicMock(side_effect=oav.snapshot.trigger) webcam.trigger = MagicMock(return_value=NullStatus()) - RE(take_robot_snapshots(oav, webcam, TEST_DIRECTORY)) + RE(take_robot_snapshots(oav, webcam, Path(TEST_DIRECTORY))) oav.snapshot.trigger.assert_called_once() assert oav.snapshot.filename.get() == "TIME_oav_snapshot_after_load" diff --git a/tests/unit_tests/external_interaction/callbacks/conftest.py b/tests/unit_tests/external_interaction/callbacks/conftest.py index 6ddc22872..0252ab9f9 100644 --- a/tests/unit_tests/external_interaction/callbacks/conftest.py +++ b/tests/unit_tests/external_interaction/callbacks/conftest.py @@ -5,9 +5,6 @@ from hyperion.parameters.constants import CONST from hyperion.parameters.gridscan import ThreeDGridScan -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanInternalParameters, -) from tests.conftest import create_dummy_scan_spec from ....conftest import default_raw_params, raw_params_from_file @@ -19,11 +16,11 @@ def dummy_params(): def dummy_params_2d(): - return GridscanInternalParameters( - **raw_params_from_file( - "tests/test_data/parameter_json_files/test_parameter_defaults_2d.json" - ) + raw_params = raw_params_from_file( + "tests/test_data/parameter_json_files/test_gridscan_param_defaults.json" ) + raw_params["z_steps"] = 1 + return ThreeDGridScan(**raw_params) @pytest.fixture @@ -31,7 +28,7 @@ def test_rotation_start_outer_document(dummy_rotation_params): return { "uid": "d8bee3ee-f614-4e7a-a516-25d6b9e87ef3", "subplan_name": CONST.PLAN.ROTATION_OUTER, - "hyperion_internal_parameters": dummy_rotation_params.json(), + "hyperion_parameters": dummy_rotation_params.json(), } @@ -48,7 +45,7 @@ class TestData: "plan_name": CONST.PLAN.GRIDSCAN_OUTER, "subplan_name": CONST.PLAN.GRIDSCAN_OUTER, CONST.TRIGGER.ZOCALO: CONST.PLAN.DO_FGS, - "hyperion_internal_parameters": dummy_params().old_parameters().json(), + "hyperion_parameters": dummy_params().json(), } test_gridscan3d_start_document: RunStart = { # type: ignore "uid": "d8bee3ee-f614-4e7a-a516-25d6b9e87ef3", @@ -58,7 +55,7 @@ class TestData: "plan_type": "generator", "plan_name": "test", "subplan_name": CONST.PLAN.GRID_DETECT_AND_DO_GRIDSCAN, - "hyperion_internal_parameters": dummy_params().old_parameters().json(), + "hyperion_parameters": dummy_params().json(), } test_gridscan2d_start_document = { "uid": "d8bee3ee-f614-4e7a-a516-25d6b9e87ef3", @@ -68,7 +65,7 @@ class TestData: "plan_type": "generator", "plan_name": "test", "subplan_name": CONST.PLAN.GRID_DETECT_AND_DO_GRIDSCAN, - "hyperion_internal_parameters": dummy_params_2d().json(), + "hyperion_parameters": dummy_params_2d().json(), } test_rotation_start_main_document = { "uid": "2093c941-ded1-42c4-ab74-ea99980fbbfd", @@ -83,7 +80,7 @@ class TestData: "plan_name": CONST.PLAN.GRIDSCAN_OUTER, "subplan_name": CONST.PLAN.GRIDSCAN_OUTER, CONST.TRIGGER.ZOCALO: CONST.PLAN.DO_FGS, - "hyperion_internal_parameters": dummy_params().old_parameters().json(), + "hyperion_parameters": dummy_params().json(), } test_rotation_event_document_during_data_collection: Event = { "descriptor": "bd45c2e5-2b85-4280-95d7-a9a15800a78b", @@ -197,6 +194,12 @@ class TestData: "s4_slit_gaps_ygap": 0.2345, "synchrotron-synchrotron_mode": SynchrotronMode.USER, "undulator-current_gap": 1.234, + "aperture_scatterguard-selected_aperture": { + "name": "Medium", + "GDA_name": "MEDIUM", + "radius_microns": 50, + "location": (15, 16, 2, 18, 19), + }, }, "timestamps": {"det1": 1666604299.8220396, "det2": 1666604299.8235943}, "seq_num": 1, diff --git a/tests/unit_tests/external_interaction/callbacks/rotation/test_ispyb_callback.py b/tests/unit_tests/external_interaction/callbacks/rotation/test_ispyb_callback.py index e095a4078..672d9acfa 100644 --- a/tests/unit_tests/external_interaction/callbacks/rotation/test_ispyb_callback.py +++ b/tests/unit_tests/external_interaction/callbacks/rotation/test_ispyb_callback.py @@ -24,15 +24,11 @@ "axisstart": 0.0, "axisrange": 0.1, "axisend": 180, - "focal_spot_size_at_samplex": 1.0, - "focal_spot_size_at_sampley": 1.0, - "beamsize_at_samplex": 1, - "beamsize_at_sampley": 1, "comments": "Hyperion rotation scan", - "data_collection_number": 0, + "data_collection_number": 1, "detector_distance": 100.0, "exp_time": 0.1, - "imgdir": "/tmp/", + "imgdir": "/tmp/dls/i03/data/2024/cm31105-4/auto/123456/", "imgprefix": "file_name", "imgsuffix": "h5", "n_passes": 1, @@ -46,9 +42,9 @@ "xtal_snapshot3": "test_3_y", "synchrotron_mode": None, "starttime": EXPECTED_START_TIME, - "filetemplate": "file_name_0_master.h5", + "filetemplate": "file_name_1_master.h5", "nimages": 1800, - "kappastart": 0, + "kappastart": None, } @@ -109,6 +105,10 @@ def test_hardware_read_events( "slitgapvertical": 0.2345, "synchrotronmode": "User", "undulatorgap1": 1.234, + "focal_spot_size_at_samplex": 50.0, + "focal_spot_size_at_sampley": 20.0, + "beamsize_at_samplex": 50.0, + "beamsize_at_sampley": 20.0, }, ) assert_upsert_call_with( @@ -116,9 +116,9 @@ def test_hardware_read_events( mx.get_dc_position_params(), { "id": TEST_DATA_COLLECTION_IDS[0], - "pos_x": dummy_rotation_params.hyperion_params.ispyb_params.position[0], - "pos_y": dummy_rotation_params.hyperion_params.ispyb_params.position[1], - "pos_z": dummy_rotation_params.hyperion_params.ispyb_params.position[2], + "pos_x": dummy_rotation_params.ispyb_params.position[0], + "pos_y": dummy_rotation_params.ispyb_params.position[1], + "pos_z": dummy_rotation_params.ispyb_params.position[2], }, ) diff --git a/tests/unit_tests/external_interaction/callbacks/rotation/test_ispyb_mapping.py b/tests/unit_tests/external_interaction/callbacks/rotation/test_ispyb_mapping.py index 7e5c8216f..05345ef29 100644 --- a/tests/unit_tests/external_interaction/callbacks/rotation/test_ispyb_mapping.py +++ b/tests/unit_tests/external_interaction/callbacks/rotation/test_ispyb_mapping.py @@ -9,12 +9,6 @@ def test_populate_data_collection_info_for_rotation_checks_snapshots( dummy_rotation_params, ): with patch("hyperion.log.ISPYB_LOGGER.warning", autospec=True) as warning: - dummy_rotation_params.hyperion_params.ispyb_params.xtal_snapshots_omega_start = ( - None - ) - populate_data_collection_info_for_rotation( - dummy_rotation_params.hyperion_params.ispyb_params, - dummy_rotation_params.hyperion_params.detector_params, - dummy_rotation_params, - ) + dummy_rotation_params.ispyb_extras.xtal_snapshots_omega_start = None + populate_data_collection_info_for_rotation(dummy_rotation_params) warning.assert_called_once_with("No xtal snapshot paths sent to ISPyB!") diff --git a/tests/unit_tests/external_interaction/callbacks/test_rotation_callbacks.py b/tests/unit_tests/external_interaction/callbacks/test_rotation_callbacks.py index 8c13a8619..359698b6a 100644 --- a/tests/unit_tests/external_interaction/callbacks/test_rotation_callbacks.py +++ b/tests/unit_tests/external_interaction/callbacks/test_rotation_callbacks.py @@ -41,9 +41,6 @@ ) from hyperion.parameters.components import IspybExperimentType from hyperion.parameters.constants import CONST -from hyperion.parameters.plan_specific.rotation_scan_internal_params import ( - RotationInternalParameters, -) from hyperion.parameters.rotation import RotationScan from ....conftest import raw_params_from_file @@ -51,7 +48,7 @@ @pytest.fixture def params(): - return RotationInternalParameters( + return RotationScan( **raw_params_from_file( "tests/test_data/parameter_json_files/good_test_rotation_scan_parameters.json" ) @@ -59,10 +56,10 @@ def params(): @pytest.fixture -def test_outer_start_doc(params: RotationInternalParameters): +def test_outer_start_doc(params: RotationScan): return { "subplan_name": CONST.PLAN.ROTATION_OUTER, - "hyperion_internal_parameters": params.json(), + "hyperion_parameters": params.json(), } @@ -80,7 +77,7 @@ def activate_callbacks(cbs: Tuple[RotationNexusFileCallback, RotationISPyBCallba def fake_rotation_scan( - params: RotationInternalParameters, + params: RotationScan, subscriptions: ( Tuple[RotationNexusFileCallback, RotationISPyBCallback] | Sequence[PlanReactiveCallback] @@ -99,7 +96,7 @@ def fake_rotation_scan( @bpp.run_decorator( # attach experiment metadata to the start document md={ "subplan_name": CONST.PLAN.ROTATION_OUTER, - "hyperion_internal_parameters": params.json(), + "hyperion_parameters": params.json(), CONST.TRIGGER.ZOCALO: CONST.PLAN.ROTATION_MAIN, } ) @@ -112,7 +109,7 @@ def plan(): md={ "subplan_name": CONST.PLAN.ROTATION_MAIN, "zocalo_environment": "dev_zocalo", - "scan_points": [params.get_scan_points()], + "scan_points": [params.scan_points], } ) def fake_main_plan(): @@ -145,7 +142,7 @@ def activated_mocked_cbs(): def test_nexus_handler_gets_documents_in_mock_plan( ispyb, RE: RunEngine, - params: RotationInternalParameters, + params: RotationScan, activated_mocked_cbs: Tuple[RotationNexusFileCallback, RotationISPyBCallback], ): nexus_handler, _ = activated_mocked_cbs @@ -153,7 +150,7 @@ def test_nexus_handler_gets_documents_in_mock_plan( assert nexus_handler.activity_gated_start.call_count == 2 # type: ignore call_content_outer = nexus_handler.activity_gated_start.call_args_list[0].args[0] # type: ignore - assert call_content_outer["hyperion_internal_parameters"] == params.json() + assert call_content_outer["hyperion_parameters"] == params.json() call_content_inner = nexus_handler.activity_gated_start.call_args_list[1].args[0] # type: ignore assert call_content_inner["subplan_name"] == CONST.PLAN.ROTATION_MAIN @@ -167,7 +164,7 @@ def test_nexus_handler_gets_documents_in_mock_plan( def test_nexus_handler_only_writes_once( nexus_writer: MagicMock, RE: RunEngine, - params: RotationInternalParameters, + params: RotationScan, test_outer_start_doc, ): nexus_writer.return_value.full_filename = "test_full_filename" @@ -180,22 +177,23 @@ def test_nexus_handler_only_writes_once( def test_nexus_handler_triggers_write_file_when_told( - RE: RunEngine, params: RotationInternalParameters + RE: RunEngine, params: RotationScan ): - if os.path.isfile("/tmp/file_name_0.nxs"): - os.remove("/tmp/file_name_0.nxs") - if os.path.isfile("/tmp/file_name_0_master.h5"): - os.remove("/tmp/file_name_0_master.h5") + pattern = f"{params.storage_directory}{params.file_name}_{params.detector_params.run_number}" + files = [f"{pattern}.nxs", f"{pattern}_master.h5"] + + def do_files(do_assert=False): + for file in files: + if do_assert: + assert os.path.isfile(file) + if os.path.isfile(file): + os.remove(file) + do_files() cb = RotationNexusFileCallback() cb.active = True - RE(fake_rotation_scan(params, [cb])) - - assert os.path.isfile("/tmp/file_name_0.nxs") - assert os.path.isfile("/tmp/file_name_0_master.h5") - os.remove("/tmp/file_name_0.nxs") - os.remove("/tmp/file_name_0_master.h5") + do_files(do_assert=True) @patch( @@ -215,7 +213,7 @@ def test_zocalo_start_and_end_not_triggered_if_ispyb_ids_not_present( zocalo_trigger, nexus_writer, RE: RunEngine, - params: RotationInternalParameters, + params: RotationScan, test_outer_start_doc, ): nexus_writer.return_value.full_filename = "test_full_filename" @@ -243,7 +241,7 @@ def test_ispyb_starts_on_opening_and_zocalo_on_main_so_ispyb_triggered_before_zo zocalo_trigger, nexus_writer, RE: RunEngine, - params: RotationInternalParameters, + params: RotationScan, test_outer_start_doc, test_main_start_doc, ): @@ -284,7 +282,7 @@ def after_main_do( autospec=True, ) def test_ispyb_handler_grabs_uid_from_main_plan_and_not_first_start_doc( - zocalo, RE: RunEngine, params: RotationInternalParameters, test_outer_start_doc + zocalo, RE: RunEngine, params: RotationScan, test_outer_start_doc ): (nexus_callback, ispyb_callback) = create_rotation_callbacks() ispyb_callback.emit_cb = None @@ -328,7 +326,7 @@ def after_main_do( def test_ispyb_reuses_dcgid_on_same_sampleID( rotation_ispyb: MagicMock, RE: RunEngine, - params: RotationInternalParameters, + params: RotationScan, ): ispyb_cb = RotationISPyBCallback() ispyb_cb.active = True @@ -336,14 +334,14 @@ def test_ispyb_reuses_dcgid_on_same_sampleID( rotation_ispyb.return_value.begin_deposition.return_value = ispyb_ids test_cases = zip( - ["abc", "abc", "abc", "def", "abc", "def", "def", "xyz", "hij", "hij", "hij"], + [123, 123, 123, 456, 123, 456, 456, 999, 789, 789, 789], [False, True, True, False, False, False, True, False, False, True, True], ) last_dcgid = None for sample_id, same_dcgid in test_cases: - params.hyperion_params.ispyb_params.sample_id = sample_id + params.sample_id = sample_id def after_open_do(callbacks: list[RotationISPyBCallback]): assert callbacks[0].uid_to_finalize_on is None @@ -367,69 +365,6 @@ def after_main_do(callbacks: list[RotationISPyBCallback]): last_dcgid = ispyb_cb.ispyb_ids.data_collection_group_id -@patch( - "hyperion.external_interaction.callbacks.rotation.ispyb_callback.StoreInIspyb", - autospec=True, -) -def test_ispyb_specifies_experiment_type_if_supplied( - rotation_ispyb: MagicMock, - RE: RunEngine, -): - raw_params = raw_params_from_file( - "tests/test_data/parameter_json_files/good_test_rotation_scan_parameters.json" - ) - raw_params["hyperion_params"]["ispyb_params"][ - "ispyb_experiment_type" - ] = "Characterization" - params = RotationInternalParameters(**raw_params) - - ispyb_cb = RotationISPyBCallback() - ispyb_cb.active = True - assert ( - params.hyperion_params.ispyb_params.ispyb_experiment_type == "Characterization" - ) - rotation_ispyb.return_value.begin_deposition.return_value = IspybIds( - data_collection_group_id=23, data_collection_ids=(45,) - ) - - params.hyperion_params.ispyb_params.sample_id = "abc" - - RE(fake_rotation_scan(params, [ispyb_cb])) - - assert rotation_ispyb.call_args.args[1] == IspybExperimentType.CHARACTERIZATION - - -@patch( - "hyperion.external_interaction.callbacks.rotation.ispyb_callback.StoreInIspyb", - autospec=True, -) -def test_new_params_ispyb_specifies_experiment_type_if_supplied( - rotation_ispyb: MagicMock, - RE: RunEngine, -): - raw_params = raw_params_from_file( - "tests/test_data/new_parameter_json_files/good_test_rotation_scan_parameters_nomove.json" - ) - raw_params["ispyb_experiment_type"] = "Characterization" - new_params = RotationScan(**raw_params) - params = new_params.old_parameters() - - ispyb_cb = RotationISPyBCallback() - ispyb_cb.active = True - assert ( - params.hyperion_params.ispyb_params.ispyb_experiment_type == "Characterization" - ) - rotation_ispyb.return_value.begin_deposition.return_value = IspybIds( - data_collection_group_id=23, data_collection_ids=(45,) - ) - - params.hyperion_params.ispyb_params.sample_id = "abc" - - RE(fake_rotation_scan(params, [ispyb_cb])) - - assert rotation_ispyb.call_args.args[1] == IspybExperimentType.CHARACTERIZATION - - n_images_store_id = [ (123, False), (3600, True), @@ -457,7 +392,7 @@ def test_new_params_ispyb_specifies_experiment_type_if_supplied( def test_ispyb_handler_stores_sampleid_for_full_collection_not_screening( n_images: int, store_id: bool, - params: RotationInternalParameters, + params: RotationScan, ): cb = RotationISPyBCallback() cb.active = True @@ -467,11 +402,13 @@ def test_ispyb_handler_stores_sampleid_for_full_collection_not_screening( "uid": "abc123", } - params.hyperion_params.ispyb_params.sample_id = "SAMPLEID" - params.experiment_params.rotation_angle = n_images / 10 - assert params.experiment_params.get_num_images() == n_images + params.sample_id = 987678 + params.scan_width_deg = n_images / 10 + if n_images < 200: + params.ispyb_experiment_type = IspybExperimentType.CHARACTERIZATION + assert params.num_images == n_images doc["subplan_name"] = CONST.PLAN.ROTATION_OUTER # type: ignore - doc["hyperion_internal_parameters"] = params.json() # type: ignore + doc["hyperion_parameters"] = params.json() # type: ignore cb.start(doc) - assert (cb.last_sample_id == "SAMPLEID") is store_id + assert (cb.last_sample_id == 987678) is store_id diff --git a/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_callback.py b/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_callback.py index e1449a7f1..5a8bb9edf 100644 --- a/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_callback.py +++ b/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_callback.py @@ -23,10 +23,6 @@ "axisstart": 0.0, "axisrange": 0, "axisend": 0, - "focal_spot_size_at_samplex": 0.0, - "focal_spot_size_at_sampley": 0.0, - "beamsize_at_samplex": 0.1, - "beamsize_at_sampley": 0.1, "data_collection_number": 1, "detector_distance": 100.0, "exp_time": 0.1, @@ -55,37 +51,6 @@ "filetemplate": "file_name_2_master.h5", } -EXPECTED_DATA_COLLECTION_2D = { - "visitid": TEST_SESSION_ID, - "parentid": TEST_DATA_COLLECTION_GROUP_ID, - "sampleid": TEST_SAMPLE_ID, - "detectorid": 78, - "axisstart": 0.0, - "axisrange": 0, - "axisend": 0, - "focal_spot_size_at_samplex": 0.0, - "focal_spot_size_at_sampley": 0.0, - "beamsize_at_samplex": 0.1, - "beamsize_at_sampley": 0.1, - "data_collection_number": 0, - "detector_distance": 100.0, - "exp_time": 0.1, - "imgdir": "/tmp/", - "imgprefix": "file_name", - "imgsuffix": "h5", - "n_passes": 1, - "overlap": 0, - "omegastart": 0, - "start_image_number": 1, - "wavelength": None, - "xbeam": 150.0, - "ybeam": 160.0, - "synchrotron_mode": None, - "undulator_gap1": None, - "starttime": EXPECTED_START_TIME, - "filetemplate": "file_name_0_master.h5", -} - @patch( "hyperion.external_interaction.callbacks.common.ispyb_mapping.get_current_time_string", @@ -143,6 +108,10 @@ def test_hardware_read_event_3d(self, mock_ispyb_conn): "slitgapvertical": 0.2345, "synchrotronmode": "User", "undulatorgap1": 1.234, + "focal_spot_size_at_samplex": 50.0, + "focal_spot_size_at_sampley": 20.0, + "beamsize_at_samplex": 50.0, + "beamsize_at_sampley": 20.0, }, ) assert_upsert_call_with( @@ -155,6 +124,10 @@ def test_hardware_read_event_3d(self, mock_ispyb_conn): "slitgapvertical": 0.2345, "synchrotronmode": "User", "undulatorgap1": 1.234, + "focal_spot_size_at_samplex": 50.0, + "focal_spot_size_at_sampley": 20.0, + "beamsize_at_samplex": 50.0, + "beamsize_at_sampley": 20.0, }, ) diff --git a/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_mapping.py b/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_mapping.py index df8d2b7fb..0a273043e 100644 --- a/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_mapping.py +++ b/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_mapping.py @@ -7,9 +7,7 @@ ) from hyperion.external_interaction.ispyb.data_model import DataCollectionGridInfo from hyperion.external_interaction.ispyb.ispyb_dataclass import Orientation -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanInternalParameters, -) +from hyperion.parameters.gridscan import ThreeDGridScan from ...conftest import ( TEST_SAMPLE_ID, @@ -19,9 +17,9 @@ @pytest.fixture def dummy_params(): - dummy_params = GridscanInternalParameters(**default_raw_params()) - dummy_params.hyperion_params.ispyb_params.sample_id = TEST_SAMPLE_ID - dummy_params.hyperion_params.detector_params.run_number = 0 + dummy_params = ThreeDGridScan(**default_raw_params()) + dummy_params.sample_id = TEST_SAMPLE_ID + dummy_params.run_number = 0 return dummy_params @@ -67,7 +65,7 @@ def test_ispyb_deposition_rounds_position_to_int( ) def test_ispyb_deposition_rounds_box_size_int( bottom_right_from_top_left: MagicMock, - dummy_params: GridscanInternalParameters, + dummy_params: ThreeDGridScan, raw, rounded, ): diff --git a/tests/unit_tests/external_interaction/conftest.py b/tests/unit_tests/external_interaction/conftest.py index 6e56d6b88..f4fa60ae7 100644 --- a/tests/unit_tests/external_interaction/conftest.py +++ b/tests/unit_tests/external_interaction/conftest.py @@ -1,3 +1,4 @@ +import glob import os from copy import deepcopy from typing import Any, Callable, Sequence @@ -13,12 +14,8 @@ from hyperion.external_interaction.callbacks.plan_reactive_callback import ( PlanReactiveCallback, ) -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanInternalParameters, -) -from hyperion.parameters.plan_specific.rotation_scan_internal_params import ( - RotationInternalParameters, -) +from hyperion.parameters.gridscan import ThreeDGridScan +from hyperion.parameters.rotation import RotationScan from hyperion.utils.utils import convert_angstrom_to_eV from ...conftest import raw_params_from_file @@ -68,30 +65,33 @@ def test_rotation_params(): param_dict = raw_params_from_file( "tests/test_data/parameter_json_files/good_test_rotation_scan_parameters.json" ) - param_dict["hyperion_params"]["detector_params"]["directory"] = "tests/test_data" - param_dict["hyperion_params"]["detector_params"]["prefix"] = "TEST_FILENAME" - param_dict["hyperion_params"]["detector_params"]["expected_energy_ev"] = 12700 - param_dict["experiment_params"]["rotation_angle"] = 360.0 - params = RotationInternalParameters(**param_dict) - params.experiment_params.x = 0 - params.experiment_params.y = 0 - params.experiment_params.z = 0 - params.hyperion_params.detector_params.exposure_time = 0.004 + param_dict["storage_directory"] = "tests/test_data" + param_dict["file_name"] = "TEST_FILENAME" + param_dict["demand_energy_ev"] = 12700 + param_dict["scan_width_deg"] = 360.0 + params = RotationScan(**param_dict) + params.x_start_um = 0 + params.y_start_um = 0 + params.z_start_um = 0 + params.exposure_time_s = 0.004 return params -@pytest.fixture(params=[1044]) +@pytest.fixture(params=[1050]) def test_fgs_params(request): - params = GridscanInternalParameters(**default_raw_params()) - params.hyperion_params.detector_params.expected_energy_ev = convert_angstrom_to_eV( - 1.0 - ) - params.hyperion_params.detector_params.use_roi_mode = True - params.hyperion_params.detector_params.num_triggers = request.param - params.hyperion_params.detector_params.directory = ( + assert request.param % 25 == 0, "Please use a multiple of 25 images" + params = ThreeDGridScan(**default_raw_params()) + params.demand_energy_ev = convert_angstrom_to_eV(1.0) + params.use_roi_mode = True + first_scan_img = (request.param // 10) * 6 + second_scan_img = (request.param // 10) * 4 + params.x_steps = 5 + params.y_steps = first_scan_img // 5 + params.z_steps = second_scan_img // 5 + params.storage_directory = ( os.path.dirname(os.path.realpath(__file__)) + "/test_data" ) - params.hyperion_params.detector_params.prefix = "dummy" + params.file_name = "dummy" yield params @@ -179,20 +179,28 @@ def mock_retrieve_visit(visit_str): @pytest.fixture def dummy_rotation_params(): - dummy_params = RotationInternalParameters( + dummy_params = RotationScan( **default_raw_params( "tests/test_data/parameter_json_files/good_test_rotation_scan_parameters.json" ) ) - dummy_params.hyperion_params.ispyb_params.sample_id = TEST_SAMPLE_ID - return dummy_params + dummy_params.sample_id = TEST_SAMPLE_ID + + def clear_files(): + files = glob.glob(f"{dummy_params.storage_directory}*") + for f in files: + os.remove(f) + + clear_files() + yield dummy_params + clear_files() -TEST_SAMPLE_ID = "364758" +TEST_SAMPLE_ID = 364758 TEST_BARCODE = "12345A" def default_raw_params( - json_file="tests/test_data/parameter_json_files/test_internal_parameter_defaults.json", + json_file="tests/test_data/parameter_json_files/good_test_parameters.json", ): return raw_params_from_file(json_file) diff --git a/tests/unit_tests/external_interaction/ispyb/conftest.py b/tests/unit_tests/external_interaction/ispyb/conftest.py index 99078a372..243902b22 100644 --- a/tests/unit_tests/external_interaction/ispyb/conftest.py +++ b/tests/unit_tests/external_interaction/ispyb/conftest.py @@ -9,11 +9,8 @@ ) from hyperion.external_interaction.ispyb.ispyb_dataclass import Orientation from hyperion.external_interaction.ispyb.ispyb_store import StoreInIspyb -from hyperion.parameters.components import IspybExperimentType from hyperion.parameters.constants import CONST -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanInternalParameters, -) +from hyperion.parameters.gridscan import ThreeDGridScan from ..conftest import ( TEST_DATA_COLLECTION_GROUP_ID, @@ -25,29 +22,27 @@ @pytest.fixture def dummy_params(): - dummy_params = GridscanInternalParameters(**default_raw_params()) - dummy_params.hyperion_params.ispyb_params.sample_id = TEST_SAMPLE_ID - dummy_params.hyperion_params.detector_params.run_number = 0 + dummy_params = ThreeDGridScan(**default_raw_params()) + dummy_params.sample_id = TEST_SAMPLE_ID + dummy_params.run_number = 0 return dummy_params @pytest.fixture def dummy_3d_gridscan_ispyb(): - store_in_ispyb_3d = StoreInIspyb( - CONST.SIM.ISPYB_CONFIG, IspybExperimentType.GRIDSCAN_3D - ) + store_in_ispyb_3d = StoreInIspyb(CONST.SIM.ISPYB_CONFIG) return store_in_ispyb_3d @pytest.fixture def dummy_rotation_ispyb(dummy_rotation_params): - store_in_ispyb = StoreInIspyb(CONST.SIM.ISPYB_CONFIG, IspybExperimentType.ROTATION) + store_in_ispyb = StoreInIspyb(CONST.SIM.ISPYB_CONFIG) return store_in_ispyb @pytest.fixture def dummy_2d_gridscan_ispyb(): - return StoreInIspyb(CONST.SIM.ISPYB_CONFIG, IspybExperimentType.GRIDSCAN_2D) + return StoreInIspyb(CONST.SIM.ISPYB_CONFIG) @pytest.fixture diff --git a/tests/unit_tests/external_interaction/ispyb/test_gridscan_ispyb_store_3d.py b/tests/unit_tests/external_interaction/ispyb/test_gridscan_ispyb_store_3d.py index db2a8d02d..263753683 100644 --- a/tests/unit_tests/external_interaction/ispyb/test_gridscan_ispyb_store_3d.py +++ b/tests/unit_tests/external_interaction/ispyb/test_gridscan_ispyb_store_3d.py @@ -37,7 +37,7 @@ def dummy_collection_group_info(): return DataCollectionGroupInfo( visit_string="cm31105-4", experiment_type="Mesh3D", - sample_id="364758", + sample_id=364758, ) @@ -56,7 +56,7 @@ def scan_data_info_for_begin(): kappa_start=None, parent_id=None, visit_string="cm31105-4", - sample_id="364758", + sample_id=364758, detector_id=78, axis_start=0.0, focal_spot_size_at_samplex=0.0, @@ -104,7 +104,7 @@ def scan_data_infos_for_update(): kappa_start=None, parent_id=34, visit_string="cm31105-4", - sample_id="364758", + sample_id=364758, detector_id=78, axis_start=0.0, focal_spot_size_at_samplex=0.0, @@ -162,7 +162,7 @@ def scan_data_infos_for_update(): kappa_start=None, parent_id=34, visit_string="cm31105-4", - sample_id="364758", + sample_id=364758, detector_id=78, axis_start=90.0, focal_spot_size_at_samplex=0.0, @@ -263,15 +263,12 @@ def test_store_3d_grid_scan( scan_data_info_for_begin, scan_data_infos_for_update, ): - assert dummy_3d_gridscan_ispyb.experiment_type == "Mesh3D" - ispyb_ids = dummy_3d_gridscan_ispyb.begin_deposition( dummy_collection_group_info, [scan_data_info_for_begin] ) assert ispyb_ids == IspybIds( data_collection_ids=(TEST_DATA_COLLECTION_IDS[0],), data_collection_group_id=TEST_DATA_COLLECTION_GROUP_ID, - data_collection_id=TEST_DATA_COLLECTION_IDS[0], ) assert dummy_3d_gridscan_ispyb.update_deposition( @@ -695,7 +692,7 @@ def test_given_real_sampleid_when_grid_scan_stored_then_sample_id_set( scan_data_info_for_begin, scan_xy_data_info_for_update, ): - expected_sample_id = "364758" + expected_sample_id = 364758 def test_sample_id(default_params, actual): sampleid_idx = list(default_params).index("sampleid") diff --git a/tests/unit_tests/external_interaction/ispyb/test_rotation_ispyb_store.py b/tests/unit_tests/external_interaction/ispyb/test_rotation_ispyb_store.py index 00c8fe2a7..5f4751482 100644 --- a/tests/unit_tests/external_interaction/ispyb/test_rotation_ispyb_store.py +++ b/tests/unit_tests/external_interaction/ispyb/test_rotation_ispyb_store.py @@ -12,7 +12,6 @@ IspybIds, StoreInIspyb, ) -from hyperion.parameters.components import IspybExperimentType from hyperion.parameters.constants import CONST from ..conftest import ( @@ -70,7 +69,7 @@ def dummy_rotation_data_collection_group_info(): return DataCollectionGroupInfo( visit_string="cm31105-4", experiment_type="SAD", - sample_id="364758", + sample_id=364758, ) @@ -93,7 +92,7 @@ def scan_data_info_for_begin(): kappa_start=0.0, parent_id=None, visit_string="cm31105-4", - sample_id="364758", + sample_id=364758, detector_id=78, axis_start=0.0, focal_spot_size_at_samplex=1.0, @@ -176,9 +175,7 @@ def scan_data_info_for_update(scan_data_info_for_begin): @pytest.fixture def dummy_rotation_ispyb_with_experiment_type(): - store_in_ispyb = StoreInIspyb( - CONST.SIM.ISPYB_CONFIG, IspybExperimentType.CHARACTERIZATION - ) + store_in_ispyb = StoreInIspyb(CONST.SIM.ISPYB_CONFIG) return store_in_ispyb @@ -232,9 +229,7 @@ def test_begin_deposition_with_group_id_updates_but_doesnt_insert( dummy_rotation_data_collection_group_info, scan_data_info_for_begin, ): - dummy_rotation_ispyb = StoreInIspyb( - CONST.SIM.ISPYB_CONFIG, IspybExperimentType.ROTATION - ) + dummy_rotation_ispyb = StoreInIspyb(CONST.SIM.ISPYB_CONFIG) scan_data_info_for_begin.data_collection_info.parent_id = ( TEST_DATA_COLLECTION_GROUP_ID ) @@ -365,9 +360,7 @@ def test_update_deposition_with_group_id_updates( scan_data_info_for_begin, scan_data_info_for_update, ): - dummy_rotation_ispyb = StoreInIspyb( - CONST.SIM.ISPYB_CONFIG, IspybExperimentType.ROTATION - ) + dummy_rotation_ispyb = StoreInIspyb(CONST.SIM.ISPYB_CONFIG) scan_data_info_for_begin.data_collection_info.parent_id = ( TEST_DATA_COLLECTION_GROUP_ID ) @@ -492,7 +485,7 @@ def test_store_rotation_scan_uses_supplied_dcgid( mock_ispyb_conn.return_value.mx_acquisition.upsert_data_collection_group.return_value = ( dcgid ) - store_in_ispyb = StoreInIspyb(CONST.SIM.ISPYB_CONFIG, IspybExperimentType.ROTATION) + store_in_ispyb = StoreInIspyb(CONST.SIM.ISPYB_CONFIG) scan_data_info_for_begin.data_collection_info.parent_id = dcgid ispyb_ids = store_in_ispyb.begin_deposition( dummy_rotation_data_collection_group_info, [scan_data_info_for_begin] diff --git a/tests/unit_tests/external_interaction/nexus/test_write_nexus.py b/tests/unit_tests/external_interaction/nexus/test_write_nexus.py index 591f2ad14..a320f064c 100644 --- a/tests/unit_tests/external_interaction/nexus/test_write_nexus.py +++ b/tests/unit_tests/external_interaction/nexus/test_write_nexus.py @@ -6,15 +6,17 @@ import h5py import numpy as np import pytest +from dodal.devices.detector.det_dim_constants import ( + PIXELS_X_EIGER2_X_4M, + PIXELS_Y_EIGER2_X_4M, +) from dodal.devices.fast_grid_scan import GridAxis, GridScanParams from hyperion.external_interaction.nexus.nexus_utils import ( create_beam_and_attenuator_parameters, ) from hyperion.external_interaction.nexus.write_nexus import NexusWriter -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanInternalParameters, -) +from hyperion.parameters.gridscan import ThreeDGridScan """It's hard to effectively unit test the nexus writing so these are really system tests that confirms that we're passing the right sorts of data to nexgen to get a sensible output. @@ -31,49 +33,67 @@ def assert_end_data_correct(nexus_writer: NexusWriter): assert "end_time_estimated" in entry -def create_nexus_writer(parameters, writer_num): - nexus_writer = NexusWriter(parameters, **parameters.get_nexus_info(writer_num)) +def create_nexus_writer(parameters: ThreeDGridScan, writer_num): + d_size = parameters.detector_params.detector_size_constants.det_size_pixels + n_img = ( + parameters.scan_indices[1] + if writer_num == 1 + else parameters.num_images - parameters.scan_indices[1] + ) + points = ( + parameters.scan_points_first_grid + if writer_num == 1 + else parameters.scan_points_second_grid + ) + data_shape = (n_img, d_size.width, d_size.height) + run_number = parameters.detector_params.run_number + writer_num - 1 + vds_start = 0 if writer_num == 1 else parameters.scan_indices[1] + omega_start = ( + parameters.grid1_omega_deg if writer_num == 1 else parameters.grid2_omega_deg + ) + nexus_writer = NexusWriter( + parameters, + data_shape, + scan_points=points, + run_number=run_number, + vds_start_index=vds_start, + omega_start_deg=omega_start, + ) nexus_writer.beam, nexus_writer.attenuator = create_beam_and_attenuator_parameters( 20, TEST_FLUX, 0.5 ) return nexus_writer -@pytest.fixture -def dummy_nexus_writers(test_fgs_params: GridscanInternalParameters): - writers = [create_nexus_writer(test_fgs_params, i) for i in [1, 2]] - writers[1].start_index = test_fgs_params.get_nexus_info(1)["data_shape"][0] - - yield writers - - for writer in writers: - os.remove(writer.nexus_file) - os.remove(writer.master_file) - - @contextmanager -def create_nexus_writers_with_many_images(parameters: GridscanInternalParameters): - x, y, z = 45, 35, 25 - parameters.experiment_params.x_steps = x - parameters.experiment_params.y_steps = y - parameters.experiment_params.z_steps = z - parameters.hyperion_params.detector_params.num_triggers = x * y + x * z - +def create_nexus_writers(parameters: ThreeDGridScan): writers = [create_nexus_writer(parameters, i) for i in [1, 2]] - writers[1].start_index = parameters.get_nexus_info(1)["data_shape"][0] - + writers[1].start_index = parameters.scan_indices[1] try: yield writers - finally: for writer in writers: - os.remove(writer.nexus_file) - os.remove(writer.master_file) + for file in [writer.nexus_file, writer.master_file]: + if os.path.isfile(file): + os.remove(file) + + +@pytest.fixture +def dummy_nexus_writers(test_fgs_params: ThreeDGridScan): + with create_nexus_writers(test_fgs_params) as ( + nexus_writer_1, + nexus_writer_2, + ): + yield nexus_writer_1, nexus_writer_2 @pytest.fixture -def dummy_nexus_writers_with_more_images(test_fgs_params: GridscanInternalParameters): - with create_nexus_writers_with_many_images(test_fgs_params) as ( +def dummy_nexus_writers_with_more_images(test_fgs_params: ThreeDGridScan): + x, y, z = 45, 35, 25 + test_fgs_params.x_steps = x + test_fgs_params.y_steps = y + test_fgs_params.z_steps = z + with create_nexus_writers(test_fgs_params) as ( nexus_writer_1, nexus_writer_2, ): @@ -81,8 +101,16 @@ def dummy_nexus_writers_with_more_images(test_fgs_params: GridscanInternalParame @pytest.fixture -def single_dummy_file(test_fgs_params: GridscanInternalParameters): - nexus_writer = NexusWriter(test_fgs_params, **test_fgs_params.get_nexus_info(1)) +def single_dummy_file(test_fgs_params: ThreeDGridScan): + test_fgs_params.use_roi_mode = True + d_size = test_fgs_params.detector_params.detector_size_constants.det_size_pixels + data_shape = (test_fgs_params.scan_indices[1], d_size.width, d_size.height) + nexus_writer = NexusWriter( + test_fgs_params, + data_shape, + scan_points=test_fgs_params.scan_points_first_grid, + run_number=1, + ) yield nexus_writer for file in [nexus_writer.nexus_file, nexus_writer.master_file]: if os.path.isfile(file): @@ -91,33 +119,33 @@ def single_dummy_file(test_fgs_params: GridscanInternalParameters): @pytest.mark.parametrize( "test_fgs_params, expected_num_of_files", - [(2540, 3), (4000, 4), (8999, 9)], + [(2550, 3), (4000, 4), (8975, 9)], indirect=["test_fgs_params"], ) def test_given_number_of_images_above_1000_then_expected_datafiles_used( - test_fgs_params: GridscanInternalParameters, + test_fgs_params: ThreeDGridScan, expected_num_of_files: Literal[3, 4, 9], single_dummy_file: NexusWriter, ): - first_writer = single_dummy_file - assert len(first_writer.get_image_datafiles()) == expected_num_of_files - paths = [str(filename) for filename in first_writer.get_image_datafiles()] + datafiles = single_dummy_file.get_image_datafiles() + assert len(datafiles) == expected_num_of_files + paths = [str(filename) for filename in datafiles] test_data_folder = ( os.path.dirname(os.path.realpath(os.path.join(__file__, ".."))) + "/test_data" ) expected_paths = [ - f"{test_data_folder}/dummy_0_00000{i + 1}.h5" + f"{test_data_folder}/dummy_1_00000{i + 1}.h5" for i in range(expected_num_of_files) ] assert expected_paths[0] == paths[0] def test_given_dummy_data_then_datafile_written_correctly( - test_fgs_params: GridscanInternalParameters, + test_fgs_params: ThreeDGridScan, dummy_nexus_writers: tuple[NexusWriter, NexusWriter], ): nexus_writer_1, nexus_writer_2 = dummy_nexus_writers - grid_scan_params: GridScanParams = test_fgs_params.experiment_params + grid_scan_params: GridScanParams = test_fgs_params.FGS_params nexus_writer_1.create_nexus_file(np.uint16) for filename in [nexus_writer_1.nexus_file, nexus_writer_1.master_file]: @@ -138,7 +166,7 @@ def test_given_dummy_data_then_datafile_written_correctly( h5py.Dataset, ) assert flux[()] == TEST_FLUX - assert_contains_external_link(data_path, "data_000001", "dummy_0_000001.h5") + assert_contains_external_link(data_path, "data_000001", "dummy_1_000001.h5") assert isinstance(omega := data_path["omega"], h5py.Dataset) assert np.all(omega[:] == 0.0) @@ -167,7 +195,7 @@ def test_given_dummy_data_then_datafile_written_correctly( ] ) - assert_data_edge_at(nexus_writer_1.nexus_file, 799) + assert_data_edge_at(nexus_writer_1.nexus_file, 629) assert_end_data_correct(nexus_writer_1) nexus_writer_2.create_nexus_file(np.uint16) @@ -190,8 +218,8 @@ def test_given_dummy_data_then_datafile_written_correctly( h5py.Dataset, ) assert flux[()] == TEST_FLUX - assert_contains_external_link(data_path, "data_000001", "dummy_0_000001.h5") - assert_contains_external_link(data_path, "data_000002", "dummy_0_000002.h5") + assert_contains_external_link(data_path, "data_000001", "dummy_1_000001.h5") + assert_contains_external_link(data_path, "data_000002", "dummy_1_000002.h5") assert isinstance(omega := data_path["omega"], h5py.Dataset) assert np.all(omega[:] == 90.0) assert np.all( @@ -203,7 +231,7 @@ def test_given_dummy_data_then_datafile_written_correctly( ] ) - assert_data_edge_at(nexus_writer_2.nexus_file, 243) + assert_data_edge_at(nexus_writer_2.nexus_file, 419) def assert_x_data_stride_correct(data_path, grid_scan_params, varying_axis_steps): @@ -222,9 +250,9 @@ def assert_varying_axis_stride_correct( def assert_axis_data_fixed(written_nexus_file, axis, expected_value): - assert f"sam_{axis}" not in written_nexus_file["/entry/data"] - sam_y_data = written_nexus_file[f"/entry/sample/sample_{axis}/sam_{axis}"][()] - assert sam_y_data == expected_value + if f"sam_{axis}" in written_nexus_file["/entry/data"]: + fixed_data = written_nexus_file["/entry/data"][f"sam_{axis}"][:] + assert sum(fixed_data) == len(fixed_data) * fixed_data[0] def assert_data_edge_at(nexus_file, expected_edge_index): @@ -242,24 +270,16 @@ def assert_contains_external_link(data_path, entry_name, file_name): def test_nexus_writer_files_are_formatted_as_expected( - test_fgs_params: GridscanInternalParameters, single_dummy_file: NexusWriter + test_fgs_params: ThreeDGridScan, single_dummy_file: NexusWriter ): for file in [single_dummy_file.nexus_file, single_dummy_file.master_file]: file_name = os.path.basename(file.name) - expected_file_name_prefix = ( - test_fgs_params.hyperion_params.detector_params.prefix + "_0" - ) + expected_file_name_prefix = test_fgs_params.file_name + "_1" assert file_name.startswith(expected_file_name_prefix) -def test_nexus_writer_writes_width_and_height_correctly( - single_dummy_file: NexusWriter, -): - from dodal.devices.detector.det_dim_constants import ( - PIXELS_X_EIGER2_X_4M, - PIXELS_Y_EIGER2_X_4M, - ) - +def test_nexus_writer_writes_width_and_height_correctly(single_dummy_file: NexusWriter): + assert len(single_dummy_file.detector.detector_params.image_size) >= 2 assert ( single_dummy_file.detector.detector_params.image_size[0] == PIXELS_Y_EIGER2_X_4M ) @@ -270,9 +290,11 @@ def test_nexus_writer_writes_width_and_height_correctly( @patch.dict(os.environ, {"BEAMLINE": "I03"}) def test_nexus_writer_writes_beamline_name_correctly( - test_fgs_params, + test_fgs_params: ThreeDGridScan, ): - nexus_writer = NexusWriter(test_fgs_params, **test_fgs_params.get_nexus_info(1)) + d_size = test_fgs_params.detector_params.detector_size_constants.det_size_pixels + data_shape = (test_fgs_params.num_images, d_size.width, d_size.height) + nexus_writer = NexusWriter(test_fgs_params, data_shape, test_fgs_params.scan_points) assert nexus_writer.source.beamline == "I03" @@ -336,10 +358,10 @@ def test_given_some_datafiles_outside_of_VDS_range_THEN_they_are_not_in_nexus_fi def test_given_data_files_not_yet_written_when_nexus_files_created_then_nexus_files_still_written( - test_fgs_params: GridscanInternalParameters, + test_fgs_params: ThreeDGridScan, ): - test_fgs_params.hyperion_params.detector_params.prefix = "non_existant_file" - with create_nexus_writers_with_many_images(test_fgs_params) as ( + test_fgs_params.file_name = "non_existant_file" + with create_nexus_writers(test_fgs_params) as ( nexus_writer_1, nexus_writer_2, ): diff --git a/tests/unit_tests/external_interaction/test_data/dummy_0_000001.h5 b/tests/unit_tests/external_interaction/test_data/dummy_1_000001.h5 similarity index 100% rename from tests/unit_tests/external_interaction/test_data/dummy_0_000001.h5 rename to tests/unit_tests/external_interaction/test_data/dummy_1_000001.h5 diff --git a/tests/unit_tests/external_interaction/test_data/dummy_0_000002.h5 b/tests/unit_tests/external_interaction/test_data/dummy_1_000002.h5 similarity index 100% rename from tests/unit_tests/external_interaction/test_data/dummy_0_000002.h5 rename to tests/unit_tests/external_interaction/test_data/dummy_1_000002.h5 diff --git a/tests/unit_tests/external_interaction/test_data/dummy_0_000003.h5 b/tests/unit_tests/external_interaction/test_data/dummy_1_000003.h5 similarity index 100% rename from tests/unit_tests/external_interaction/test_data/dummy_0_000003.h5 rename to tests/unit_tests/external_interaction/test_data/dummy_1_000003.h5 diff --git a/tests/unit_tests/external_interaction/test_write_rotation_nexus.py b/tests/unit_tests/external_interaction/test_write_rotation_nexus.py index b2836578b..23b3b031b 100644 --- a/tests/unit_tests/external_interaction/test_write_rotation_nexus.py +++ b/tests/unit_tests/external_interaction/test_write_rotation_nexus.py @@ -20,9 +20,7 @@ ) from hyperion.log import LOGGER from hyperion.parameters.constants import CONST -from hyperion.parameters.plan_specific.rotation_scan_internal_params import ( - RotationInternalParameters, -) +from hyperion.parameters.rotation import RotationScan from ...conftest import extract_metafile, raw_params_from_file @@ -37,23 +35,20 @@ def test_params(tmpdir): param_dict = raw_params_from_file( "tests/test_data/parameter_json_files/good_test_rotation_scan_parameters.json" ) - param_dict["hyperion_params"]["detector_params"]["directory"] = "tests/test_data" - param_dict["hyperion_params"]["detector_params"][ - "prefix" - ] = f"{tmpdir}/{TEST_FILENAME}" - param_dict["experiment_params"]["rotation_angle"] = 360.0 - param_dict["hyperion_params"]["detector_params"]["expected_energy_ev"] = 12700 - param_dict["experiment_params"]["rotation_angle"] = 360.0 - params = RotationInternalParameters(**param_dict) - params.experiment_params.x = 0 - params.experiment_params.y = 0 - params.experiment_params.z = 0 - params.hyperion_params.detector_params.exposure_time = 0.004 + param_dict["storage_directory"] = "tests/test_data" + param_dict["file_name"] = f"{tmpdir}/{TEST_FILENAME}" + param_dict["scan_width_deg"] = 360.0 + param_dict["demand_energy_ev"] = 12700 + params = RotationScan(**param_dict) + params.x_start_um = 0 + params.y_start_um = 0 + params.z_start_um = 0 + params.exposure_time_s = 0.004 return params def fake_rotation_scan( - parameters: RotationInternalParameters, + parameters: RotationScan, subscription: RotationNexusFileCallback, rotation_devices: RotationScanComposite, ): @@ -62,7 +57,7 @@ def fake_rotation_scan( @bpp.run_decorator( # attach experiment metadata to the start document md={ "subplan_name": CONST.PLAN.ROTATION_OUTER, - "hyperion_internal_parameters": parameters.json(), + "hyperion_parameters": parameters.json(), "activate_callbacks": "RotationNexusFileCallback", } ) @@ -110,11 +105,12 @@ def apply_metafile_mapping(exceptions: dict, mapping: dict): def test_rotation_scan_nexus_output_compared_to_existing_full_compare( - test_params: RotationInternalParameters, + test_params: RotationScan, tmpdir, fake_create_rotation_devices: RotationScanComposite, ): - run_number = test_params.hyperion_params.detector_params.run_number + test_params.chi_start_deg = 0 + run_number = test_params.detector_params.run_number nexus_filename = f"{tmpdir}/{TEST_FILENAME}_{run_number}.nxs" master_filename = f"{tmpdir}/{TEST_FILENAME}_{run_number}_master.h5" meta_filename = f"{TEST_FILENAME}_{run_number}_meta.h5" @@ -227,11 +223,11 @@ def test_rotation_scan_nexus_output_compared_to_existing_full_compare( def test_rotation_scan_nexus_output_compared_to_existing_file( - test_params: RotationInternalParameters, + test_params: RotationScan, tmpdir, fake_create_rotation_devices: RotationScanComposite, ): - run_number = test_params.hyperion_params.detector_params.run_number + run_number = test_params.run_number or test_params.detector_params.run_number nexus_filename = f"{tmpdir}/{TEST_FILENAME}_{run_number}.nxs" master_filename = f"{tmpdir}/{TEST_FILENAME}_{run_number}_master.h5" @@ -344,7 +340,7 @@ def test_rotation_scan_nexus_output_compared_to_existing_file( @patch("hyperion.external_interaction.nexus.write_nexus.NXmxFileWriter") def test_given_detector_bit_depth_changes_then_vds_datatype_as_expected( mock_nexus_writer, - test_params: RotationInternalParameters, + test_params: RotationScan, fake_create_rotation_devices: RotationScanComposite, bit_depth, expected_type, @@ -465,7 +461,7 @@ def _compare_actual_and_expected(path: list[str], actual, expected, exceptions: if callable(exception): assert exception( actual_value, expected_value - ), f"Actual and expected values differ for {item_path_str}: {actual_value_str} != {expected_value_str}" + ), f"Actual and expected values differ for {item_path_str}: {actual_value_str} != {expected_value_str}, according to {exception}" else: assert np.array_equal( actual_value, diff --git a/tests/unit_tests/hyperion/test_main_system.py b/tests/unit_tests/hyperion/test_main_system.py index cbb009269..f0838f9f8 100644 --- a/tests/unit_tests/hyperion/test_main_system.py +++ b/tests/unit_tests/hyperion/test_main_system.py @@ -30,9 +30,7 @@ from hyperion.experiment_plans.experiment_registry import PLAN_REGISTRY from hyperion.log import LOGGER from hyperion.parameters.cli import parse_cli_args -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanInternalParameters, -) +from hyperion.parameters.gridscan import ThreeDGridScan from hyperion.utils.context import device_composite_from_context from ...conftest import raw_params_from_file @@ -45,7 +43,7 @@ TEST_BAD_PARAM_ENDPOINT = "/fgs_real_params/" + Actions.START.value TEST_PARAMS = json.dumps( raw_params_from_file( - "tests/test_data/new_parameter_json_files/good_test_parameters.json" + "tests/test_data/parameter_json_files/good_test_parameters.json" ) ) @@ -114,7 +112,7 @@ def mock_dict_values(d: dict): TEST_EXPTS = { "test_experiment": { "setup": MagicMock(), - "internal_param_type": MagicMock(), + "param_type": MagicMock(), "experiment_param_type": MagicMock(), "callback_collection_type": MagicMock(), }, @@ -125,7 +123,7 @@ def mock_dict_values(d: dict): }, "fgs_real_params": { "setup": MagicMock(), - "internal_param_type": GridscanInternalParameters, + "param_type": ThreeDGridScan, "experiment_param_type": MagicMock(), "callback_collection_type": MagicMock(), }, @@ -291,7 +289,7 @@ def test_start_with_json_file_gives_success(test_env: ClientAndRunEngine): test_env.mock_run_engine.RE_takes_time = False with open( - "tests/test_data/new_parameter_json_files/good_test_parameters.json" + "tests/test_data/parameter_json_files/good_test_parameters.json" ) as test_params_file: test_params = test_params_file.read() response = test_env.client.put(START_ENDPOINT, data=test_params) @@ -348,7 +346,6 @@ def test_blueskyrunner_uses_cli_args_correctly_for_callbacks( parsed_arg_values, ): mock_params = MagicMock() - mock_params.hyperion_params.experiment_type = "test_experiment" mock_param_class = MagicMock() mock_param_class.from_json.return_value = mock_params callbacks_mock = MagicMock( @@ -359,8 +356,7 @@ def test_blueskyrunner_uses_cli_args_correctly_for_callbacks( TEST_REGISTRY = { "test_experiment": { "setup": MagicMock(), - "internal_param_type": mock_param_class, - "experiment_param_type": MagicMock(), + "param_type": mock_param_class, "callback_collection_type": callbacks_mock, } } @@ -486,25 +482,25 @@ def test_when_blueskyrunner_initiated_and_skip_flag_is_not_set_then_all_plans_se { "flyscan_xray_centre": { "setup": mock_setup, - "internal_param_type": MagicMock(), + "param_type": MagicMock(), "experiment_param_type": MagicMock(), "callback_collection_type": MagicMock(), }, "rotation_scan": { "setup": mock_setup, - "internal_param_type": MagicMock(), + "param_type": MagicMock(), "experiment_param_type": MagicMock(), "callback_collection_type": MagicMock(), }, "other_plan": { "setup": mock_setup, - "internal_param_type": MagicMock(), + "param_type": MagicMock(), "experiment_param_type": MagicMock(), "callback_collection_type": MagicMock(), }, "yet_another_plan": { "setup": mock_setup, - "internal_param_type": MagicMock(), + "param_type": MagicMock(), "experiment_param_type": MagicMock(), "callback_collection_type": MagicMock(), }, diff --git a/tests/unit_tests/parameters/plan_specific/__init__.py b/tests/unit_tests/parameters/plan_specific/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/unit_tests/parameters/plan_specific/test_fgs_internal_parameters.py b/tests/unit_tests/parameters/plan_specific/test_fgs_internal_parameters.py deleted file mode 100644 index d10fedf1a..000000000 --- a/tests/unit_tests/parameters/plan_specific/test_fgs_internal_parameters.py +++ /dev/null @@ -1,29 +0,0 @@ -import numpy as np -from dodal.devices.detector.det_dim_constants import EIGER2_X_16M_SIZE -from dodal.devices.fast_grid_scan import GridScanParams - -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanInternalParameters, -) - -from ....conftest import raw_params_from_file - - -def test_FGS_parameters_load_from_file(): - params = raw_params_from_file( - "tests/test_data/parameter_json_files/good_test_parameters.json" - ) - internal_parameters = GridscanInternalParameters(**params) - internal_parameters.json() - - assert isinstance(internal_parameters.experiment_params, GridScanParams) - - ispyb_params = internal_parameters.hyperion_params.ispyb_params - - np.testing.assert_array_equal(ispyb_params.position, np.array([10, 20, 30])) - - detector_params = internal_parameters.hyperion_params.detector_params - - assert detector_params.detector_size_constants == EIGER2_X_16M_SIZE - assert detector_params.num_triggers == 60 - assert detector_params.num_images_per_trigger == 1 diff --git a/tests/unit_tests/parameters/plan_specific/test_grid_scan_with_edge_detect_internal_parameters.py b/tests/unit_tests/parameters/plan_specific/test_grid_scan_with_edge_detect_internal_parameters.py deleted file mode 100644 index e446faa8a..000000000 --- a/tests/unit_tests/parameters/plan_specific/test_grid_scan_with_edge_detect_internal_parameters.py +++ /dev/null @@ -1,32 +0,0 @@ -import numpy as np -from dodal.devices.detector.det_dim_constants import EIGER2_X_16M_SIZE - -from hyperion.parameters.gridscan import GridScanWithEdgeDetect -from hyperion.parameters.plan_specific.grid_scan_with_edge_detect_params import ( - GridScanWithEdgeDetectParams, -) - -from ....conftest import raw_params_from_file - - -def test_grid_scan_with_edge_detect_parameters_load_from_file(): - # Can be removed in #1277 - params = raw_params_from_file( - "tests/test_data/new_parameter_json_files/good_test_grid_with_edge_detect_parameters.json" - ) - new_parameters = GridScanWithEdgeDetect(**params) - internal_parameters = new_parameters.old_parameters() - - assert isinstance( - internal_parameters.experiment_params, GridScanWithEdgeDetectParams - ) - - ispyb_params = internal_parameters.hyperion_params.ispyb_params - - np.testing.assert_array_equal(ispyb_params.position, np.array([10, 20, 30])) - - detector_params = internal_parameters.hyperion_params.detector_params - - assert detector_params.detector_size_constants == EIGER2_X_16M_SIZE - assert detector_params.num_triggers == 0 - assert detector_params.num_images_per_trigger == 1 diff --git a/tests/unit_tests/parameters/plan_specific/test_rotation_internal_parameters.py b/tests/unit_tests/parameters/plan_specific/test_rotation_internal_parameters.py deleted file mode 100644 index e02acba3f..000000000 --- a/tests/unit_tests/parameters/plan_specific/test_rotation_internal_parameters.py +++ /dev/null @@ -1,73 +0,0 @@ -from unittest.mock import MagicMock - -import numpy as np -from dodal.devices.detector.det_dim_constants import EIGER2_X_16M_SIZE -from dodal.devices.motors import XYZLimitBundle - -from hyperion.parameters.plan_specific.rotation_scan_internal_params import ( - RotationInternalParameters, - RotationScanParams, -) - -from ....conftest import raw_params_from_file - - -def test_rotation_scan_param_validity(): - test_params = RotationScanParams( - transmission_fraction=0.01, - rotation_axis="omega", - rotation_angle=360, - image_width=0.1, - omega_start=0, - phi_start=0, - chi_start=0, - kappa_start=0, - x=0, - y=0, - z=0, - ) - - xlim = MagicMock() - ylim = MagicMock() - zlim = MagicMock() - lims = XYZLimitBundle(xlim, ylim, zlim) - - assert test_params.xyz_are_valid(lims) - zlim.is_within.return_value = False - assert not test_params.xyz_are_valid(lims) - zlim.is_within.return_value = True - ylim.is_within.return_value = False - assert not test_params.xyz_are_valid(lims) - ylim.is_within.return_value = True - xlim.is_within.return_value = False - assert not test_params.xyz_are_valid(lims) - - -def test_rotation_parameters_load_from_file(): - params = raw_params_from_file( - "tests/test_data/parameter_json_files/good_test_rotation_scan_parameters.json" - ) - internal_parameters = RotationInternalParameters(**params) - - assert isinstance(internal_parameters.experiment_params, RotationScanParams) - assert internal_parameters.experiment_params.rotation_direction == "Negative" - - ispyb_params = internal_parameters.hyperion_params.ispyb_params - - np.testing.assert_array_equal(ispyb_params.position, np.array([10, 20, 30])) - - detector_params = internal_parameters.hyperion_params.detector_params - - assert detector_params.detector_size_constants == EIGER2_X_16M_SIZE - assert detector_params.expected_energy_ev == 100 - - -def test_rotation_parameters_enum_interpretation(): - params = raw_params_from_file( - "tests/test_data/parameter_json_files/good_test_rotation_scan_parameters.json" - ) - params["experiment_params"]["rotation_direction"] = "Positive" - internal_parameters = RotationInternalParameters(**params) - assert isinstance(internal_parameters.experiment_params, RotationScanParams) - - assert internal_parameters.experiment_params.rotation_direction == "Positive" diff --git a/tests/unit_tests/parameters/test_internal_parameters.py b/tests/unit_tests/parameters/test_internal_parameters.py deleted file mode 100644 index f610bb658..000000000 --- a/tests/unit_tests/parameters/test_internal_parameters.py +++ /dev/null @@ -1,279 +0,0 @@ -import copy -import json - -import numpy as np -import pytest -from dodal.devices.detector import DetectorParams -from dodal.devices.fast_grid_scan import GridScanParams -from pydantic import ValidationError - -from hyperion.external_interaction.ispyb.ispyb_dataclass import ( - GRIDSCAN_ISPYB_PARAM_DEFAULTS, - GridscanIspybParams, -) -from hyperion.parameters.gridscan import ThreeDGridScan -from hyperion.parameters.internal_parameters import ( - InternalParameters, - extract_hyperion_params_from_flat_dict, - fetch_subdict_from_bucket, - flatten_dict, - get_extracted_experiment_and_flat_hyperion_params, -) -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanHyperionParameters, - GridscanInternalParameters, - OddYStepsException, -) -from hyperion.parameters.plan_specific.rotation_scan_internal_params import ( - RotationInternalParameters, -) - -from ...conftest import default_raw_params, raw_params_from_file - - -@pytest.fixture -def raw_params(): - return raw_params_from_file( - "tests/test_data/parameter_json_files/test_parameters.json" - ) - - -@pytest.fixture -def rotation_raw_params(): - return raw_params_from_file( - "tests/test_data/parameter_json_files/good_test_rotation_scan_parameters.json" - ) - - -@pytest.fixture -def gridscan_params(raw_params): - return GridscanInternalParameters(**raw_params) - - -@pytest.fixture -def rotation_params(rotation_raw_params): - return RotationInternalParameters(**rotation_raw_params) - - -TEST_PARAM_DICT = { - "layer_1": { - "a": 23, - "x": 56, - "k": 47, - "layer_2": {"l": 11, "h": "test_value"}, - "layer_3": {"b": 5, "c": 6, "y": 7, "z": "test_value_2"}, - } -} - - -def test_cant_initialise_abstract_internalparams(): - with pytest.raises(TypeError): - internal_parameters = InternalParameters(**default_raw_params()) # noqa - - -def test_ispyb_param_dict(): - ispyb_params = GridscanIspybParams(**GRIDSCAN_ISPYB_PARAM_DEFAULTS) - as_dict = ispyb_params.dict() - assert isinstance(as_dict.get("position"), list) - modified_params = copy.deepcopy(GRIDSCAN_ISPYB_PARAM_DEFAULTS) - modified_params["position"] = [123, 7777777, 3] - modified_ispyb_params = GridscanIspybParams(**modified_params) - assert ispyb_params != modified_ispyb_params - assert isinstance(modified_ispyb_params.position, np.ndarray) - modified_as_dict = modified_ispyb_params.dict() - assert modified_as_dict.get("position") == [123, 7777777, 3] - - -def test_internal_param_serialisation_deserialisation(): - data = default_raw_params() - internal_parameters = ThreeDGridScan(**data) - - serialised = internal_parameters.json(indent=2) - reloaded = json.loads(serialised) - - deserialised = ThreeDGridScan(**reloaded) - - assert deserialised == internal_parameters - - -def test_flatten(): - params = raw_params_from_file( - "tests/test_data/parameter_json_files/test_parameters.json" - ) - flat_dict = flatten_dict(params) - for k in flat_dict: - assert not isinstance(flat_dict[k], dict) - - flat_test_dict = flatten_dict(TEST_PARAM_DICT) - for k in ["a", "b", "c", "h", "k", "l", "x", "y", "z"]: - assert k in flat_test_dict - - with pytest.raises(Exception): - flatten_dict({"x": 6, "y": {"x": 7}}) - - -def test_hyperion_params_needs_values_from_experiment(raw_params): - extracted_hyperion_param_dict = extract_hyperion_params_from_flat_dict( - flatten_dict(raw_params), - GridscanInternalParameters._hyperion_param_key_definitions(), - ) - with pytest.raises(ValidationError): - hyperion_params = GridscanHyperionParameters(**extracted_hyperion_param_dict) - with pytest.raises(UnboundLocalError): - assert hyperion_params is not None - - -def test_hyperion_parameters_only_from_file(): - with open("tests/test_data/hyperion_parameters.json") as f: - hyperion_param_dict = json.load(f) - hyperion_params_deserialised = GridscanHyperionParameters(**hyperion_param_dict) - ispyb = hyperion_params_deserialised.ispyb_params - detector = hyperion_params_deserialised.detector_params - assert isinstance(ispyb, GridscanIspybParams) - assert isinstance(detector, DetectorParams) - - -def test_hyperion_params_can_be_deserialised_from_internal_representation(raw_params): - internal_params = GridscanInternalParameters(**raw_params) - hyperion_param_json = internal_params.hyperion_params.json() - hyperion_param_dict = json.loads(hyperion_param_json) - assert hyperion_param_dict.get("ispyb_params") is not None - assert hyperion_param_dict.get("detector_params") is not None - hyperion_params_deserialised = GridscanHyperionParameters(**hyperion_param_dict) - assert internal_params.hyperion_params == hyperion_params_deserialised - ispyb = hyperion_params_deserialised.ispyb_params - detector = hyperion_params_deserialised.detector_params - assert isinstance(ispyb, GridscanIspybParams) - assert isinstance(detector, DetectorParams) - - -def test_hyperion_params_eq(raw_params): - internal_params = GridscanInternalParameters(**raw_params) - - hyperion_params_1 = internal_params.hyperion_params - hyperion_params_2 = copy.deepcopy(hyperion_params_1) - assert hyperion_params_1 == hyperion_params_2 - - hyperion_params_2.zocalo_environment = "some random thing" - assert hyperion_params_1 != hyperion_params_2 - - hyperion_params_2 = copy.deepcopy(hyperion_params_1) - hyperion_params_2.insertion_prefix = "some random thing" - assert hyperion_params_1 != hyperion_params_2 - - hyperion_params_2 = copy.deepcopy(hyperion_params_1) - hyperion_params_2.experiment_type = "some random thing" - assert hyperion_params_1 != hyperion_params_2 - - hyperion_params_2 = copy.deepcopy(hyperion_params_1) - hyperion_params_2.detector_params.expected_energy_ev = 99999 - assert hyperion_params_1 != hyperion_params_2 - - hyperion_params_2 = copy.deepcopy(hyperion_params_1) - hyperion_params_2.ispyb_params.beam_size_x = 99999 - assert hyperion_params_1 != hyperion_params_2 - - -def test_get_extracted_experiment_and_flat_hyperion_params(raw_params): - flat_params = flatten_dict(raw_params) - processed_params = get_extracted_experiment_and_flat_hyperion_params( - GridScanParams, flat_params - ) - assert processed_params.get("experiment_params") not in [None, {}] - experiment_params = GridScanParams(**processed_params.get("experiment_params")) - assert experiment_params.x_steps == flat_params["x_steps"] - assert experiment_params.y_steps == flat_params["y_steps"] - assert experiment_params.z_steps == flat_params["z_steps"] - - -def test_fetch_subdict(raw_params): - keys_all_in = ["x_steps", "y_steps", "z_steps"] - keys_not_all_in = ["x_steps", "y_steps", "z_steps", "asdfghjk"] - flat_params = flatten_dict(raw_params) - subdict = fetch_subdict_from_bucket(keys_all_in, flat_params) - assert len(subdict) == 3 - subdict_2 = fetch_subdict_from_bucket(keys_not_all_in, flat_params) - assert len(subdict_2) == 3 - - -def test_param_fields_match_components_they_should_use( - gridscan_params: GridscanInternalParameters, - rotation_params: RotationInternalParameters, -): - r_params = rotation_params.hyperion_params.ispyb_params - g_params = gridscan_params.hyperion_params.ispyb_params - - r_calculated_ispyb_param_keys = list( - rotation_params._hyperion_param_key_definitions()[2] - ) - g_calculated_ispyb_param_keys = list( - gridscan_params._hyperion_param_key_definitions()[2] - ) - - from hyperion.external_interaction.ispyb.ispyb_dataclass import IspybParams - - base_ispyb_annotation_keys = list(IspybParams.__annotations__.keys()) - r_ispyb_annotation_keys = list(r_params.__class__.__annotations__.keys()) - g_ispyb_annotation_keys = list(g_params.__class__.__annotations__.keys()) - - assert ( - r_calculated_ispyb_param_keys - == base_ispyb_annotation_keys + r_ispyb_annotation_keys - ) - assert ( - g_calculated_ispyb_param_keys - == base_ispyb_annotation_keys + g_ispyb_annotation_keys - ) - - -def test_internal_params_eq(): - params = raw_params_from_file( - "tests/test_data/parameter_json_files/test_parameters.json" - ) - internal_params = GridscanInternalParameters(**params) - internal_params_2 = copy.deepcopy(internal_params) - - assert internal_params == internal_params_2 - assert internal_params_2 != 3 - assert internal_params_2.hyperion_params != 3 - - internal_params_2.experiment_params.x_steps = 11111 - assert internal_params != internal_params_2 - - internal_params_2 = copy.deepcopy(internal_params) - internal_params_2.hyperion_params.ispyb_params.beam_size_x = 123456 - assert internal_params != internal_params_2 - - internal_params_2 = copy.deepcopy(internal_params) - internal_params_2.hyperion_params.detector_params.exposure_time = 99999 - assert internal_params != internal_params_2 - - internal_params_2 = copy.deepcopy(internal_params) - internal_params_2.hyperion_params.zocalo_environment = "not_real_env" - assert internal_params != internal_params_2 - - internal_params_2 = copy.deepcopy(internal_params) - internal_params_2.hyperion_params.beamline = "not_real_beamline" - assert internal_params != internal_params_2 - - internal_params_2 = copy.deepcopy(internal_params) - internal_params_2.hyperion_params.insertion_prefix = "not_real_prefix" - assert internal_params != internal_params_2 - - internal_params_2 = copy.deepcopy(internal_params) - internal_params_2.hyperion_params.experiment_type = "not_real_experiment" - assert internal_params != internal_params_2 - - -def test_panda_y_steps_must_be_even(): - params = raw_params_from_file( - "tests/test_data/parameter_json_files/test_parameters.json" - ) - params["experiment_params"]["y_steps"] = 11 - - from hyperion.parameters.plan_specific.panda.panda_gridscan_internal_params import ( - PandAGridscanInternalParameters, - ) - - with pytest.raises(OddYStepsException): - PandAGridscanInternalParameters(**params) diff --git a/tests/unit_tests/parameters/test_parameter_model.py b/tests/unit_tests/parameters/test_parameter_model.py index 664b7e348..ad6e7d8a7 100644 --- a/tests/unit_tests/parameters/test_parameter_model.py +++ b/tests/unit_tests/parameters/test_parameter_model.py @@ -1,27 +1,13 @@ import json import pytest -from dodal.devices.detector.det_dist_to_beam_converter import ( - DetectorDistanceToBeamXYConverter, -) from pydantic import ValidationError -from hyperion.parameters.constants import CONST from hyperion.parameters.gridscan import ( - PinTipCentreThenXrayCentre, + OddYStepsException, RobotLoadThenCentre, ThreeDGridScan, ) -from hyperion.parameters.plan_specific.gridscan_internal_params import ( - GridscanInternalParameters, -) -from hyperion.parameters.plan_specific.pin_centre_then_xray_centre_params import ( - PinCentreThenXrayCentreInternalParameters, -) -from hyperion.parameters.plan_specific.rotation_scan_internal_params import ( - RotationInternalParameters, -) -from hyperion.parameters.rotation import RotationScan @pytest.fixture @@ -42,22 +28,25 @@ def minimal_3d_gridscan_params(): "storage_directory": "/tmp/dls/i03/data/2024/cm31105-4/xraycentring/123456/", "ispyb_extras": { "position": [0, 0, 0], - "beam_size_x": 0, - "beam_size_y": 0, - "focal_spot_size_x": 0, - "focal_spot_size_y": 0, }, } def test_minimal_3d_gridscan_params(minimal_3d_gridscan_params): test_params = ThreeDGridScan(**minimal_3d_gridscan_params) - assert {"sam_x", "sam_y", "sam_z", "omega"} == set(test_params.scan_points.keys()) + assert {"sam_x", "sam_y", "sam_z"} == set(test_params.scan_points.keys()) assert test_params.scan_indices == [0, 35] assert test_params.num_images == (5 * 7 + 5 * 9) assert test_params.exposure_time_s == 0.02 +def test_cant_do_panda_fgs_with_odd_y_steps(minimal_3d_gridscan_params): + test_params = ThreeDGridScan(**minimal_3d_gridscan_params) + with pytest.raises(OddYStepsException): + test_params.panda_FGS_params + assert test_params.FGS_params + + def test_serialise_deserialise(minimal_3d_gridscan_params): test_params = ThreeDGridScan(**minimal_3d_gridscan_params) serialised = json.loads(test_params.json()) @@ -82,57 +71,6 @@ def test_param_version(minimal_3d_gridscan_params): _ = ThreeDGridScan(**minimal_3d_gridscan_params) -def test_new_gridscan_params_equals_old(): - # Can be removed in #1277 - with open("tests/test_data/parameter_json_files/good_test_parameters.json") as f: - old_json_data = json.loads(f.read()) - with open( - "tests/test_data/new_parameter_json_files/good_test_parameters.json" - ) as f: - new_json_data = json.loads(f.read()) - - new_json_data["x_steps"] = 10 - new_json_data["y_steps"] = 5 - new_json_data["z_steps"] = 1 - old_params = GridscanInternalParameters(**old_json_data) - new_params = ThreeDGridScan(**new_json_data) - - old_detector_params = old_params.hyperion_params.detector_params - new_detector_params = new_params.detector_params - - assert isinstance( - old_detector_params.beam_xy_converter, DetectorDistanceToBeamXYConverter - ) - - assert old_detector_params == new_detector_params - assert old_params.hyperion_params.ispyb_params == new_params.ispyb_params - - -def test_new_rotation_params_equals_old(): - # Can be removed in #1277 - with open( - "tests/test_data/parameter_json_files/good_test_rotation_scan_parameters_nomove.json" - ) as f: - old_json_data = json.loads(f.read()) - with open( - "tests/test_data/new_parameter_json_files/good_test_rotation_scan_parameters_nomove.json" - ) as f: - new_json_data = json.loads(f.read()) - - old_params = RotationInternalParameters(**old_json_data) - new_params = RotationScan(**new_json_data) - - old_detector_params = old_params.hyperion_params.detector_params - new_detector_params = new_params.detector_params - - assert isinstance( - old_detector_params.beam_xy_converter, DetectorDistanceToBeamXYConverter - ) - - assert old_detector_params == new_detector_params - assert old_params.hyperion_params.ispyb_params == new_params.ispyb_params - - def test_robot_load_then_centre_params(): params = { "parameter_model_version": "5.0.0", @@ -141,10 +79,6 @@ def test_robot_load_then_centre_params(): "file_name": "file_name", "storage_directory": "/tmp/dls/i03/data/2024/cm31105-4/xraycentring/123456/", "ispyb_extras": { - "beam_size_x": 0.05, - "beam_size_y": 0.05, - "focal_spot_size_x": 0.06, - "focal_spot_size_y": 0.06, "position": [0, 0, 0], }, } @@ -152,189 +86,3 @@ def test_robot_load_then_centre_params(): test_params = RobotLoadThenCentre(**params) assert test_params.visit_directory assert test_params.detector_params - - -class TestNewGdaParams: - # Can be removed in #1277 - - energy = 12123 - filename = "samplefilenametest" - omega_start = 0.023 - transmission = 45 / 100 - visit = "cm66666-6" - position = [123.0, 234.0, 345.0] - beam_size_x = 131 / 1000.0 - beam_size_y = 204 / 1000.0 - focal_spot_size_x = 468 - focal_spot_size_y = 787 - sample_id = 456789 - exposure_time_s = 0.004 - detector_distance_mm = 242 - chi = 27.0 - rotation_inc = 0.56 - rotation_axis = "omega" - rotation_direction = "Negative" - rotation_comment = "Hyperion rotation scan - " - directory = "/tmp/dls/i03/data/2024/cm66666-6/xraycentring/456789/" - - def test_pin_then_xray(self): - new_hyperion_params_dict = { - "parameter_model_version": "5.0.0", - "demand_energy_ev": self.energy, - "exposure_time_s": self.exposure_time_s, - "detector_distance_mm": self.detector_distance_mm, - "visit": self.visit, - "omega_start_deg": self.omega_start, - "file_name": self.filename, - "sample_id": self.sample_id, - "use_roi_mode": False, - "transmission_frac": self.transmission, - "zocalo_environment": "artemis", - "storage_directory": self.directory, - "ispyb_extras": { - "position": self.position, - "beam_size_x": self.beam_size_x, - "beam_size_y": self.beam_size_y, - "focal_spot_size_x": self.focal_spot_size_x, - "focal_spot_size_y": self.focal_spot_size_y, - }, - } - old_hyperion_params_dict = { - "params_version": "5.0.0", - "hyperion_params": { - "beamline": CONST.I03.BEAMLINE, - "insertion_prefix": CONST.I03.INSERTION_PREFIX, - "zocalo_environment": "artemis", - "experiment_type": "pin_centre_then_xray_centre", - "detector_params": { - "expected_energy_ev": self.energy, - "directory": self.directory, - "prefix": self.filename, - "use_roi_mode": False, - "detector_size_constants": CONST.I03.DETECTOR, - "run_number": 1, - "det_dist_to_beam_converter_path": CONST.PARAM.DETECTOR.BEAM_XY_LUT_PATH, - }, - "ispyb_params": { - "current_energy_ev": self.energy, - "sample_id": self.sample_id, - "visit_path": "/tmp/dls/i03/data/2024/cm66666-6", - "position": self.position, - "beam_size_x": self.beam_size_x, - "beam_size_y": self.beam_size_y, - "focal_spot_size_x": self.focal_spot_size_x, - "focal_spot_size_y": self.focal_spot_size_y, - "resolution": 1.57, - "comment": "", - }, - }, - "experiment_params": { - "transmission_fraction": self.transmission, - "snapshot_dir": f"{self.directory}snapshots", - "detector_distance": self.detector_distance_mm, - "exposure_time": self.exposure_time_s, - "omega_start": self.omega_start, - "grid_width_microns": 600, - "tip_offset_microns": 0, - "set_stub_offsets": False, - }, - } - new_params = PinTipCentreThenXrayCentre(**new_hyperion_params_dict) - old_params = PinCentreThenXrayCentreInternalParameters( - **old_hyperion_params_dict - ) - - new_old_params = new_params.old_parameters() - - # This should all be stuff that is no longer needed because - # we get it from devices! - old_params.hyperion_params.ispyb_params.xtal_snapshots_omega_end = [] - old_params.hyperion_params.ispyb_params.xtal_snapshots_omega_start = [] - - assert new_old_params == old_params - - def test_rotation_new_params(self): - new_hyperion_params_dict = { - "parameter_model_version": "5.0.0", - "comment": self.rotation_comment, - "detector_distance_mm": self.detector_distance_mm, - "demand_energy_ev": self.energy, - "exposure_time_s": self.exposure_time_s, - "omega_start_deg": self.omega_start, - "chi_start_deg": self.chi, - "file_name": self.filename, - "scan_width_deg": self.rotation_inc * 1001, - "rotation_axis": self.rotation_axis, - "storage_directory": self.directory, - "rotation_direction": self.rotation_direction, - "rotation_increment_deg": self.rotation_inc, - "sample_id": self.sample_id, - "visit": self.visit, - "zocalo_environment": "artemis", - "transmission_frac": self.transmission, - "ispyb_extras": { - "xtal_snapshots_omega_start": ["test1", "test2", "test3"], - "xtal_snapshots_omega_end": ["", "", ""], - "position": self.position, - "beam_size_x": self.beam_size_x, - "beam_size_y": self.beam_size_y, - "focal_spot_size_x": self.focal_spot_size_x, - "focal_spot_size_y": self.focal_spot_size_y, - }, - } - - old_hyperion_params_dict = { - "params_version": "5.0.0", - "hyperion_params": { - "beamline": CONST.I03.BEAMLINE, - "insertion_prefix": CONST.I03.INSERTION_PREFIX, - "detector": "EIGER2_X_16M", - "zocalo_environment": "artemis", - "experiment_type": "SAD", - "detector_params": { - "expected_energy_ev": self.energy, - "directory": self.directory, - "prefix": self.filename, - "use_roi_mode": False, - "detector_size_constants": CONST.I03.DETECTOR, - "run_number": 1, - "det_dist_to_beam_converter_path": CONST.PARAM.DETECTOR.BEAM_XY_LUT_PATH, - }, - "ispyb_params": { - "ispyb_experiment_type": "SAD", - "current_energy_ev": self.energy, - "sample_id": self.sample_id, - "visit_path": "/tmp/dls/i03/data/2024/cm66666-6", - "position": self.position, - "beam_size_x": self.beam_size_x, - "beam_size_y": self.beam_size_y, - "focal_spot_size_x": self.focal_spot_size_x, - "focal_spot_size_y": self.focal_spot_size_y, - "resolution": 1.57, - "comment": self.rotation_comment, - "xtal_snapshots_omega_start": ["test1", "test2", "test3"], - "xtal_snapshots_omega_end": ["", "", ""], - "xtal_snapshots": ["", "", ""], - }, - }, - "experiment_params": { - "transmission_fraction": self.transmission, - "rotation_axis": self.rotation_axis, - "chi_start": self.chi, - "rotation_angle": self.rotation_inc * 1001, - "omega_start": self.omega_start, - "exposure_time": self.exposure_time_s, - "detector_distance": self.detector_distance_mm, - "rotation_increment": self.rotation_inc, - "image_width": self.rotation_inc, - "positive_rotation_direction": False, - "shutter_opening_time_s": 0.06, - }, - } - - new_params = RotationScan(**new_hyperion_params_dict) - old_params = RotationInternalParameters(**old_hyperion_params_dict) - - new_old_params = new_params.old_parameters() - - assert new_old_params == old_params