Пример #1
0
def save_mantid_mask(mask_vec, h5_name, two_theta, note):
    """
    Save a mask vector to
    :param mask_vec:
    :param h5_name:
    :param two_theta:
    :param note:
    :return:
    """
    checkdatatypes.check_numpy_arrays('Mask vector', [mask_vec],
                                      dimension=1,
                                      check_same_shape=False)
    checkdatatypes.check_file_name(h5_name, False, True, False,
                                   'PyRS masking file to export to')
    if two_theta is not None:
        checkdatatypes.check_float_variable('2-theta', two_theta, (-360., 360))
    if note is not None:
        checkdatatypes.check_string_variable('Mask note', note, None)

    # create file
    mask_file = h5py.File(h5_name, 'w')
    # add data set
    mask_data_set = mask_file.create_dataset('mask', data=mask_vec)
    # add attributes
    if two_theta:
        mask_data_set.attrs['2theta'] = two_theta  # '{}'.format(two_theta)
    if note:
        mask_data_set.attrs['note'] = note
    # close file
    mask_file.close()

    return
Пример #2
0
    def set_sample_log(self, log_name, sub_runs, log_value_array):
        """Set sample log value for each sub run, i.e., average value in each sub run

        Parameters
        ----------
        log_name : str
            sample log name
        sub_runs: ndarray
            sub runs with same shape as log_value_array
        log_value_array : ndarray
            log values

        Returns
        -------
        None
        """
        # Check inputs
        checkdatatypes.check_string_variable('Log name', log_name)
        checkdatatypes.check_numpy_arrays('Sub runs and log values',
                                          [sub_runs, log_value_array], 1, True)
        if len(self._sample_logs) > 0:
            self._sample_logs.matching_subruns(sub_runs)
        else:
            self._sample_logs.subruns = numpy.atleast_1d(sub_runs)

        # Set sub runs and log value to dictionary
        self._sample_logs[log_name] = numpy.atleast_1d(log_value_array)
Пример #3
0
    def set_raw_counts(self, raw_count_vec):
        """ Set experimental data (for a sub-run)
        :param raw_count_vec: detector raw counts
        :return:
        """
        checkdatatypes.check_numpy_arrays('Detector (raw) counts',
                                          [raw_count_vec], None, False)

        self._detector_counts = raw_count_vec

        return
Пример #4
0
    def write_sub_runs(self, sub_runs):
        """ Set sub runs to sample log entry
        """
        if isinstance(sub_runs, list):
            sub_runs = numpy.array(sub_runs)
        else:
            checkdatatypes.check_numpy_arrays('Sub run numbers', [sub_runs], 1,
                                              False)

        sample_log_entry = self._project_h5[HidraConstants.RAW_DATA][
            HidraConstants.SAMPLE_LOGS]
        sample_log_entry.create_dataset(HidraConstants.SUB_RUNS, data=sub_runs)
Пример #5
0
    def set_raw_counts(self, sub_run_number, counts):
        """
        Set the raw counts to
        :param sub_run_number: integer for sub run number
        :param counts: ndarray of detector counts
        :return:
        """
        checkdatatypes.check_numpy_arrays('Counts', [counts],
                                          dimension=None,
                                          check_same_shape=False)

        if len(counts.shape) == 2 and counts.shape[1] == 1:
            # 1D array in 2D format: set to 1D array
            counts = counts.reshape((counts.shape[0], ))

        self._raw_counts[int(sub_run_number)] = counts
Пример #6
0
    def set_experimental_data(self, two_theta: float, l2: Optional[float],
                              raw_count_vec):
        """ Set experimental data (for a sub-run)
        :param two_theta: detector position
        :param l2: detector distance from center of rotation
        :param raw_count_vec: detector raw counts
        :return:
        """
        self._detector_2theta = to_float('2-theta', two_theta, -180, 180)

        if l2 is not None:
            l2 = to_float('L2', l2, 1.E-2)
        self._detector_l2 = l2

        checkdatatypes.check_numpy_arrays('Detector (raw) counts',
                                          [raw_count_vec], None, False)
        self._detector_counts = raw_count_vec
Пример #7
0
    def set_experimental_data(self, two_theta, l2, raw_count_vec):
        """ Set experimental data (for a sub-run)
        :param two_theta: detector position
        :param raw_count_vec: detector raw counts
        :return:
        """
        checkdatatypes.check_float_variable('2-theta', two_theta, (-180, 180))
        checkdatatypes.check_numpy_arrays('Detector (raw) counts',
                                          [raw_count_vec], None, False)
        if l2 is not None:
            checkdatatypes.check_float_variable('L2', l2, (1.E-2, None))

        self._detector_2theta = two_theta
        self._detector_l2 = l2
        self._detector_counts = raw_count_vec

        return
Пример #8
0
    def set_counts(self, counts_array, detector_shape):
        """
        set counts with detector shape
        :param counts_array:
        :param detector_shape:
        :return:
        """
        checkdatatypes.check_tuple('Detector shape', detector_shape, 2)
        num_pixels = detector_shape[0] * detector_shape[1]

        checkdatatypes.check_numpy_arrays('Detector counts', [counts_array], 1,
                                          False)
        if counts_array.shape[0] != num_pixels:
            raise RuntimeError(
                'Detector counts array has shape {}.  It does not match '
                'input detector shape {}'.format(counts_array, detector_shape))

        self._counts = counts_array
        self._det_shape = detector_shape

        return
Пример #9
0
    def set_detector_mask(self, mask_array, is_default, mask_id=None):
        """Set mask array to HidraWorkspace

        Record the mask to HidraWorkspace future reference

        Parameters
        ----------
        mask_array : numpy.darray
            mask bit for each pixel
        is_default : bool
            whether this mask is the default mask from beginning
        mask_id : str
            ID for mask

        Returns
        -------

        """
        checkdatatypes.check_numpy_arrays('Detector mask', [mask_array], None,
                                          False)

        # Convert mask to 1D array
        if len(mask_array.shape) == 2:
            # rule out unexpected shape
            if mask_array.shape[1] != 1:
                raise RuntimeError(
                    'Mask array with shape {} is not acceptable'.format(
                        mask_array.shape))
            # convert from (N, 1) to (N,)
            num_pixels = mask_array.shape[0]
            mask_array = mask_array.reshape((num_pixels, ))
        # END-IF

        if is_default:
            self._default_mask = mask_array
        else:
            checkdatatypes.check_string_variable('Mask ID',
                                                 mask_id,
                                                 allow_empty=False)
            self._mask_dict[mask_id] = mask_array
Пример #10
0
    def set_user_grid_parameter_values(self, grid_vec,
                                       mapped_param_value_array, direction):
        """ set the parameter values on user defined grid
        Note: each grid's value is given by a dict with keys (2) value (3) dir (4) scan-index
        :param grid_vec:
        :param mapped_param_value_array: key = position, value is described as note
        :param direction:
        :return:
        """
        checkdatatypes.check_numpy_arrays('Grid position vector', [grid_vec],
                                          2, False)
        checkdatatypes.check_numpy_arrays('Parameter value mapped onto grid',
                                          mapped_param_value_array, 1, False)
        assert grid_vec.shape[0] == mapped_param_value_array.shape[
            0], 'Number of grids shall be same'

        for i_grid in range(grid_vec.shape[0]):
            self.append_row([
                None, grid_vec[i_grid][0], grid_vec[i_grid][1],
                grid_vec[i_grid][2], mapped_param_value_array[i_grid],
                direction
            ])
Пример #11
0
    def add_grid_strain_stress(self, grid_pos, strain_matrix, stress_matrix):
        """
        add a grid with strain and
        :param grid_pos:
        :param strain_matrix:
        :param stress_matrix:
        :return:
        """
        # check inputs
        checkdatatypes.check_numpy_arrays('Grid position', [grid_pos],
                                          dimension=1,
                                          check_same_shape=False)
        checkdatatypes.check_numpy_arrays('Strain and stress matrix',
                                          [strain_matrix, stress_matrix],
                                          dimension=2,
                                          check_same_shape=True)

        line_list = list()
        line_list.extend([pos for pos in grid_pos])
        line_list.extend([strain_matrix[i, i] for i in range(3)])
        line_list.extend([stress_matrix[i, i] for i in range(3)])

        self.append_row(line_list)
Пример #12
0
    def histogram_by_numpy(pixel_2theta_array, pixel_count_array,
                           two_theta_bins, is_point_data, vanadium_counts):
        """Histogram a data set (X, Y) by numpy histogram algorithm

        Assumption:
        1. pixel_2theta_array[i] and vec_counts[i] correspond to the same detector pixel

        Parameters
        ----------
        pixel_2theta_array : ~numpy.ndarray
            2theta (1D) array for each pixel
        pixel_count_array : numpy.ndarray
            count array (1D) for each pixel and paired to pixel_2theta_array
        two_theta_bins : numpy.ndarray
            2-theta bin boundaries
        is_point_data : bool
            Output shall be point data; otherwise, histogram data
        vanadium_counts : None or numpy.ndarray
            Vanadium counts for normalization and efficiency calibration.  It is allowed to be None

        Returns
        -------

        """
        # Check inputs
        checkdatatypes.check_numpy_arrays(
            'Pixel 2theta array, pixel counts array',
            [pixel_2theta_array, pixel_count_array], 1, True)

        # Exclude pixels with no vanadium counts
        if vanadium_counts is not None:
            vanadium_mask = vanadium_counts < 0.9
            pixel_2theta_array = np.ma.masked_where(vanadium_mask,
                                                    pixel_2theta_array)
            pixel_count_array = np.ma.masked_where(vanadium_mask,
                                                   pixel_count_array)
            vanadium_counts = np.ma.masked_where(vanadium_mask,
                                                 vanadium_counts)

        # Exclude NaN and infinity regions
        masked_pixels = (np.isnan(pixel_count_array)) | (
            np.isinf(pixel_count_array))
        pixel_2theta_array = np.ma.masked_where(
            masked_pixels, pixel_2theta_array).compressed()
        pixel_count_array = np.ma.masked_where(masked_pixels,
                                               pixel_count_array).compressed()

        # construct data variance array
        pixel_var_array = np.sqrt(pixel_count_array)
        pixel_var_array[pixel_var_array == 0.0] = 1.

        # Call numpy to histogram raw counts and variance
        data_hist, bin_edges = np.histogram(pixel_2theta_array,
                                            bins=two_theta_bins,
                                            weights=pixel_count_array)
        data_var, var_edges = np.histogram(pixel_2theta_array,
                                           bins=two_theta_bins,
                                           weights=pixel_var_array**2)
        data_var = np.sqrt(data_var)

        # get indexs in histograms that do not have neutron counts
        zero_count_mask = data_hist == 0.0

        # Optionally to normalize by number of pixels (sampling points) in the 2theta bin
        if vanadium_counts is not None:
            # Normalize by vanadium including efficiency calibration
            checkdatatypes.check_numpy_arrays('Vanadium counts',
                                              [vanadium_counts], 1, False)

            # Exclude NaN and infinity regions
            vanadium_counts = np.ma.masked_where(masked_pixels,
                                                 vanadium_counts).compressed()

            # construct vanadium variance array
            vanadium_var = np.sqrt(vanadium_counts)
            vanadium_var[vanadium_var == 0.0] = 1.

            # Call numpy to histogram vanadium counts and variance
            van_hist, be_temp = np.histogram(pixel_2theta_array,
                                             bins=two_theta_bins,
                                             weights=vanadium_counts)
            van_var, van_var_temp = np.histogram(pixel_2theta_array,
                                                 bins=two_theta_bins,
                                                 weights=vanadium_var**2)
            van_var = np.sqrt(van_var)

            # get indexs in histograms with no counts to 1
            data_hist[zero_count_mask] = 1.0
            van_hist[zero_count_mask] = 1.0
            data_var[zero_count_mask] = 1.0
            van_var[zero_count_mask] = 1.0

            # propagation of error
            data_var = np.sqrt((data_var / data_hist)**2 +
                               (van_var / van_hist)**2)

            # Normalize diffraction data
            data_hist /= van_hist  # normalize
            data_var *= data_hist

        # END-IF-ELSE

        # set indexs in histograms that do not have any neutron counts to 0 with var = 1
        data_hist[zero_count_mask] = 0.
        data_var[zero_count_mask] = 1.

        # convert to point data as an option.  Use the center of the 2theta bin as new theta
        if is_point_data:
            # calculate bin centers
            bins = 0.5 * (bin_edges[1:] + bin_edges[:-1])
        else:
            # return bin edges
            bins = bin_edges

        return bins, data_hist, data_var
Пример #13
0
    def reduce_to_2theta_histogram(self,
                                   two_theta_bins,
                                   mask_array,
                                   is_point_data=True,
                                   vanadium_counts_array=None):
        """Reduce the previously added detector raw counts to 2theta histogram (i.e., diffraction pattern)

        Parameters
        ----------
        two_theta_bins : numpy.ndarray
            2theta bin boundaries to binned to
        mask_array : numpy.ndarray or None
            mask: 1 to keep, 0 to mask (exclude)
        is_point_data : bool
            Flag whether the output is point data (numbers of X and Y are same)
        vanadium_counts_array : None or numpy.ndarray
            Vanadium counts array for normalization and efficiency calibration

        Returns
        -------
        numpy.ndarray, numpy.ndarray, numpy.ndarray
            2theta vector, intensity vector, and variances_vector

        """
        # Get two-theta-histogram vector
        checkdatatypes.check_numpy_arrays('2theta array', [two_theta_bins], 1,
                                          False)

        # Get the data (each pixel's 2theta and counts): the 2theta value is the absolute diffraction angle
        # that disregards the real 2theta value in the instrument coordinate system
        pixel_2theta_array = self._instrument.get_pixels_2theta(1)
        checkdatatypes.check_numpy_arrays(
            'Two theta and detector counts array',
            [pixel_2theta_array, self._detector_counts],
            1,
            check_same_shape=True)  # optional check

        # Convert vector counts array's dtype to float
        counts_array = self._detector_counts.astype('float64')

        # print('[INFO] PyRS.Instrument: pixels 2theta range: ({}, {}) vs 2theta histogram range: ({}, {})'
        #       ''.format(pixel_2theta_array.min(), pixel_2theta_array.max(), two_theta_bins.min(),
        #                 two_theta_bins.max()))

        # Apply mask: act on local variable vec_counts and thus won't affect raw data
        if mask_array is not None:
            # mask detector counts, assuming detector mask and counts are in same order of pixel
            checkdatatypes.check_numpy_arrays('Counts vector and mask vector',
                                              [counts_array, mask_array], 1,
                                              True)
            # exclude mask from histogramming
            counts_array = counts_array[np.where(mask_array == 1)]
            pixel_2theta_array = pixel_2theta_array[np.where(mask_array == 1)]
            if vanadium_counts_array is not None:
                vanadium_counts_array = vanadium_counts_array[np.where(
                    mask_array == 1)]
        else:
            # no mask: do nothing
            pass
        # END-IF-ELSE

        # Histogram:
        # NOTE: input 2theta_range may not be accurate because 2theta max may not be on the full 2-theta tick
        # TODO - If use vanadium for normalization, then (1) flag to normalize by pixel count and (2) efficiency
        #        are not required anymore but both of them will be replaced by integrated vanadium counts

        # use numpy.histogram
        two_theta_bins, intensity_vector, variances_vector = self.histogram_by_numpy(
            pixel_2theta_array, counts_array, two_theta_bins, is_point_data,
            vanadium_counts_array)

        # Record
        self._reduced_diffraction_data = two_theta_bins, intensity_vector, variances_vector

        return two_theta_bins, intensity_vector, variances_vector
Пример #14
0
    def generate_2theta_histogram_vector(min_2theta: Optional[float],
                                         num_bins: int,
                                         max_2theta: Optional[float],
                                         pixel_2theta_array,
                                         mask_array,
                                         step_2theta=None):
        """Generate a 1-D array for histogram 2theta bins

        Parameters
        ----------
        min_2theta : float or None
            minimum 2theta or None
        num_bins : int
            number of bins
        max_2theta : float  or None
             maximum 2theta and must be integer
        pixel_2theta_array : numpy.ndarray
            2theta of each detector pixel
        mask_array : numpy.ndarray or None
            array of mask

        Returns
        -------
        numpy.ndarray
            2theta values serving as bin boundaries, such its size is 1 larger than num_bins

        """

        # If default value is required: set the default
        if min_2theta is None or max_2theta is None:
            # check inputs
            if mask_array is None:
                checkdatatypes.check_numpy_arrays('Pixel 2theta angles',
                                                  [pixel_2theta_array], 1,
                                                  False)
            else:
                checkdatatypes.check_numpy_arrays(
                    'Pixel 2theta position and mask array',
                    [pixel_2theta_array, mask_array], 1, True)
                # mask
                pixel_2theta_array = pixel_2theta_array[np.where(
                    mask_array == 1)]

            if min_2theta is None:
                # lower boundary of 2theta for bins is the minimum 2theta angle of all the pixels
                min_2theta = np.min(pixel_2theta_array)
            if max_2theta is None:
                # upper boundary of 2theta for bins is the maximum 2theta angle of all the pixels
                max_2theta = np.max(pixel_2theta_array)

        if step_2theta is None:
            step_2theta = (max_2theta - min_2theta) * 1. / num_bins
        else:
            num_bins = np.ceil((max_2theta - min_2theta) / step_2theta) + 1

        # Check inputs
        min_2theta = to_float('Minimum 2theta', min_2theta, 20, 140)
        max_2theta = to_float('Maximum 2theta', max_2theta, 21, 180)
        step_2theta = to_float('2theta bin size', step_2theta, 0, 180)
        if min_2theta >= max_2theta:
            raise RuntimeError(
                '2theta range ({}, {}) is invalid for generating histogram'
                ''.format(min_2theta, max_2theta))

        # Create 2theta: these are bin edges from (min - 1/2) to (max + 1/2) with num_bins bins
        # and (num_bins + 1) data points
        vec_2theta = np.arange(num_bins + 1).astype(float) * step_2theta + (
            min_2theta - step_2theta)
        if vec_2theta.shape[0] != num_bins + 1:
            raise RuntimeError(
                'Expected = {} vs {}\n2theta min max  = {}, {}\n2thetas: {}'
                ''.format(num_bins, vec_2theta.shape, min_2theta, max_2theta,
                          vec_2theta))

        # Sanity check
        assert vec_2theta.shape[0] == num_bins + 1, '2theta bins (boundary)\'size ({}) shall be exactly ' \
                                                    '1 larger than specified num_bins ({})' \
                                                    ''.format(vec_2theta.shape, num_bins)

        return vec_2theta
Пример #15
0
    def write_reduced_diffraction_data_set(self, two_theta_array,
                                           diff_data_set, var_data_set):
        """Set the reduced diffraction data (set)

        Parameters
        ----------
        two_theta_array : numppy.ndarray
            2D array for 2-theta vector, which could be various to each other among sub runs
        diff_data_set : dict
            dictionary of 2D arrays for reduced diffraction patterns' intensities
        var_data_set : dict
            dictionary of 2D arrays for reduced diffraction patterns' variances
        """
        # Check input
        checkdatatypes.check_numpy_arrays('Two theta vector',
                                          [two_theta_array], 2, False)
        checkdatatypes.check_dict('Diffraction data set', diff_data_set)

        # Retrieve diffraction group
        diff_group = self._project_h5[HidraConstants.REDUCED_DATA]

        # Add 2theta vector
        if HidraConstants.TWO_THETA in diff_group.keys():
            # over write data
            try:
                diff_group[HidraConstants.TWO_THETA][...] = two_theta_array
            except TypeError:
                # usually two theta vector size changed
                del diff_group[HidraConstants.TWO_THETA]
                diff_group.create_dataset(HidraConstants.TWO_THETA,
                                          data=two_theta_array)
        else:
            # new data
            diff_group.create_dataset(HidraConstants.TWO_THETA,
                                      data=two_theta_array)

        # Add Diffraction data
        for mask_id in diff_data_set:
            # Get data
            diff_data_matrix_i = diff_data_set[mask_id]
            self._log.information('Mask {} data set shape: {}'.format(
                mask_id, diff_data_matrix_i.shape))
            # Check
            checkdatatypes.check_numpy_arrays('Diffraction data (matrix)',
                                              [diff_data_matrix_i], None,
                                              False)
            if two_theta_array.shape != diff_data_matrix_i.shape:
                raise RuntimeError(
                    'Length of 2theta vector ({}) is different from intensities ({})'
                    ''.format(two_theta_array.shape, diff_data_matrix_i.shape))
            # Set name for default mask
            if mask_id is None:
                data_name = HidraConstants.REDUCED_MAIN
            else:
                data_name = mask_id

            # Write
            if data_name in diff_group.keys():
                # overwrite
                diff_h5_data = diff_group[data_name]
                try:
                    diff_h5_data[...] = diff_data_matrix_i
                except TypeError:
                    # usually two theta vector size changed
                    del diff_group[data_name]
                    diff_group.create_dataset(data_name,
                                              data=diff_data_matrix_i)
            else:
                # new
                diff_group.create_dataset(data_name, data=diff_data_matrix_i)

        # Add Variances data
        if var_data_set is None:
            var_data_set = diff_data_set
            for mask_id in var_data_set:
                var_data_set[mask_id] = numpy.sqrt(var_data_set[mask_id])

        for mask_id in var_data_set:
            # Get data
            var_data_matrix_i = var_data_set[mask_id]
            self._log.information('Mask {} data set shape: {}'.format(
                mask_id, var_data_matrix_i.shape))
            # Check
            checkdatatypes.check_numpy_arrays('Diffraction data (matrix)',
                                              [var_data_matrix_i], None, False)
            if two_theta_array.shape != var_data_matrix_i.shape:
                raise RuntimeError(
                    'Length of 2theta vector ({}) is different from intensities ({})'
                    ''.format(two_theta_array.shape, var_data_matrix_i.shape))
            # Set name for default mask
            if mask_id is None:
                data_name = HidraConstants.REDUCED_MAIN + '_var'
            else:
                data_name = mask_id + '_var'

            # Write
            if data_name in diff_group.keys():
                # overwrite
                diff_h5_data = diff_group[data_name]
                try:
                    diff_h5_data[...] = var_data_matrix_i
                except TypeError:
                    # usually two theta vector size changed
                    del diff_group[data_name]
                    diff_group.create_dataset(data_name,
                                              data=var_data_matrix_i)
            else:
                # new
                diff_group.create_dataset(data_name, data=var_data_matrix_i)
Пример #16
0
    def histogram_by_numpy(pixel_2theta_array, pixel_count_array,
                           two_theta_bins, is_point_data, vanadium_counts):
        """Histogram a data set (X, Y) by numpy histogram algorithm

        Assumption:
        1. pixel_2theta_array[i] and vec_counts[i] correspond to the same detector pixel

        Parameters
        ----------
        pixel_2theta_array : ~numpy.ndarray
            2theta (1D) array for each pixel
        pixel_count_array : numpy.ndarray
            count array (1D) for each pixel and paired to pixel_2theta_array
        two_theta_bins : numpy.ndarray
            2-theta bin boundaries
        is_point_data : bool
            Output shall be point data; otherwise, histogram data
        vanadium_counts : None or numpy.ndarray
            Vanadium counts for normalization and efficiency calibration.  It is allowed to be None

        Returns
        -------

        """
        # Check inputs
        checkdatatypes.check_numpy_arrays(
            'Pixel 2theta array, pixel counts array',
            [pixel_2theta_array, pixel_count_array], 1, True)

        # Exclude pixels with no vanadium counts
        if vanadium_counts is not None:
            vandium_mask = vanadium_counts < 0.9
            pixel_2theta_array = np.ma.masked_where(vandium_mask,
                                                    pixel_2theta_array)
            pixel_count_array = np.ma.masked_where(vandium_mask,
                                                   pixel_count_array)
            vanadium_counts = np.ma.masked_where(vandium_mask, vanadium_counts)

        # Exclude NaN and infinity regions
        masked_pixels = (np.isnan(pixel_count_array)) | (
            np.isinf(pixel_count_array))
        pixel_2theta_array = np.ma.masked_where(
            masked_pixels, pixel_2theta_array).compressed()
        pixel_count_array = np.ma.masked_where(masked_pixels,
                                               pixel_count_array).compressed()

        # construct variance array
        pixel_var_array = np.sqrt(pixel_count_array)
        pixel_var_array[pixel_var_array == 0.0] = 1.

        # Call numpy to histogram raw counts and variance
        hist, bin_edges = np.histogram(pixel_2theta_array,
                                       bins=two_theta_bins,
                                       weights=pixel_count_array)
        var, var_edges = np.histogram(pixel_2theta_array,
                                      bins=two_theta_bins,
                                      weights=pixel_var_array**2)
        var = np.sqrt(var)

        # Optionally to normalize by number of pixels (sampling points) in the 2theta bin
        if vanadium_counts is not None:
            # Normalize by vanadium including efficiency calibration
            checkdatatypes.check_numpy_arrays('Vanadium counts',
                                              [vanadium_counts], 1, False)

            # Exclude NaN and infinity regions
            vanadium_counts = np.ma.masked_where(masked_pixels,
                                                 vanadium_counts).compressed()

            # construct variance array
            vanadium_var = np.sqrt(vanadium_counts)
            vanadium_var[vanadium_var == 0.0] = 1.

            # Call numpy to histogram vanadium counts and variance
            hist_bin, be_temp = np.histogram(pixel_2theta_array,
                                             bins=two_theta_bins,
                                             weights=vanadium_counts)
            van_var, van_var_temp = np.histogram(pixel_2theta_array,
                                                 bins=two_theta_bins,
                                                 weights=vanadium_var**2)
            van_var = np.sqrt(van_var)

            # Find out the bin where there is either no vanadium count or no pixel's located
            # Mask these bins by NaN
            # make sure it is float
            hist_bin = hist_bin.astype(float)
            hist_bin[np.where(hist_bin < 1E-10)] = np.nan

            # propogation of error
            var = np.sqrt((var / hist)**2 + (van_var / hist_bin)**2)

            # Normalize diffraction data
            hist /= hist_bin  # normalize
            var *= hist

        # END-IF-ELSE

        # convert to point data as an option.  Use the center of the 2theta bin as new theta
        if is_point_data:
            # calculate bin centers
            bins = 0.5 * (bin_edges[1:] + bin_edges[:-1])
        else:
            # return bin edges
            bins = bin_edges

        return bins, hist, var
Пример #17
0
    def reduce_diffraction_data(self,
                                session_name,
                                apply_calibrated_geometry,
                                num_bins,
                                sub_run_list,
                                mask,
                                mask_id,
                                vanadium_counts=None,
                                van_duration=None,
                                normalize_by_duration=True,
                                eta_step=None,
                                eta_min=None,
                                eta_max=None,
                                min_2theta=None,
                                max_2theta=None,
                                delta_2theta=None):
        """Reduce ALL sub runs in a workspace from detector counts to diffraction data

        Parameters
        ----------
        session_name
        apply_calibrated_geometry : ~DENEXDetectorShift or bool
            3 options (1) user-provided DENEXDetectorShift
                                          (2) True (use the one in workspace) (3) False (no calibration)
        num_bins : int
            number of bins
        mask : numpy.ndarray
            Mask
        mask_id : str or None
            ID for mask.  If mask ID is None, then it is the default universal mask applied to all data
        sub_run_list : List of None
            sub runs
        vanadium_counts : None or ~numpy.ndarray
            vanadium counts of each detector pixels for normalization
            If vanadium duration is recorded, the vanadium counts are normalized by its duration in seconds
        eta_step : float
            angular step size for out-of-plane reduction
        eta_min : float
            min angle for out-of-plane reduction
        eta_max : float
            max angle for out-of-plane reduction
        min_2theta : float or None
            min 2theta
        max_2theta : float or None
            max 2theta
        delta_2theta : float or None
            2theta increment in the reduced diffraction data

        Returns
        -------
        None

        """
        # Get workspace
        if session_name is None:  # default as current session/workspace
            workspace = self._curr_workspace
        else:
            workspace = self._session_dict[session_name]

        # Process mask: No mask, Mask ID and mask vector
        default_mask = workspace.get_detector_mask(is_default=True,
                                                   mask_id=None)
        if mask is None:
            # No use mask:  use default detector mask.  It could be None but does not matter
            mask_vec = default_mask
        elif isinstance(mask, str):
            # mask is determined by mask ID
            mask_vec = self.get_mask_vector(mask)
        else:
            # user supplied an array for mask
            checkdatatypes.check_numpy_arrays('Mask', [mask],
                                              dimension=1,
                                              check_same_shape=False)
            mask_vec = mask

        # Operate AND with default mask
        if default_mask is not None:
            mask_vec *= default_mask

        # Apply (or not) instrument geometry calibration shift
        if isinstance(apply_calibrated_geometry,
                      instrument_geometry.DENEXDetectorShift):
            det_pos_shift = apply_calibrated_geometry
        elif apply_calibrated_geometry:
            det_pos_shift = workspace.get_detector_shift()
        else:
            det_pos_shift = None

        print('[DB...BAT] Det Position Shift: {}'.format(det_pos_shift))

        if sub_run_list is None:
            sub_run_list = workspace.get_sub_runs()

        # Determine whether normalization by time is supported
        if normalize_by_duration and not workspace.has_sample_log(
                HidraConstants.SUB_RUN_DURATION):
            raise RuntimeError(
                'Workspace {} does not have sample log {}.  Existing logs are {}'
                ''.format(workspace, HidraConstants.SUB_RUN_DURATION,
                          workspace.get_sample_log_names()))

        # Reset workspace's 2theta matrix and intensities
        workspace.reset_diffraction_data()

        for sub_run in sub_run_list:
            # get the duration
            if normalize_by_duration:
                duration_i = workspace.get_sample_log_value(
                    HidraConstants.SUB_RUN_DURATION, sub_run)
            else:
                # not normalized
                duration_i = 1.

            if eta_step is None:
                # reduce sub run
                self.reduce_sub_run_diffraction(
                    workspace,
                    sub_run,
                    det_pos_shift,
                    mask_vec_tuple=(mask_id, mask_vec),
                    min_2theta=min_2theta,
                    max_2theta=max_2theta,
                    num_bins=num_bins,
                    delta_2theta=delta_2theta,
                    sub_run_duration=duration_i,
                    vanadium_counts=vanadium_counts,
                    van_duration=van_duration)
            else:
                # reduce sub run texture
                self.reduce_sub_run_texture(workspace,
                                            sub_run,
                                            det_pos_shift,
                                            mask_vec_tuple=(mask_id, mask_vec),
                                            min_2theta=min_2theta,
                                            max_2theta=max_2theta,
                                            num_bins=num_bins,
                                            sub_run_duration=duration_i,
                                            vanadium_counts=vanadium_counts,
                                            van_duration=van_duration,
                                            eta_step=eta_step,
                                            eta_min=eta_min,
                                            eta_max=eta_max,
                                            delta_2theta=delta_2theta)