Source code for easistrain.EDD.io

from typing import Dict, Optional, Sequence, Tuple, Union
import h5py
import numpy


nxchar = h5py.special_dtype(vlen=str)


[docs] def as_nxchar(s: Union[str, Sequence[str]]) -> numpy.ndarray: return numpy.array(s, dtype=nxchar)
[docs] def create_info_group( root: h5py.Group, fileRead: str, fileSave: str, sample: Optional[str], dataset: Union[str, int, None], nameHorizontalDetector: str, nameVerticalDetector: str, nbPeaksInBoxes: Sequence[int], ): infoGroup = root.create_group("infos") ## infos group creation infoGroup.create_dataset( "fileRead", dtype=h5py.string_dtype(encoding="utf-8"), data=fileRead ) ## save path of raw data file in infos group infoGroup.create_dataset( "fileSave", dtype=h5py.string_dtype(encoding="utf-8"), data=fileSave ) ## save path of the file in which results will be saved in info group infoGroup.create_dataset( "sample", dtype=h5py.string_dtype(encoding="utf-8"), data=sample if sample is not None else "No sample", ) ## save the name of the sample in infos group infoGroup.create_dataset( "dataset", dtype=h5py.string_dtype(encoding="utf-8"), data=dataset if dataset is not None else "No dataset", ) ## save the name of dataset in infos group infoGroup.create_dataset( "nameHorizontalDetector", dtype=h5py.string_dtype(encoding="utf-8"), data=nameHorizontalDetector, ) ## save of the name of the horizontal detector in infos group infoGroup.create_dataset( "nameVerticalDetector", dtype=h5py.string_dtype(encoding="utf-8"), data=nameVerticalDetector, ) ## save of the name of the vertical detector in infos group infoGroup.create_dataset( "nbPeaksInBoxes", dtype="int", data=nbPeaksInBoxes ) ## save of the number of peaks per box/window in infos group infoGroup.create_dataset( "fittingFunction", dtype=h5py.string_dtype(encoding="utf-8"), data="asymmetric Pseudo-Voigt", ) ## save of the type of function used in the fitting of the peaks return infoGroup
[docs] def create_calib_info_group( root: h5py.Group, fileRead: str, fileSave: str, sample: Optional[str], dataset: Union[str, int, None], nameHorizontalDetector: str, nameVerticalDetector: str, nbPeaksInBoxes: Sequence[int], scanNumberHorizontalDetector: Union[str, int], scanNumberVerticalDetector: Union[str, int], rangeFit: Sequence[int], peakEnergies: Sequence[float], ): infoGroup = create_info_group( root, fileRead, fileSave, sample, dataset, nameHorizontalDetector, nameVerticalDetector, nbPeaksInBoxes, ) infoGroup.create_dataset( "scanNumberHorizontalDetector", dtype=int, data=int(scanNumberHorizontalDetector), ) ## save of the number of the scan containing the calibration pattern of the horizontal detector in infos group infoGroup.create_dataset( "scanNumberVerticalDetector", dtype=int, data=int(scanNumberVerticalDetector), ) ## save of the number of the scan containing the calibration pattern of the vertical detector in info group infoGroup.create_dataset( "rangeFit", dtype=int, data=rangeFit ) ## save of the range of the fit of each box/window in infos group infoGroup.create_dataset( "peakEnergies", dtype=float, data=peakEnergies, ) ## save of the path of the calibrant File in infos group return infoGroup
[docs] def create_angle_calib_info_group( root: h5py.Group, fileRead: str, fileSave: str, sample: Optional[str], dataset: Union[str, int, None], nameHorizontalDetector: str, nameVerticalDetector: str, nbPeaksInBoxes: Sequence[int], rangeFitHD: Sequence[int], rangeFitVD: Sequence[int], ): infoGroup = create_info_group( root, fileRead, fileSave, sample, dataset, nameHorizontalDetector, nameVerticalDetector, nbPeaksInBoxes, ) infoGroup.create_dataset( "rangeFitHD", dtype="int", data=rangeFitHD ) ## save of the range of the fit of each box/window of the horizontal detector in infos group infoGroup.create_dataset( "rangeFitVD", dtype="int", data=rangeFitVD ) ## save of the range of the fit of each box/window of the vertical detector in infos group return infoGroup
[docs] def create_fit_info_group( root: h5py.Group, fileRead: str, fileSave: str, sample: Optional[str], dataset: Union[str, int, None], scanNumber: Union[str, int], nameHorizontalDetector: str, nameVerticalDetector: str, nbPeaksInBoxes: Sequence[int], rangeFitHD: Sequence[int], rangeFitVD: Sequence[int], positioners: Sequence[str], ): infoGroup = create_info_group( root, fileRead, fileSave, sample, dataset, nameHorizontalDetector, nameVerticalDetector, nbPeaksInBoxes, ) infoGroup.create_dataset( "scanNumber", dtype="int", data=scanNumber ) ## save of the number of the scan in infos group infoGroup.create_dataset( "rangeFitHD", dtype="int", data=rangeFitHD ) ## save of the range of the fit of each box/window of the horizontal detector in infos group infoGroup.create_dataset( "rangeFitVD", dtype="int", data=rangeFitVD ) ## save of the range of the fit of each box/window of the vertical detector in infos group infoGroup.create_dataset( "positioners", dtype=h5py.string_dtype(encoding="utf-8"), data=str(positioners) ) ## save of the range of the fit of each box/window of the vertical detector in infos group return infoGroup
[docs] def peak_dataset_data( positionAngles: numpy.ndarray, savedPeakFitParams: numpy.ndarray, delta_angle: float, nacq, ): return [ *positionAngles[nacq, 0:6], delta_angle, ## delta angle of the horizontal detector (debye scherer angle) 0, ## theta angle (diffraction fixed angle) of the horizontal detector (I suppose that it is zero as we work with a small angle fixed to 2.5 deg) savedPeakFitParams[1], ## peak position of HD savedPeakFitParams[0], ## peak intensity of HD (maximum intensity) 0.5 * ( savedPeakFitParams[2] + savedPeakFitParams[3] ), ## FWHM of HD (mean of the FWHM at left and right as I am using an assymetric function) savedPeakFitParams[ 4 ], ## shape factor (contribution of the lorentzian function) ( savedPeakFitParams[5] if len(savedPeakFitParams) >= 6 else 0 ), ## Rw factor of HD (goodness of the fit) ]
[docs] def save_fit_data( fitLine: h5py.Group, detectorName: str, channels: numpy.ndarray, raw_data: numpy.ndarray, background: numpy.ndarray, fitted_data: numpy.ndarray, ): detectorGroup = fitLine.create_group(detectorName) detectorGroup.create_dataset( "channels", dtype="float64", data=channels, ) detectorGroup.create_dataset( "raw_data", dtype="float64", data=raw_data, ) detectorGroup.create_dataset( "background", dtype="float64", data=background, ) detectorGroup.create_dataset( "data - background", dtype="float64", data=raw_data - background, ) detectorGroup.create_dataset( "fitted_data", dtype="float64", data=fitted_data, ) detectorGroup.create_dataset( "residual", dtype="float64", data=numpy.absolute(fitted_data - raw_data), ) # NeXus detectorGroup.attrs["NX_class"] = as_nxchar("NXdata") detectorGroup.attrs["auxiliary_signals"] = as_nxchar(["raw_data"]) detectorGroup.attrs["signal"] = as_nxchar("fitted_data") detectorGroup.attrs["axes"] = as_nxchar("channels")
[docs] def scan_group_path( sample: Union[str, None], dataset: Union[str, int, None], scanNumber: Union[str, int], ): path = "" if sample: path += f"{sample}_" if dataset: path += f"{dataset}_" return f"{path}{scanNumber}.1"
[docs] def read_detector_pattern( input_filename: str, sample: Union[str, None], dataset: Union[str, int, None], scanNumber: Union[str, int], detector_name: str, detectorSliceIndex: Union[int, Tuple[()], str] = tuple(), ): with h5py.File(input_filename, "r") as h5Read: ## Read the h5 file of raw data meas_group = h5Read[ f"{scan_group_path(sample, dataset, scanNumber)}/measurement" ] if not isinstance(meas_group, h5py.Group) or detector_name not in meas_group: raise TypeError("No pattern was saved in this scan") return detector_dset = meas_group[detector_name] assert isinstance(detector_dset, h5py.Dataset) if detectorSliceIndex == "sum": return detector_dset[()].sum(axis=0) return detector_dset[detectorSliceIndex]
[docs] def read_positioner_data( input_filename: str, sample: Union[str, None], dataset: Union[str, int, None], scanNumber: Union[str, int], positioner_name: str, detectorSliceIndex: Union[int, Tuple[()]] = tuple(), ): with h5py.File(input_filename, "r") as h5Read: input_positioners = h5Read[ f"{scan_group_path(sample, dataset, scanNumber)}/instrument/positioners" ] assert isinstance(input_positioners, h5py.Group) if positioner_name not in input_positioners: raise KeyError( f"{positioner_name} was not found in input positioners! Possible values: {input_positioners.keys()}" ) pos_dataset = input_positioners[positioner_name] assert isinstance(pos_dataset, h5py.Dataset) # Scalar if not pos_dataset.shape: return pos_dataset[()] return pos_dataset[detectorSliceIndex]
[docs] def save_fit_params( parent: h5py.Group, fitParams: Dict[str, numpy.ndarray], uncertaintyFitParams: Dict[str, numpy.ndarray], ): savedFitParamsHD = numpy.reshape( fitParams["horizontal"], (int(numpy.size(fitParams["horizontal"]) / 6), 6) ) parent.create_dataset( "fitParamsHD", dtype="float64", data=savedFitParamsHD, ) ## save parameters of the fit of HD savedUncertaintyFitParamsHD = numpy.reshape( uncertaintyFitParams["horizontal"], (int(numpy.size(uncertaintyFitParams["horizontal"]) / 5), 5), ) parent.create_dataset( "uncertaintyFitParamsHD", dtype="float64", data=savedUncertaintyFitParamsHD, ) ## save uncertainty on the parameters of the fit of HD savedFitParamsVD = numpy.reshape( fitParams["vertical"], (int(numpy.size(fitParams["vertical"]) / 6), 6) ) parent.create_dataset( "fitParamsVD", dtype="float64", data=savedFitParamsVD, ) ## save parameters of the fit of VD savedUncertaintyFitParamsVD = numpy.reshape( uncertaintyFitParams["vertical"], (int(numpy.size(uncertaintyFitParams["vertical"]) / 5), 5), ) parent.create_dataset( "uncertaintyFitParamsVD", dtype="float64", data=savedUncertaintyFitParamsVD, ) ## save uncertainty on the parameters of the fit of VD return ( savedFitParamsHD, savedFitParamsVD, savedUncertaintyFitParamsHD, savedUncertaintyFitParamsVD, )