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
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)
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
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)
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
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
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
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
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
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 ])
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)
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
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
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
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)
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
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)