Source code for ewoksxrdct.tasks.read_fscan2d

import os
from pathlib import Path

from ewokscore import Task

from .utils.hdf5 import load_hdf5_path
from .utils.hdf5 import open_hdf5_file
from .utils.read_models import ReadInputModel
from .utils.read_models import ReadOutputModel
from .utils.validate import validate_frame_count
from .utils.validate import validate_motor_counts


[docs] class ReadFscan2d( Task, input_model=ReadInputModel, output_model=ReadOutputModel, ): """This task assumes the bliss master file follows ESRF's beamline conventions for fscan2d scans. The master file must contain: - `measurement/{translation_motor_name}`: 1D translation positions - `measurement/{rotation_motor_name}`: 1D rotation angles - `instrument/fscan_parameters/fast_motor`: name of the fast motor - `instrument/fscan_parameters/slow_motor`: name of the slow motor - `instrument/fscan_parameters/fast_start_pos`: scalar, fast motor start position - `instrument/fscan_parameters/fast_step_size`: scalar, fast motor step size - `instrument/fscan_parameters/fast_npoints`: scalar, number of fast motor points - `instrument/fscan_parameters/slow_start_pos`: scalar, slow motor start position - `instrument/fscan_parameters/slow_step_size`: scalar, slow motor step size - `instrument/fscan_parameters/slow_npoints`: scalar, number of slow motor points """
[docs] def run(self) -> None: """Execute the task to read the raw motor and azimuthally integrated data for fscan2d scans and derive the grid info needed for regridding.""" bliss_master = self.inputs.bliss_master_path with open_hdf5_file(bliss_master) as f: file = Path(bliss_master).name scan = f"{self.inputs.scan_number}.1" translations = load_hdf5_path( f, f"{scan}/measurement/{self.inputs.translation_motor_name}", file )[()] rotations = load_hdf5_path( f, f"{scan}/measurement/{self.inputs.rotation_motor_name}", file )[()] fast_motor_name = load_hdf5_path( f, f"{scan}/instrument/fscan_parameters/fast_motor", file )[()].decode() slow_motor_name = load_hdf5_path( f, f"{scan}/instrument/fscan_parameters/slow_motor", file )[()].decode() fast_start = load_hdf5_path( f, f"{scan}/instrument/fscan_parameters/fast_start_pos", file )[()].item() fast_step = load_hdf5_path( f, f"{scan}/instrument/fscan_parameters/fast_step_size", file )[()].item() fast_npoints = load_hdf5_path( f, f"{scan}/instrument/fscan_parameters/fast_npoints", file )[()].item() slow_start = load_hdf5_path( f, f"{scan}/instrument/fscan_parameters/slow_start_pos", file )[()].item() slow_step = load_hdf5_path( f, f"{scan}/instrument/fscan_parameters/slow_step_size", file )[()].item() slow_npoints = load_hdf5_path( f, f"{scan}/instrument/fscan_parameters/slow_npoints", file )[()].item() if ( fast_motor_name == self.inputs.rotation_motor_name and slow_motor_name == self.inputs.translation_motor_name ): rotation_is_fast = True elif ( fast_motor_name == self.inputs.translation_motor_name and slow_motor_name == self.inputs.rotation_motor_name ): rotation_is_fast = False else: raise ValueError( f"Either 'rotation_motor_name' ({self.inputs.rotation_motor_name!r}) or" f" 'translation_motor_name' ({self.inputs.translation_motor_name!r}) " f"does not match the fast/slow motors recorded for this scan " f"({fast_motor_name!r}/{slow_motor_name!r})." ) validate_motor_counts(fast_npoints * slow_npoints, translations, rotations) ai_filename = self.inputs.integration_output_path with open_hdf5_file(ai_filename) as f: ai_file = Path(ai_filename).name radial_axis = load_hdf5_path( f, self.inputs.integration_radial_axis_path, ai_file )[()] intensity = load_hdf5_path( f, self.inputs.integration_intensity_path, ai_file )[()] # Check the data sizing will be consistent in the final NX file. validate_frame_count(fast_npoints * slow_npoints, intensity) # The fast motor records the center of each step (see fscan's # MusstCenterCalc, same convention as aeroystepscan's rotation motor). # The slow motor is a standard step-scan master and records the exact # commanded target position. fast_grid_params = ( fast_start + fast_step / 2, fast_start + fast_npoints * fast_step - fast_step / 2, fast_npoints, ) slow_grid_params = ( slow_start, slow_start + (slow_npoints - 1) * slow_step, slow_npoints, ) self.outputs.rotation_angles = rotations self.outputs.translation_values = translations self.outputs.integration_intensity_values = intensity self.outputs.integration_radial_axis = os.path.basename( self.inputs.integration_radial_axis_path ) self.outputs.integration_radial_axis_values = radial_axis if rotation_is_fast: self.outputs.rotation_grid_params = fast_grid_params self.outputs.translation_grid_params = slow_grid_params else: self.outputs.rotation_grid_params = slow_grid_params self.outputs.translation_grid_params = fast_grid_params