Example #1
0
    def _load_masks(self, hidra_file):
        """Load masks from Hidra project file

        Parameters
        ----------
        hidra_file :  pyrs.projectfile.file_object.HidraProjectFile
            Hidra project file instance

        Returns
        -------

        """
        # Check
        checkdatatypes.check_type('HIDRA project file', hidra_file,
                                  HidraProjectFile)

        # Default mask: get value and set
        default_mask = hidra_file.read_default_masks()
        if default_mask is not None:
            self.set_detector_mask(default_mask, True)

        # User specified mask
        mask_dict = dict()
        hidra_file.read_user_masks(mask_dict)
        for mask_name in mask_dict:
            self.set_detector_mask(mask_dict[mask_name], False, mask_name)
Example #2
0
    def init_session(self, session_name, hidra_ws=None):
        """
        Initialize a new session of reduction and thus to store data according to session name
        :return:
        """
        # Check inputs
        checkdatatypes.check_string_variable('Reduction session name',
                                             session_name)
        if session_name == '':
            raise RuntimeError('Session name {} is empty'.format(session_name))
        elif session_name in self._session_dict:
            print(
                '[WARNING] Session {} is previously taken.  The HidraWorkspace associated '
                'will be replaced if new HidraWorkspace is not None ({})'
                ''.format(session_name, hidra_ws is None))

        if hidra_ws is None:
            # session is initialized without HidraWorkspace
            self._curr_workspace = workspaces.HidraWorkspace()
        else:
            # session starts with a HidraWorkspace
            checkdatatypes.check_type('HidraWorkspace', hidra_ws,
                                      workspaces.HidraWorkspace)
            self._curr_workspace = hidra_ws

        self._session_dict[session_name] = self._curr_workspace
Example #3
0
def generate_mantid_workspace(hidra_workspace, workspace_name, mask_id=None):
    """
    Generate a Mantid MatrixWorkspace from a HidraWorkspace
    :param hidra_workspace:
    :param workspace_name: string for output workspace name
    :param mask_id: Mask index for the reduced diffraction data in HidraWorkspace/HidraProjectFile
    :return:
    """
    # Check inputs
    checkdatatypes.check_type('Hidra workspace', hidra_workspace, workspaces.HidraWorkspace)
    # workspace name:
    if workspace_name is None:
        workspace_name = hidra_workspace.name
    else:
        checkdatatypes.check_string_variable('Workspace name', workspace_name)

    # Get data from HiDRA Workspace
    two_theta_matrix, data_y_matrix, data_e_matrix = hidra_workspace.get_reduced_diffraction_data_set(mask_id)

    # Mantid (2019.11) does not accept NaN
    # Convert all NaN to zero.  No good peak will have NaN or Zero
    data_y_matrix[np.where(np.isnan(data_y_matrix))] = 0.
    data_e_matrix[np.where(np.isnan(data_e_matrix))] = 0.

    # Create Mantid workspace
    matrix_ws = CreateWorkspace(DataX=two_theta_matrix,
                                DataY=data_y_matrix,
                                DataE=data_e_matrix,
                                NSpec=data_y_matrix.shape[0],
                                OutputWorkspace=workspace_name, EnableLogging=False)

    return matrix_ws
Example #4
0
    def load_hidra_project(self, hidra_file, load_raw_counts,
                           load_reduced_diffraction):
        """
        Load HIDRA project file
        :param hidra_file: HIDRA project file instance (not file name)
        :param load_raw_counts: Flag to load raw counts
        :param load_reduced_diffraction: Flag to load reduced diffraction data
        :return:
        """
        # Check input
        checkdatatypes.check_type('HIDRA project file', hidra_file,
                                  HidraProjectFile)
        self._project_file_name = hidra_file.name
        self._project_file = hidra_file

        # create the spectrum map - must exist before loading the counts array
        self._sample_logs.subruns = hidra_file.read_sub_runs()

        # load raw detector counts and load instrument
        if load_raw_counts:
            self._load_raw_counts(hidra_file)
            self._load_instrument(hidra_file)

        # load reduced diffraction
        if load_reduced_diffraction:
            self._load_reduced_diffraction_data(hidra_file)

        # load sample logs
        self._load_sample_logs(hidra_file)

        # load masks
        self._load_masks(hidra_file)

        # load the wave length
        self._load_wave_length(hidra_file)
Example #5
0
def convert_opt_operations(opt_opts):
    """
    Convert a 7-tuple list (long-name, short-name, target name, type, default value, is mandatory, document)
    :param opt_opts: list of operation
    :return: (1) operation_dict  key as either long name --xxx, or short name -x),
                                 value = parameter name, value type  (removed: default value, mandatory)
             (2) list of mandatory parameters
             (3) optional default value dictionary: key = parameter name, value = default default value
             (4) dictionary for helping message: key = parameter name, value = short name, long name, document
    """

    checkdatatypes.check_type('Command options', opt_opts, list)

    # split a 4 tuple to 2 3-tuples
    opt_dict = dict()
    man_param_list = list()
    default_param_dict = dict()
    info_dict = dict()

    for t4 in opt_opts:
        if len(t4) != 7:
            raise RuntimeError(
                'Item {} is not defined properly.  7 and only 7 items are allowed'
            )
        long_name_i, short_name_i, target_name_i, type_i, default_i, mandatory_i, doc_i = t4

        # long/full opt name
        if long_name_i is not None:
            if len(long_name_i) < 2:
                raise RuntimeError(
                    'Long name {} in {} is not allowed. At least 2 letters'
                    ''.format(long_name_i, t4))
            opt_dict['--{}'.format(
                long_name_i
            )] = target_name_i, type_i  # , default_i, mandatory_i

        # short opt name
        if short_name_i is not None:
            if len(short_name_i) != 1:
                raise RuntimeError(
                    'Short name {} in {} is not allowed. 1 and only 1 letter'
                    ''.format(short_name_i, t4))
            opt_dict['-{}'.format(
                short_name_i
            )] = target_name_i, type_i  # , default_i, mandatory_i

        # Mandatory
        if mandatory_i:
            man_param_list.append(target_name_i)
        else:
            default_param_dict[target_name_i] = default_i

        # Information
        info_dict[
            target_name_i] = short_name_i, long_name_i, doc_i, mandatory_i, default_i

    # END-FOR

    return opt_dict, man_param_list, default_param_dict, info_dict
Example #6
0
    def save_reduced_diffraction_data(self, hidra_project):
        """ Export reduced diffraction data to project
        :param hidra_project: HidraProjectFile instance
        :return:
        """
        checkdatatypes.check_type('HIDRA project file', hidra_project,
                                  HidraProjectFile)

        hidra_project.write_reduced_diffraction_data_set(
            self._2theta_matrix, self._diff_data_set, self._var_data_set)
Example #7
0
    def _load_instrument(self, hidra_file):
        """ Load instrument setup from HIDRA file
        :param hidra_file: HIDRA project file instance
        :return:
        """
        # Check
        checkdatatypes.check_type('HIDRA project file', hidra_file,
                                  HidraProjectFile)

        # Get values
        self._instrument_setup = hidra_file.read_instrument_geometry()
Example #8
0
    def set_geometry_calibration(self, geometry_calibration):
        """ Load and apply calibration file
        :param geometry_calibration:
        :return:
        """
        # TODO FIXME - #81 NOWNOW - Still not sure how to apply!
        checkdatatypes.check_type(
            'Geometry calibration', geometry_calibration,
            instrument_geometry.AnglerCameraDetectorShift)

        self._geometry_calibration = geometry_calibration
Example #9
0
    def _load_sample_logs(self, hidra_file):
        """ Load sample logs.
        Note: this method can clear all the sample logs added previously. But it is not
            an issue in the real use cases.
        :param hidra_file:  HIDRA project file instance
        :return:
        """
        checkdatatypes.check_type('HIDRA project file', hidra_file,
                                  HidraProjectFile)

        # overwrite the existing sample logs
        self._sample_logs = hidra_file.read_sample_logs()
Example #10
0
    def _load_raw_counts(self, hidra_file):
        """ Load raw detector counts from HIDRA file
        :param hidra_file:
        :return:
        """
        checkdatatypes.check_type('HIDRA project file', hidra_file,
                                  HidraProjectFile)

        for sub_run_i in self._sample_logs.subruns:
            counts_vec_i = hidra_file.read_raw_counts(sub_run_i)
            self._raw_counts[sub_run_i] = counts_vec_i
        # END-FOR

        return
Example #11
0
    def build_instrument(self, calibration):
        """ Build an instrument for each pixel's position in cartesian coordinate
        :param calibration: DENEXDetectorShift from geometry calibration
        :return: 2D numpy array
        """
        if calibration is not None:
            checkdatatypes.check_type('Instrument geometry calibrated shift',
                                      calibration,
                                      instrument_geometry.DENEXDetectorShift)

        self._instrument.build_instrument(self._detector_2theta,
                                          self._detector_l2,
                                          instrument_calibration=calibration)

        return
Example #12
0
    def _load_wave_length(self, hidra_file):
        """Load wave length from HidraProject file

        Parameters
        ----------
        hidra_file : pyrs.projectfile.file_object.HidraProjectFile
            Project file (instance)

        Returns
        -------
        None

        """
        checkdatatypes.check_type('HIDRA project file', hidra_file,
                                  HidraProjectFile)

        # reset the wave length (dictionary) from HIDRA project file
        self._wave_length = hidra_file.read_wavelengths()
Example #13
0
    def write_instrument_geometry(self, instrument_setup):
        """
        Add instrument geometry and wave length information to project file
        """
        # check inputs
        self._validate_write_operation()
        checkdatatypes.check_type('Instrument geometry setup',
                                  instrument_setup, HidraSetup)

        # write value to instrument
        instrument_group = self._project_h5[HidraConstants.INSTRUMENT]

        # write attributes
        instrument_group.attrs['name'] = instrument_setup.name

        # get the entry for raw instrument setup
        detector_group = instrument_group['geometry setup']['detector']
        raw_geometry = instrument_setup.get_instrument_geometry(False)
        detector_group.create_dataset('L2',
                                      data=numpy.array(
                                          raw_geometry.arm_length))
        det_size = numpy.array(
            instrument_setup.get_instrument_geometry(False).detector_size)
        detector_group.create_dataset('detector size', data=det_size)
        pixel_dimension = list(
            instrument_setup.get_instrument_geometry(False).pixel_dimension)
        detector_group.create_dataset('pixel dimension',
                                      data=numpy.array(pixel_dimension))

        # wave length
        wavelength_group = instrument_group[HidraConstants.GEOMETRY_SETUP][
            HidraConstants.WAVELENGTH]
        try:
            wl = instrument_setup.get_wavelength(None)
        except (NotImplementedError, RuntimeError) as run_err:
            # No wave length from workspace: do nothing
            self._log.error(str(run_err))
            wl = None

        # Set wave length
        if wl is not None:
            wavelength_group.create_dataset('Calibrated',
                                            data=numpy.array([wl]))
Example #14
0
    def __init__(self, detector_setup):
        """Initialization

        Initialization HB2B instrument setup

        Parameters
        ----------
        detector_setup
        """
        # check inputs
        checkdatatypes.check_type('Detector geometry setup', detector_setup, DENEXDetectorGeometry)

        # set for original instrument setup defined by engineering
        self._geometry_setup = detector_setup
        self._single_wave_length = None

        self._geometry_shift = None
        self._calibrated_wave_length = None

        # calibration state
        self._calibration_applied = False
Example #15
0
    def __init__(self, instrument_setup):
        """
        initialization
        :param instrument_setup:
        """
        # check input
        checkdatatypes.check_type('Instrument setup', instrument_setup,
                                  instrument_geometry.DENEXDetectorGeometry)

        # Instrument geometry parameters
        self._instrument_geom_params = instrument_setup

        # Pixels' positions without calibration. It is kept stable upon calibration values (shifts) and arm (000 plane)
        self._raw_pixel_matrix = self._set_uncalibrated_pixels(
        )  # never been used for external client: len(shape) = 3

        self._pixel_matrix = None  # used by external after build_instrument: matrix for pixel positions
        self._pixel_2theta_matrix = None  # matrix for pixel's 2theta value
        self._pixel_eta_matrix = None  # matrix for pixel's eta value

        self._wave_length = None

        return
Example #16
0
    def save_reduced_diffraction_data(self, hidra_project, sub_runs):
        """Save reduced diffraction data to HiDRA project file
        Parameters
        ----------
        hidra_project: HidraProjectFile
            reference to a HyDra project file
        sub_runs: None or list/ndarray(1D)
            None for exporting all or the specified sub runs

        Returns
        -------
        None
        """

        checkdatatypes.check_type('HIDRA project file', hidra_project,
                                  HidraProjectFile)

        if len(self._raw_counts.keys()) == len(sub_runs):
            hidra_project.write_reduced_diffraction_data_set(
                self._2theta_matrix, self._diff_data_set, self._var_data_set)
        else:
            if type(sub_runs) is list:
                sub_runs = numpy.array(sub_runs)

            diff_key = list(self._diff_data_set.keys())[0]
            _diff_data_temp = {}
            _var_data_temp = {}

            # sub_runs - 1 is used to convert sub_run naming into a numpy index
            _diff_data_temp[diff_key] = self._diff_data_set[diff_key][sub_runs
                                                                      - 1]
            _var_data_temp[diff_key] = self._var_data_set[diff_key][sub_runs -
                                                                    1]

            hidra_project.write_reduced_diffraction_data_set(
                self._2theta_matrix[sub_runs - 1], _diff_data_temp,
                _var_data_temp)
Example #17
0
    def apply_shift(self, geometry_shift):
        checkdatatypes.check_type('Detector geometry shift', geometry_shift, DENEXDetectorShift)

        self._arm_length += geometry_shift.center_shift_z
Example #18
0
    def build_instrument(self,
                         two_theta: float,
                         l2: Optional[float] = None,
                         instrument_calibration=None):
        """
        build instrument considering calibration
        step 1: rotate instrument according to the calibration
        step 2: rotate instrument about 2theta
        :param two_theta
        :param l2
        :param instrument_calibration: DENEXDetectorShift or None (no calibration)
        :return:
        """
        # Check input
        two_theta = to_float('2theta', two_theta)
        # Check or set L2
        if l2 is None:
            l2 = self._instrument_geom_params.arm_length
        else:
            l2 = to_float('L2', l2, 1E-2)

        # print('[DB...L101] Build instrument: 2theta = {}, arm = {} (diff to default = {})'
        #       ''.format(two_theta, l2, l2 - self._instrument_geom_params.arm_length))

        # make a copy from raw (constant position)
        self._pixel_matrix = self._raw_pixel_matrix.copy()

        # Check and set instrument calibration
        if instrument_calibration is not None:
            # check type
            checkdatatypes.check_type('Instrument calibration',
                                      instrument_calibration,
                                      instrument_geometry.DENEXDetectorShift)

            # shift center
            self._pixel_matrix[:, :,
                               0] += instrument_calibration.center_shift_x
            self._pixel_matrix[:, :,
                               1] += instrument_calibration.center_shift_y

            # rotation around instrument center
            # get rotation matrix at origin (for flip, spin and vertical): all data from calibration value
            rot_x_flip = instrument_calibration.rotation_x * np.pi / 180.
            rot_y_flip = instrument_calibration.rotation_y * np.pi / 180.
            rot_z_spin = instrument_calibration.rotation_z * np.pi / 180.
            calib_matrix = self.generate_rotation_matrix(
                rot_x_flip, rot_y_flip, rot_z_spin)
            # print ('[DB...BAT] Calibration rotation matrix:\n{}'.format(calib_matrix))
            # and rotate at origin
            self._pixel_matrix = self._rotate_detector(self._pixel_matrix,
                                                       calib_matrix)

            # shift two_theta by offset
            two_theta += instrument_calibration.two_theta_0
        # END-IF-ELSE

        # push to +Z at length of detector arm
        arm_l2 = l2
        if instrument_calibration is not None:
            # Apply the shift on Z (arm length)
            arm_l2 += instrument_calibration.center_shift_z
        # END-IF
        self._pixel_matrix[:, :, 2] += arm_l2

        # rotate detector (2theta) if it is not zero
        self.rotate_detector_2theta(two_theta)

        return self._pixel_matrix
Example #19
0
    def _load_reduced_diffraction_data(self, hidra_file):
        """ Load reduced diffraction data from HIDRA file
        :param hidra_file: HidraProjectFile instance
        :return:
        """
        # Check inputs
        checkdatatypes.check_type('HIDRA project file', hidra_file,
                                  HidraProjectFile)

        # get 2theta value
        try:
            vec_2theta = hidra_file.read_diffraction_2theta_array()
        except KeyError as key_err:
            print(
                '[INFO] Unable to load 2theta vector from HidraProject file due to {}.'
                'It is very likely that no reduced data is recorded.'
                ''.format(key_err))
            return
        # TRY-CATCH

        # Get number of spectra
        num_spec = len(hidra_file.read_sub_runs())

        # Promote to 2theta from vector to array
        if len(vec_2theta.shape) == 1:
            # convert from 1D array to 2D
            tth_size = vec_2theta.shape[0]
            matrix_2theta = numpy.repeat(vec_2theta.reshape(1, tth_size),
                                         num_spec,
                                         axis=0)
        else:
            matrix_2theta = vec_2theta

        # Set value
        self._2theta_matrix = numpy.copy(matrix_2theta)

        # initialize data set for reduced diffraction patterns
        diff_mask_list = hidra_file.read_diffraction_masks()
        for mask_name in diff_mask_list:
            if mask_name == 'main':
                mask_name = None
            self._diff_data_set[mask_name] = numpy.ndarray(
                shape=(num_spec, vec_2theta.shape[0]), dtype='float')
        # END-FOR

        # Load data: all including masks / ROI
        for mask_name in diff_mask_list:
            # force to None
            if mask_name == 'main':
                mask_name = None
            self._diff_data_set[
                mask_name] = hidra_file.read_diffraction_intensity_vector(
                    mask_id=mask_name, sub_run=None)

        # Load data: all including masks / ROI
        for mask_name in diff_mask_list:
            # force to None
            if mask_name == 'main':
                mask_name = None
            self._var_data_set[
                mask_name] = hidra_file.read_diffraction_variance_vector(
                    mask_id=mask_name, sub_run=None)

            if self._var_data_set[mask_name] is None:
                self._var_data_set[mask_name] = numpy.sqrt(
                    self._diff_data_set[mask_name])

        print('[INFO] Loaded diffraction data from {} includes : {}'
              ''.format(self._project_file_name, self._diff_data_set.keys()))