def test_pre_fit(): # No pre-defined elements. Use all possible elements activated at # given energy y0 = synthetic_spectrum() x0 = np.arange(len(y0)) # the following items should appear item_list = ['Ar_K', 'Fe_K', 'compton', 'elastic'] param = get_para() # fit without weights x, y_total, area_v = linear_spectrum_fitting(x0, y0, param, weights=None) for v in item_list: assert v in y_total sum1 = np.sum([v for v in y_total.values()], axis=0) # r squares as a measurement r1 = 1 - np.sum((sum1 - y0)**2) / np.sum((y0 - np.mean(y0))**2) assert r1 > 0.85 # fit with weights w = 1 / np.sqrt(y0 + 1) x, y_total, area_v = linear_spectrum_fitting(x0, y0, param, weights=w) for v in item_list: assert v in y_total sum2 = np.sum([v for v in y_total.values()], axis=0) # r squares as a measurement r2 = 1 - np.sum((sum2 - y0)**2) / np.sum((y0 - np.mean(y0))**2) assert r2 > 0.85
def test_pre_fit(): # No pre-defined elements. Use all possible elements activated at # given energy y0 = synthetic_spectrum() x0 = np.arange(len(y0)) # the following items should appear item_list = ['Ar_K', 'Fe_K', 'compton', 'elastic'] param = get_para() # fit without weights x, y_total, area_v = linear_spectrum_fitting(x0, y0, param, weights=None) for v in item_list: assert_true(v in y_total) sum1 = np.sum([v for v in y_total.values()], axis=0) # r squares as a measurement r1 = 1 - np.sum((sum1-y0)**2)/np.sum((y0-np.mean(y0))**2) assert_true(r1 > 0.85) # fit with weights w = 1/np.sqrt(y0+1) x, y_total, area_v = linear_spectrum_fitting(x0, y0, param, weights=w) for v in item_list: assert_true(v in y_total) sum2 = np.sum([v for v in y_total.values()], axis=0) # r squares as a measurement r2 = 1 - np.sum((sum2-y0)**2)/np.sum((y0-np.mean(y0))**2) assert_true(r2 > 0.85)
def fit_each_pixel_with_nnls(data, params, elemental_lines=None, weights=None): """ Fit a spectrum with a linear model. Parameters ---------- data : array spectrum intensity param : dict fitting parameters elemental_lines : list, optional e.g., ['Na_K', Mg_K', 'Pt_M'] refers to the K lines of Sodium, the K lines of Magnesium, and the M lines of Platinum. If elemental_lines is set as None, all the possible lines activated at given energy will be used. """ param = copy.deepcopy(parameter) if incident_energy is not None: param['coherent_sct_amplitude']['value'] = incident_energy # cut data into proper range low = param['non_fitting_values']['energy_bound_low']['value'] high = param['non_fitting_values']['energy_bound_high']['value'] a0 = param['e_offset']['value'] a1 = param['e_linear']['value'] x, y = define_range(data, low, high, a0, a1) # pixel fitting _, result_dict, area_dict = linear_spectrum_fitting(x, y, elemental_lines=elemental_lines, weighs=weighs) return result_dict
def fit_pixel_per_file_no_multi(dir_path, file_prefix, fileID, param, interpath, save_spectrum=True): """ Single pixel fit of experiment data. No multiprocess is applied. .. warning :: This function is not optimized as it calls linear_spectrum_fitting function, where lots of repeated calculation are processed. Parameters ---------- data : array 3D data of experiment spectrum param : dict fitting parameters Returns ------- dict : fitting values for all the elements """ num_str = "{:03d}".format(fileID) filename = file_prefix + num_str file_path = os.path.join(dir_path, filename) with h5py.File(file_path, "r") as f: data = f[interpath][:] datas = data.shape elist = param["non_fitting_values"]["element_list"].split(", ") elist = [e.strip(" ") for e in elist] non_element = ["compton", "elastic", "background"] total_list = elist + non_element result_map = dict() for v in total_list: if save_spectrum: result_map.update({v: np.zeros([datas[0], datas[1], datas[2]])}) else: result_map.update({v: np.zeros([datas[0], datas[1]])}) for i in range(datas[0]): for j in range(datas[1]): x, result, area_v = linear_spectrum_fitting(data[i, j, :], param, elemental_lines=elist, constant_weight=1.0) for v in total_list: if v in result: if save_spectrum: result_map[v][i, j, :len(result[v])] = result[v] else: result_map[v][i, j] = np.sum(result[v]) return result_map
def find_peak(self, threshv=0.1): """ Run automatic peak finding, and save results as dict of object. Parameters ---------- threshv : float The value will not be shown on GUI if it is smaller than the threshold. """ self.define_range() # in case the energy calibraiton changes self.prefit_x, out_dict, area_dict = linear_spectrum_fitting(self.x0, self.y0, self.param_new) logger.info('Energy range: {}, {}'.format( self.param_new['non_fitting_values']['energy_bound_low']['value'], self.param_new['non_fitting_values']['energy_bound_high']['value'])) prefit_dict = OrderedDict() for k, v in six.iteritems(out_dict): ps = PreFitStatus(z=get_Z(k), energy=get_energy(k), area=area_dict[k], spectrum=v, maxv=np.around(np.max(v), self.max_area_dig), norm=-1, lbd_stat=False) prefit_dict.update({k: ps}) logger.info('Automatic Peak Finding found elements as : {}'.format( list(prefit_dict.keys()))) self.EC.delete_all() self.EC.add_to_dict(prefit_dict)
def fit_pixel_per_file_no_multi(dir_path, file_prefix, fileID, param, interpath, save_spectrum=True): """ Single pixel fit of experiment data. No multiprocess is applied. .. warning :: This function is not optimized as it calls linear_spectrum_fitting function, where lots of repeated calculation are processed. Parameters ---------- data : array 3D data of experiment spectrum param : dict fitting parameters Returns ------- dict : fitting values for all the elements """ num_str = '{:03d}'.format(fileID) filename = file_prefix + num_str file_path = os.path.join(dir_path, filename) with h5py.File(file_path, 'r') as f: data = f[interpath][:] datas = data.shape elist = param['non_fitting_values']['element_list'].split(', ') elist = [e.strip(' ') for e in elist] non_element = ['compton', 'elastic', 'background'] total_list = elist + non_element result_map = dict() for v in total_list: if save_spectrum: result_map.update({v: np.zeros([datas[0], datas[1], datas[2]])}) else: result_map.update({v: np.zeros([datas[0], datas[1]])}) for i in xrange(datas[0]): for j in xrange(datas[1]): x, result, area_v = linear_spectrum_fitting(data[i, j, :], param, elemental_lines=elist, constant_weight=1.0) for v in total_list: if v in result: if save_spectrum: result_map[v][i, j, :len(result[v])] = result[v] else: result_map[v][i, j] = np.sum(result[v]) return result_map