def get_peak_fit_parameter_vec(self, param_name: str, det_id: int) -> np.ndarray: """ get the fitted parameters and return in vector :param param_name: :param det_id: :return: """ det_id = to_int('Detector ID', det_id, min_value=0) param_vec = np.ndarray(shape=(len(self._peak_fit_info_dict[det_id]), ), dtype='float') log_index_list = sorted(self._peak_fit_info_dict[det_id].keys()) for i, log_index in enumerate(log_index_list): try: param_vec[i] = self._peak_fit_info_dict[det_id][log_index][ param_name] except KeyError: raise RuntimeError( 'Parameter {0} is not a key. Candidates are {1} ... {2}' ''.format( param_name, self._peak_fit_info_dict[det_id].keys(), self._peak_fit_info_dict[det_id][log_index].keys())) # END-FOR return param_vec
def has_raw_data(self, sub_run: int) -> bool: """ Check whether a raw file that has been loaded :param sub_run: sub run number (integer) :return: """ sub_run = to_int('Sub run', sub_run, min_value=1) return sub_run in self._raw_counts
def get_spectrum_index(self, sub_run: int) -> Any: """ Get spectrum (index) from sub run number :param sub_run: sub run number (integer) :return: """ sub_run = to_int('Sub run number', sub_run, min_value=0) return self._sample_logs.get_subrun_indices(sub_run)[0]
def get_detector_counts(self, session_name, sub_run: int): """ Get the raw counts from detector of the specified sub run :param session_name: name of the session for locating workspace :param sub_run: sub run number (integer) :return: array of detector counts """ sub_run = to_int('Sub run number', sub_run, min_value=0) workspace = self._session_dict[session_name] return workspace.get_detector_counts(sub_run)
def __init__(self, num_rows: int, num_columns: int, pixel_size_x: float, pixel_size_y: float, arm_length: float, calibrated: bool) -> None: """ Initialization of instrument geometry setup for 1 denex detector :param num_rows: number of rows of pixels in detector (number of pixels per column) :param num_columns: number of columns of pixels in detector (number of pixels per row) :param pixel_size_x: pixel size at X direction (along a row) :param pixel_size_y: pixel size at Y direction (along a column) :param arm_length: arm length :param calibrated: flag whether these values are calibrated """ # check inputs self._arm_length = to_float('Arm length', arm_length, min_value=1E-5) self._pixel_size_x = to_float('Pixel size (x)', pixel_size_x, min_value=1E-7) self._pixel_size_y = to_float('Pixel size (y)', pixel_size_y, min_value=1E-7) self._detector_rows = to_int('Number of rows in detector', num_rows, min_value=1) self._detector_columns = to_int('Number of columns in detector', num_columns, min_value=1) # TODO this isn't used - BUG? checkdatatypes.check_bool_variable('Flag indicating instrument setup been calibrated', calibrated)
def __init__(self, num_pixels=2048**2): """ Initialization as number of pixel :param num_pixels: """ self._num_pixels = to_int('Detector pixel number', num_pixels, 1024**2, 2048**2 + 1) self._mask_array_dict = dict() self._mask_info_dict = dict() # mask ID, original file, target_file self._2theta = None return
def get_pole_figure_1_pt(self, det_id: int, log_index: int) -> Tuple[float, float]: """ get 1 pole figure value determined by detector and sample log index :param det_id: :param log_index: :return: """ det_id = to_int('Detector id', det_id, min_value=0) log_index = to_int('Sample log index', log_index) # get raw parameters' fitted value log_index_vec, pole_figure_vec = self._pole_figure_dict[det_id] # check if log_index != int(log_index_vec[log_index]): raise RuntimeError( 'Log index {0} does not match the value in log index vector') pf_tuple = pole_figure_vec[log_index] alpha = pf_tuple[0] beta = pf_tuple[1] return alpha, beta
def get_detector_2theta(self, sub_run: int) -> float: """ Get 2theta value from sample log This is a special one :param sub_run: sub run number (integer) :return: float number as 2theta """ sub_run = to_int('Sub run number', sub_run, min_value=0) try: two_theta = self._sample_logs[HidraConstants.TWO_THETA, sub_run] except KeyError as key_err: raise RuntimeError( 'Unable to retrieve 2theta value ({}) from sub run {} due to missing key {}.' 'Available sample logs are {}'.format( HidraConstants.TWO_THETA, sub_run, key_err, self._sample_logs.keys())) return two_theta[0] # convert from numpy array of length 1 to a scalar
def read_raw_counts(self, sub_run: int) -> numpy.ndarray: """ get the raw detector counts """ assert self._project_h5 is not None, 'blabla' sub_run = to_int('sun run', sub_run, min_value=0) sub_run_str = '{:04}'.format(sub_run) try: counts = self._project_h5[HidraConstants.RAW_DATA][ HidraConstants.SUB_RUNS][sub_run_str]['counts'].value except KeyError as key_error: err_msg = 'Unable to access sub run {} with key {}: {}\nAvailable runs are: {}' \ ''.format(sub_run, sub_run_str, key_error, self._project_h5[HidraConstants.RAW_DATA][HidraConstants.SUB_RUNS].keys()) raise KeyError(err_msg) return counts
def get_reduced_diffraction_data(self, sub_run: int, mask_id: Optional[str] = None ) -> Tuple[numpy.ndarray, numpy.ndarray]: """Get data set of a single diffraction pattern Parameters ---------- sub_run: int sub run number (integer) mask_id : str or None None (as default main) or ID as a String Returns ------- numpy.ndarray, numpy.ndarray vector 2theta, vector intensity """ # Check inputs # sub run number might start from 0 sub_run = to_int('Sub run number', sub_run, min_value=0) if mask_id is None: # mask_id = 'main' pass else: checkdatatypes.check_string_variable('Mask ID', mask_id) spec_index = self._sample_logs.get_subrun_indices(sub_run)[0] # Vector 2theta vec_2theta = self._2theta_matrix[spec_index][:] # Vector intensity try: vec_intensity = self._diff_data_set[mask_id][spec_index].copy() except KeyError: raise RuntimeError( 'Mask ID {} does not exist in reduced diffraction pattern. ' 'The available masks are {}' ''.format(mask_id, self._diff_data_set.keys())) return vec_2theta, vec_intensity
def get_detector_counts(self, sub_run: int): """Get the detector counts of a sub run (split) Parameters ---------- sub_run : int sub run number Returns ------- numpy.ndarray """ sub_run = to_int('Sub run number', sub_run, min_value=0) # consider 0 as a single sub run if sub_run not in self._raw_counts: raise RuntimeError( 'Sub run {} does not exist in loaded raw counts. FYI loaded ' 'sub runs are {}'.format(sub_run, self._raw_counts.keys())) return self._raw_counts[sub_run]
def append_raw_counts(self, sub_run_number: int, counts_array: numpy.ndarray) -> None: """Add raw detector counts collected in a single scan/Pt Parameters ---------- sub_run_number : int sub run number counts_array : ~numpy.ndarray detector counts """ # check assert self._project_h5 is not None, 'cannot be None' assert self._is_writable, 'must be writable' sub_run_number = to_int('Sub-run index', sub_run_number, min_value=0) # create group scan_i_group = self._project_h5[HidraConstants.RAW_DATA][ HidraConstants.SUB_RUNS].create_group( '{:04}'.format(sub_run_number)) scan_i_group.create_dataset('counts', data=counts_array.reshape(-1))
def add_input_data_set(self, det_id: int, peak_intensity_dict: dict, peak_fit_info_dict: dict, log_dict: dict) -> None: """ set peak intensity log and experiment logs that are required by pole figure calculation :param det_id :param peak_intensity_dict : dictionary (key = scan log index (int), value = peak intensity (float) :param peak_fit_info_dict: dictionary (key = scan log index (int), value = peak fitting information (float) :param log_dict: dictionary (key = scan log index (int), value = dictionary (log name, log value)) :return: """ # check inputs if det_id in self._peak_intensity_dict: raise RuntimeError( 'Detector ID {0} already been added. Must be reset calculator.' ''.format(det_id)) det_id = to_int('Detector ID', det_id, min_value=0) checkdatatypes.check_dict('Peak intensities', peak_intensity_dict) checkdatatypes.check_dict('Peak fitting information', peak_fit_info_dict) checkdatatypes.check_dict('Log values for pole figure', log_dict) # check sample log index if set(peak_intensity_dict.keys()) != set(log_dict.keys()): raise RuntimeError( 'Sample log indexes from peak intensities and sample logs' ' do not match.') # add peak intensity self._peak_intensity_dict[det_id] = peak_intensity_dict # go through all the values for scan_log_index in log_dict: # check each log index (entry) whether there are enough 2theta log_names = log_dict[scan_log_index].keys() checkdatatypes.check_list('Pole figure motor names', log_names, ['2theta', 'chi', 'phi', 'omega']) # END-FOR # set self._peak_info_dict[det_id] = log_dict self._peak_fit_info_dict[det_id] = peak_fit_info_dict
def get_l2(self, sub_run: int) -> float: """ Get L2 for a specific sub run :param sub_run: sub run number (integer) :return: L2 or None (i.e., using default L2) """ sub_run = to_int('Sub run number', sub_run, min_value=0) if HidraConstants.L2 in self._sample_logs: # L2 is a valid sample log: get L2 try: # convert from numpy array of length 1 to a scalar l2 = self._sample_logs[HidraConstants.L2, sub_run][0] except KeyError as key_err: raise RuntimeError( 'Unable to retrieve L2 value for {} due to {}. Available sun runs are {}' .format(sub_run, key_err, self._sample_logs[HidraConstants.L2])) else: # L2 might be unchanged l2 = None return l2
def get_reduced_diffraction_data_2theta(self, sub_run: int) -> numpy.ndarray: """Get 2theta vector of reduced diffraction data Parameters ---------- sub_run : int sub run number Returns ------- numpy.ndarray vector of 2theta """ # Check inputs sub_run = to_int('Sub run number', sub_run, min_value=1) # Get spectrum index spec_index = self._sample_logs.get_subrun_indices(sub_run)[0] # Vector 2theta vec_2theta = self._2theta_matrix[spec_index][:] return vec_2theta
def load_mantid_mask(pixel_number, mantid_mask_xml, is_mask): """ Load Mantid mask file in XML format Assumption: PixelID (detector ID) starts from 0 and there is NO gap :param mantid_mask_xml: :param pixel_number: total pixel number :return: a vector """ checkdatatypes.check_file_name(mantid_mask_xml, True, False, False, 'Mantid XML mask file') pixel_number = to_int('(Total) pixel number', pixel_number, 1024**2, 2048**2 + 1) # load file to lines mask_file = open(mantid_mask_xml, 'r') mask_lines = mask_file.readlines() mask_file.close() # get detector ID range line det_id_line = None for line in mask_lines: if line.count('<detid') > 0: det_id_line = line.strip() break # END-FOR if det_id_line is None: raise RuntimeError( 'Mask file {} does not have masked detector IDs'.format( mantid_mask_xml)) # parse masked_det_pair_list = det_id_line.split('>')[1].split( '<')[0].strip().split(',') # print ('[DB...BAT] Masked detectors range: {}'.format(masked_det_pair_list)) # create vector with 1 (for not masking) masking_array = np.zeros((pixel_number, ), 'float') if is_mask: # is given string are mask then default is not masked masking_array += 1. # is ROI default = 0 masked_specs = 0 for masked_det_pair in masked_det_pair_list: # get range terms = masked_det_pair.split('-') start_detid = int(terms[0]) end_detid = int(terms[1]) # check range if end_detid >= pixel_number: raise RuntimeError( 'Detector ID {} is out of range of given detector size {}' ''.format(end_detid, pixel_number)) # mask or ROI if is_mask: masking_array[start_detid:end_detid + 1] = 0. else: masking_array[start_detid:end_detid + 1] = 1. # stat masked_specs += end_detid - start_detid + 1 # END-FOR print('[DB...CHECK] Masked spectra = {}, Sum of masking array = {}' ''.format(masked_specs, sum(masking_array))) return masking_array
def set_reduced_diffraction_data( self, sub_run: int, mask_id: Optional[str], two_theta_array: numpy.ndarray, intensity_array: numpy.ndarray, variances_array: Optional[numpy.ndarray] = None) -> None: """Set reduced diffraction data to workspace Parameters ---------- sub_run : int sub run number mask_id : None or str mask ID. None for no-mask or masked by default/universal detector masks on edges two_theta_array : numpy.ndarray 2theta bins (center) intensity_array : numpy.ndarray histogrammed intensities variances_array : numpy.ndarray histogrammed variances Returns ------- None """ # Check status of reducer whether sub run number and spectrum are initialized if len(self._sample_logs.subruns) == 0: raise RuntimeError( 'Sub run - spectrum map has not been set up yet!') # Check inputs # sub run number valid or not sub_run = to_int('Sub run number', sub_run, min_value=1) if mask_id is not None: checkdatatypes.check_string_variable('Mask ID', mask_id) # two theta array and intensity array shall match on size if two_theta_array.shape != intensity_array.shape: raise RuntimeError( 'Two theta array (bin centers) must have same dimension as intensity array. ' 'Now they are {} and {}'.format(two_theta_array.shape, intensity_array.shape)) # Set 2-theta 2D array if self._2theta_matrix is None or len(self._2theta_matrix.shape) != 2: # First time set up or legacy from input file: create the 2D array num_sub_runs = len(self._sample_logs.subruns) self._2theta_matrix = numpy.ndarray( shape=(num_sub_runs, two_theta_array.shape[0]), dtype=intensity_array.dtype) # set the diffraction data (2D) array with new dimension num_sub_runs = len(self._sample_logs.subruns) self._diff_data_set[mask_id] = numpy.ndarray( shape=(num_sub_runs, intensity_array.shape[0]), dtype=intensity_array.dtype) if variances_array is None: variances_array = numpy.sqrt(intensity_array) # END-IF # set the diffraction data (2D) array with new dimension num_sub_runs = len(self._sample_logs.subruns) self._var_data_set[mask_id] = numpy.ndarray( shape=(num_sub_runs, variances_array.shape[0]), dtype=variances_array.dtype) elif mask_id not in self._diff_data_set: # A new mask: reset the diff_data_set again num_sub_runs = len(self._sample_logs.subruns) self._diff_data_set[mask_id] = numpy.ndarray( shape=(num_sub_runs, intensity_array.shape[0]), dtype=intensity_array.dtype) # set the diffraction data (2D) array with new dimension num_sub_runs = len(self._sample_logs.subruns) if variances_array is None: raise RuntimeError('Did not expect None for variances') else: self._var_data_set[mask_id] = numpy.ndarray( shape=(num_sub_runs, variances_array.shape[0]), dtype=variances_array.dtype) # END-IF # Get spectrum index from sub run number spec_id = self._sample_logs.get_subrun_indices(sub_run)[0] # Another sanity check on the size of 2theta and intensity if self._2theta_matrix.shape[1] != two_theta_array.shape[0] \ or self._diff_data_set[mask_id].shape[1] != intensity_array.shape[0]: # Need to check if previously set raise RuntimeError( '2theta vector are different between parent method set {} and ' 'reduction engine returned {} OR ' 'Histogram (shape: {}) to set does not match data diffraction data set defined in ' 'worksapce (shape: {})'.format( self._2theta_matrix.shape, two_theta_array.shape, intensity_array.shape[0], self._diff_data_set[mask_id].shape[1])) # END-IF-ELSE # Set 2theta array self._2theta_matrix[spec_id] = two_theta_array # Set intensity self._diff_data_set[mask_id][spec_id] = intensity_array # Set variances self._var_data_set[mask_id][spec_id] = variances_array