Source code for ewoksfluo.tasks.sum_detectors

from typing import Sequence

import numpy
import h5py
from ewokscore import Task

from . import nexus
from .utils import get_correction_factor
from .positioner_utils import get_energy


DEFAULTS = {
    "xrf_spectra_uri_template": "instrument/{}/data",
    "livetime_uri_template": "instrument/{}/live_time",
    "livetime_reference_value": 1,
    "energy_name": None,
    "energy_uri_template": "instrument/positioners_start/{}",
}


[docs] class SumDetectors( Task, input_names=[ "scan_uri", "detector_names", "output_uri", ], optional_input_names=[ "xrf_spectra_uri_template", "energy_name", "energy_uri_template", "livetime_uri_template", "livetime_reference_value", ], output_names=[ "scan_uri", "detector_name", "xrf_spectra_uri_template", ], ):
[docs] def run(self): start_time = nexus.now() params = {**DEFAULTS, **self.get_input_values()} scan_uri: str = params["scan_uri"] detector_names: Sequence[str] = params["detector_names"] xrf_spectra_uri_template: str = params["xrf_spectra_uri_template"] energy_name: str = params["energy_name"] energy_uri_template: str = params["energy_uri_template"] livetime_uri_template: str = params["livetime_uri_template"] livetime_reference_value: float = params["livetime_reference_value"] output_uri: str = params["output_uri"] if len(detector_names) < 1: raise ValueError("Expected at least 1 detector to sum") input_file, scan_h5path = nexus.split_h5uri(scan_uri) with h5py.File(input_file, "r") as h5file: summed_data = None scan_group = h5file[scan_h5path] energy = get_energy(scan_uri, energy_name, energy_uri_template) for detector_name in detector_names: xrf_spectra_dataset = scan_group[ xrf_spectra_uri_template.format(detector_name) ] assert isinstance(xrf_spectra_dataset, h5py.Dataset) xrf_spectra_data = xrf_spectra_dataset[()] livetime_uri = ( f"{scan_uri}/{livetime_uri_template.format(detector_name)}" ) correction = get_correction_factor( [livetime_uri], [livetime_reference_value] ) if summed_data is None: summed_data = numpy.zeros_like( xrf_spectra_data, dtype="float32" ) # Cast to float since the correction is a floating-point division summed_data += xrf_spectra_data * correction.reshape( (len(correction), 1) ) with nexus.save_in_ewoks_process( output_uri, start_time, process_config={"livetime_reference_value": livetime_reference_value}, default_levels=("results", "sumdetectors"), ) as process_group: results_group = nexus.create_data(process_group, "mcasum", signal="data") results_group.create_dataset("data", data=summed_data) if energy is not None: dset = process_group.create_dataset( "instrument/positioners_start/energy", data=energy ) dset.attrs["units"] = "keV" process_group["instrument"].attrs["NX_class"] = "NXinstrument" process_group["instrument/positioners_start"].attrs[ "NX_class" ] = "NXcollection" self.outputs.scan_uri = ( f"{process_group.file.filename}::{process_group.name}" ) self.outputs.detector_name = "mcasum" self.outputs.xrf_spectra_uri_template = "{}/data"