def test_2_gaussian_1_subrun(setup_1_subrun, fit_domain): """Fit 2 Gaussian peaks for 1 sub run Returns ------- """ fit_engine = PeakFitEngineFactory.getInstance( setup_1_subrun['workspace'], peak_function_name='Gaussian', background_function_name='Linear', wavelength=np.nan) # Fit fit_result = fit_engine.fit_multiple_peaks(peak_tags=['Left', 'Right'], x_mins=fit_domain[0], x_maxs=fit_domain[1]) number_of_peakCollection = 2. # Test the fitted parameters: effective parameters # Effective parameter list: ['Center', 'Height', 'Intensity', 'FWHM', 'Mixing', 'A0', 'A1'] # Read data sub_runs = fit_result.peakcollections[0].sub_runs fit_costs = fit_result.peakcollections[0].fitting_costs eff_param_values, eff_param_errors = fit_result.peakcollections[ 0].get_effective_params() assert eff_param_values.size == 1, '1 sub run' assert len(eff_param_values.dtype.names) == 7, '7 effective parameters' ''' if abs(eff_param_values[2][0] - expected_intensity) < 1E-03: plt.plot(data_x, data_y, label='Test 2 Gaussian') plt.plot(model_x, model_y, label='Fitted Gaussian') plt.legend() plt.show() raise AssertionError('Peak intensity {} shall be equal to {}.' ''.format(eff_param_values[2, 0], expected_intensity)) ''' # Test the fitted parameters: native parameters native_params = PeakShape.GAUSSIAN.native_parameters native_params.extend(BackgroundFunction.LINEAR.native_parameters) sub_runs2 = fit_result.peakcollections[0].sub_runs fit_cost2 = fit_result.peakcollections[0].fitting_costs param_values, param_errors = fit_result.peakcollections[ 0].get_native_params() parameters = setup_1_subrun['parameters'][0] # Test assert sub_runs.size == 1 == sub_runs2.size np.testing.assert_equal(fit_cost2, fit_costs) np.testing.assert_equal(eff_param_values['Center'], param_values['PeakCentre']) np.testing.assert_allclose(eff_param_values['Center'], parameters['peak_center'], rtol=2e-2, err_msg='Peak center is not correct') # Parameters verified assert_checks(fit_result, parameters, param_values, number_of_peakCollection)
def test_retrieve_fit_metadata(source_project_file, output_project_file, peak_type, peak_info): """A full set of test including loading project, fitting peaks, write fitting result and exporting fitting result and calculated peaks Parameters ---------- source_project_file output_project_file peak_type peak_info Returns ------- """ if os.path.exists(source_project_file) is False: pytest.skip('{} does not exist on Travis'.format(source_project_file)) # Create calibration control controller = pyrscore.PyRsCore() # Load project file to HidraWorkspace project_name = 'Jean Peaks' hd_ws = controller.load_hidra_project(source_project_file, project_name=project_name, load_detector_counts=False, load_diffraction=True) # set wave length # TODO : @Jean please find out the correct value hd_ws.set_wavelength(1.071, False) # Set peak fitting engine # create a controller from factory fit_engine = PeakFitEngineFactory.getInstance( hd_ws, peak_function_name=peak_type, background_function_name='Linear') # Fit peak fit_result = fit_engine.fit_peaks(peak_tag=peak_info.tag, x_min=peak_info.left_bound, x_max=peak_info.right_bound) # Retrieve all effective peak parameters peakcollection = fit_result.peakcollections[0] eff_param_value_array, eff_param_error_array = peakcollection.get_effective_params( ) # result file ref_h5 = h5py.File(output_project_file, 'w') peak_entry = ref_h5.create_group(peak_info.tag) peak_entry.create_dataset('Center', data=eff_param_value_array['Center']) peak_entry.create_dataset('Height', data=eff_param_value_array['Height']) peak_entry.create_dataset('FWHM', data=eff_param_value_array['FWHM']) peak_entry.create_dataset('Mixing', data=eff_param_value_array['Mixing']) peak_entry.create_dataset('Intensity', data=eff_param_value_array['Intensity']) ref_h5.close()
def test_3_gaussian_3_subruns(target_values): """Test fitting 3 Gaussian peaks may or may not on a 3 sub runs This is an extreme case such that sub run = 1: peak @ 75 X in [68, 78] sub run = 2: peak @ 75 and @ 80 X in [72, 82] sub run = 3: peak @ 80 and @ 85 X in [78, 88] Returns ------- """ # Create dictionary for test data for 3 sub runs test_2g_dict = dict() # sub run 1 vec_x_0 = np.arange(500).astype(float) * 0.02 + 68. vec_y_0 = generate_test_gaussian(vec_x_0, [75.], [3.], [10.])['values'] test_2g_dict[1] = vec_x_0, vec_y_0 # sub run 2 vec_x_1 = np.arange(500).astype(float) * 0.02 + 72. vec_y_1 = generate_test_gaussian(vec_x_1, [75., 80], [3., 3.5], [15., 5])['values'] test_2g_dict[2] = vec_x_1, vec_y_1 # sub run 3 vec_x_2 = np.arange(500).astype(float) * 0.02 + 78. vec_y_2 = generate_test_gaussian(vec_x_2, [80., 85], [3.5, 3.7], [0.2, 7.5])['values'] test_2g_dict[3] = vec_x_2, vec_y_2 # Create a workspace based on this test_hd_ws = generate_hydra_workspace_multiple_sub_runs('3 G 3 S', test_2g_dict) # Fit fit_engine = PeakFitEngineFactory.getInstance(test_hd_ws, peak_function_name='Gaussian', background_function_name='Linear', wavelength=np.nan) fit_result = fit_engine.fit_multiple_peaks(peak_tags=['Left', 'Middle', 'Right'], x_mins=(72.5, 77.5, 82.5), x_maxs=(77.5, 82.5, 87.5)) # Verify fitting result # ['Height', 'PeakCentre', 'Sigma'], gaussian_native_params = PeakShape.GAUSSIAN.native_parameters gaussian_native_params.extend(BackgroundFunction.LINEAR.native_parameters) # peak 'Left' fit_cost2_lp = fit_result.peakcollections[0].fitting_costs param_values_lp, param_errors_lp = fit_result.peakcollections[0].get_native_params() # Parameters verified np.testing.assert_allclose(param_values_lp['Height'][0], target_values['peak_center'][0], rtol=50.0) np.testing.assert_allclose(param_values_lp['Sigma'][0], target_values['sigma'][0], rtol=50.0) np.testing.assert_allclose(param_values_lp['A0'][0], target_values['background_A0'][0], rtol=50.0) np.testing.assert_allclose(param_values_lp['A1'][0], target_values['background_A1'][0], rtol=50.0) assert np.isinf(fit_cost2_lp[2]), 'Sub run 3 does not have peak @ 75 (Peak-Left). Chi2 shall be infinity but' \ ' not {}'.format(fit_cost2_lp[2])
def test_1_gaussian_1_subrun(setup_1_subrun, fit_domain): """Test fitting single Gaussian peak on 1 spectrum with background Returns ------- None """ # initialize fit engine fit_engine = PeakFitEngineFactory.getInstance(setup_1_subrun['workspace'], peak_function_name='Gaussian', background_function_name='Linear', wavelength=np.nan, out_of_plane_angle=None) # Fit peak_tag = 'UnitTestGaussian' fit_result = fit_engine.fit_peaks(peak_tag=peak_tag, x_min=fit_domain[0], x_max=fit_domain[1]) number_of_peakCollection = 1 # get back the peak collection peakcollection = fit_result.peakcollections[0] assert peakcollection.peak_tag == peak_tag parameters = setup_1_subrun['parameters'][0] # Test the fitted parameters fit_costs = peakcollection.fitting_costs sub_runs = peakcollection.sub_runs eff_param_values, eff_param_errors = peakcollection.get_effective_params() assert eff_param_values.dtype.names[0] == 'Center' np.testing.assert_almost_equal(eff_param_values['Center'], parameters['peak_center'], decimal=1) print_peak_results_and_check_positive(eff_param_values, eff_param_errors) # Read data again for raw data native_params = PeakShape.GAUSSIAN.native_parameters native_params.extend(BackgroundFunction.LINEAR.native_parameters) # assert_checks(fit_result, native_params, number_of_peakCollection, peak_tag, # peak_center, peak_intensity, peak_FWHM, background_A0, baclground_A1) sub_runs2 = peakcollection.sub_runs fit_cost2 = peakcollection.fitting_costs param_values, param_errors = peakcollection.get_native_params() # Test assert sub_runs.size == 1 == sub_runs2.size np.testing.assert_equal(fit_cost2, fit_costs) # Effective parameter list: ['Center', 'Height', 'Intensity', 'FWHM', 'Mixing', 'A0', 'A1'] assert eff_param_values['Center'] == param_values['PeakCentre'] # center np.testing.assert_allclose(param_values['PeakCentre'], parameters['peak_center'], rtol=3e-2, err_msg='Peak center is not correct') # Parameters verified assert_checks(fit_result, parameters, param_values, number_of_peakCollection) # fit goodness assert fit_costs[0] < 2.0, 'Fit cost (chi2 = {}) is too large'.format(fit_costs[0]) # TODO was 0.5
def test_improve_quality(): """This is a test to improve the quality of peak fitting. Data are from the real HB2B data previously reported problematic Returns ------- """ # Define HiDRA project file name and skip test if it does not exist (on Travis) project_file_name = '/HFIR/HB2B/IPTS-22731/shared/autoreduce/HB2B_1060.h5' if not os.path.exists(project_file_name): pytest.skip('{} does not exist on Travis'.format(project_file_name)) # Create calibration control controller = pyrscore.PyRsCore() # Load project file to HidraWorkspace project_name = 'Jean Peaks' hd_ws = controller.load_hidra_project(project_file_name, project_name=project_name, load_detector_counts=False, load_diffraction=True) # set wave length # TODO : @Jean please find out the correct value wavelength = 1.071 hd_ws.set_wavelength(wavelength, False) peak_type = 'Gaussian' # Set peak fitting engine # create a controller from factory fit_engine = PeakFitEngineFactory.getInstance( hd_ws, peak_function_name=peak_type, background_function_name='Linear', wavelength=wavelength) # Fit peak @ left peak_info_left = PeakInfo(91.7, 87., 93., 'Left Peak') fit_result = fit_engine.fit_peaks(peak_tag=peak_info_left.tag, x_min=peak_info_left.left_bound, x_max=peak_info_left.right_bound) assert fit_result # Fit the right peak peak_info_left = PeakInfo(95.8, 93.5, 98.5, 'Right Peak') fit_engine.fit_peaks(peak_tag=peak_info_left.tag, x_min=peak_info_left.left_bound, x_max=peak_info_left.right_bound)
def fit_multi_peaks(self): QApplication.setOverrideCursor(Qt.WaitCursor) _peak_range_list = [ tuple(_range) for _range in self.parent._ui_graphicsView_fitSetup.list_peak_ranges ] _peak_center_list = [ np.mean([left, right]) for (left, right) in _peak_range_list ] _peak_tag_list = [ "peak{}".format(_index) for _index, _ in enumerate(_peak_center_list) ] _peak_function_name = str( self.parent.ui.comboBox_peakType.currentText()) _peak_xmin_list = [left for (left, _) in _peak_range_list] _peak_xmax_list = [right for (_, right) in _peak_range_list] # Fit peak hd_ws = self.parent.hidra_workspace _wavelength = hd_ws.get_wavelength(True, True) fit_engine = PeakFitEngineFactory.getInstance(hd_ws, _peak_function_name, 'Linear', wavelength=_wavelength) fit_result = fit_engine.fit_multiple_peaks(_peak_tag_list, _peak_xmin_list, _peak_xmax_list) self.parent.fit_result = fit_result self.parent.populate_fit_result_table(fit_result=fit_result) # self.parent.update_list_of_2d_plots_axis() o_gui = GuiUtilities(parent=self.parent) o_gui.set_1D_2D_axis_comboboxes(with_clear=True, fill_raw=True, fill_fit=True) o_gui.initialize_combobox() o_gui.enabled_export_csv_widgets(enabled=True) o_gui.enabled_2dplot_widgets(enabled=True) o_plot = Plot(parent=self.parent) o_plot.plot_2d() QApplication.restoreOverrideCursor()
def test_pseudovoigt_HB2B_1060(target_values): """This is a test of Pseudovoigt peak fitting for HB2B 1060. Data are from the real HB2B data previously reported problematic """ # Define HiDRA project file name and skip test if it does not exist (on Travis) project_file_name = 'tests/data/HB2B_1060_first3_subruns.h5' if not os.path.exists(project_file_name): pytest.skip('{} does not exist on Travis'.format(project_file_name)) # Create calibration control controller = pyrscore.PyRsCore() # Load project file to HidraWorkspace project_name = 'HB2B_1060 Peaks' hd_ws = controller.load_hidra_project(project_file_name, project_name=project_name, load_detector_counts=False, load_diffraction=True) peak_type = 'PseudoVoigt' # Set peak fitting engine # create a controller from factory fit_engine = PeakFitEngineFactory.getInstance( hd_ws, peak_function_name=peak_type, background_function_name='Linear', wavelength=np.nan) # Fit peak @ left and right peak_info_left = PeakInfo(91.7, 87., 93., 'Left Peak') peak_info_right = PeakInfo(95.8, 93.5, 98.5, 'Right Peak') fit_result = fit_engine.fit_multiple_peaks( peak_tags=[peak_info_left.tag, peak_info_right.tag], x_mins=[peak_info_left.left_bound, peak_info_right.left_bound], x_maxs=[peak_info_left.right_bound, peak_info_right.right_bound]) assert len(fit_result.peakcollections) == 2, 'two PeakCollection' assert fit_result.fitted assert fit_result.difference # peak 'Left' param_values_lp, _ = fit_result.peakcollections[0].get_native_params() # peak 'Right' param_values_rp, _ = fit_result.peakcollections[1].get_native_params() assert param_values_lp.size == 3, '3 subruns' assert len(param_values_lp.dtype.names) == 6, '6 native parameters' assert param_values_rp.size == 3, '3 subruns' assert len(param_values_rp.dtype.names) == 6, '6 native parameters' np.testing.assert_allclose(param_values_lp['Intensity'], target_values['Intensity'][0], atol=0.9) np.testing.assert_allclose(param_values_lp['PeakCentre'], target_values['peak_center'][0], atol=0.8) np.testing.assert_allclose(param_values_lp['FWHM'], target_values['FWHM'][0], atol=1.) np.testing.assert_allclose(param_values_lp['A0'], target_values['background_A0'][0], atol=1.) np.testing.assert_allclose(param_values_lp['A1'], target_values['background_A1'][0], atol=1.) np.testing.assert_allclose(param_values_rp['Intensity'], target_values['Intensity'][1], atol=0.01) np.testing.assert_allclose(param_values_rp['PeakCentre'], target_values['peak_center'][1], atol=1) np.testing.assert_allclose(param_values_rp['FWHM'], target_values['FWHM'][1], atol=1.2) np.testing.assert_allclose(param_values_rp['A0'], target_values['background_A0'][1], atol=1.) np.testing.assert_allclose(param_values_rp['A1'], target_values['background_A1'][1], atol=1.)
def test_1_pv_1_subrun(setup_1_subrun, fit_domain): """ Test fitting single Pseudo-voigt peak with background Returns ------- None """ # Generate test workspace and initialize fit engine fit_engine = PeakFitEngineFactory.getInstance( setup_1_subrun['workspace'], peak_function_name='PseudoVoigt', background_function_name='Linear', wavelength=np.nan) # Fit peak_tag = 'UnitTestPseudoVoigt' fit_result = fit_engine.fit_peaks(peak_tag=peak_tag, x_min=fit_domain[0], x_max=fit_domain[1]) number_of_peakCollection = 1. # get back the peak collection peakcollection = fit_result.peakcollections[0] assert peakcollection.peak_tag == peak_tag parameters = setup_1_subrun['parameters'][0] # Test the fitted parameters sub_runs = peakcollection.sub_runs eff_param_values, eff_param_errors = peakcollection.get_effective_params() fit_costs = peakcollection.fitting_costs assert eff_param_values.dtype.names[0] == 'Center' np.testing.assert_almost_equal(eff_param_values['Center'], parameters['peak_center'], decimal=1) print_peak_results_and_check_positive(eff_param_values, eff_param_errors) # Read data again for raw data native_params = PeakShape.PSEUDOVOIGT.native_parameters native_params.extend(BackgroundFunction.LINEAR.native_parameters) sub_runs2 = peakcollection.sub_runs fit_cost2 = peakcollection.fitting_costs param_values, param_errors = peakcollection.get_native_params() print('Ordered native parameters: {}'.format(native_params)) # Test assert sub_runs.shape == (1, ) == sub_runs2.shape assert np.allclose(fit_cost2, fit_costs, 0.0000001) # Effective parameter list: ['Center', 'Height', 'Intensity', 'FWHM', 'Mixing', 'A0', 'A1'] # Native parameters: ['Mixing', 'Intensity', 'PeakCentre', 'FWHM', 'A0', 'A1'] assert eff_param_values['Mixing'] == param_values['Mixing'] # mixing assert eff_param_values['Center'] == param_values['PeakCentre'] # center assert eff_param_values['Intensity'] == param_values[ 'Intensity'] # intensity assert_checks(fit_result, parameters, param_values, number_of_peakCollection, peak_profile_type='PseudoVoigt') if fit_costs[0] > 1.0: # Plot model_x = fit_result.fitted.readX(0) model_y = fit_result.fitted.readY(0) data_x, data_y = setup_1_subrun[ 'workspace'].get_reduced_diffraction_data(1, None) assert data_x.shape == model_x.shape assert data_y.shape == model_y.shape plt.clf() plt.plot(data_x, data_y, label='Test 2 Gaussian 3 sub runs') plt.plot(model_x, model_y, label='Fitted 2 Gaussian 3 sub runs') plt.legend() # plt.show() raise AssertionError( 'Fit cost (chi2 = {}) is too large (criteria = 1.)'.format( fit_costs[0]))
def test_2_gaussian_3_subruns(target_values): """Testing fitting 2 Gaussian peaks among 3 sub runs. Some of the sub runs may not have one specific peak or the peak may be off center too much. This is an extreme case such that sub run = 1: peak @ 75 and @ 83 sub run = 2: peak @ 75 and @ 80 sub run = 3: peak @ 75 very low and @ 80 Returns ------- None """ # Generate 3 sub runs vec_x = np.arange(750).astype(float) * 0.02 + 70. # Create dictionary for test data test_2g_dict = dict() # sub run 1 vec_y = generate_test_gaussian(vec_x, [75., 83], [3., 3.5], [10., 5])['values'] test_2g_dict[1] = vec_x, vec_y # sub run 2 vec_y = generate_test_gaussian(vec_x, [75., 80], [3., 3.5], [15., 5])['values'] test_2g_dict[2] = vec_x, vec_y # sub run 3 vec_y = generate_test_gaussian(vec_x, [75., 80], [3.1, 3.5], [0.2, 7.5])['values'] test_2g_dict[3] = vec_x, vec_y # Create a workspace based on this test_hd_ws = generate_hydra_workspace_multiple_sub_runs( '3 G 3 S', test_2g_dict) # Fit fit_engine = PeakFitEngineFactory.getInstance( test_hd_ws, peak_function_name='Gaussian', background_function_name='Linear', wavelength=np.nan) fit_result = fit_engine.fit_multiple_peaks(peak_tags=['Left', 'Right'], x_mins=(72.5, 77.5), x_maxs=(77.5, 82.5)) # were there returns assert len(fit_result.peakcollections) == 2, 'Two PeakCollection' assert fit_result.fitted assert fit_result.difference # Verify fitting result # ['Height', 'PeakCentre', 'Sigma'], gaussian_native_params = PeakShape.GAUSSIAN.native_parameters gaussian_native_params.extend(BackgroundFunction.LINEAR.native_parameters) # peak 'Left' param_values_lp, param_errors_lp = fit_result.peakcollections[ 0].get_native_params() # peak 'Right' param_values_rp, param_errors_rp = fit_result.peakcollections[ 1].get_native_params() """ Left Chi2: [0.3144778 0.32581177 0.31288937] Height (0) [ 9.75107193 15.30580711 0.10662809] [0.34154591 0.34128258 0.25921181] Center (1) [74.99655914 74.99921417 76.14541626] [0.0059319 0.00377185 0.75386631] Sigma (2) [0.14838572 0.14782989 0.28031287] [0.00608054 0.00388058 0.85695982] Right Chi2: [0.32870555 0.33221155 0.32712516] Note: chi2[0] can be infinity sometimes Height [0.41185206 4.91072798 7.52280378] [0.6211102 0.31933406 0.30802685] Center [78.88805389 79.9979248 80.00099945] [0.0767037 0.01266132 0.00856138] Sigma [0.04440744 0.17071389 0.18304431] [0.07783635 0.01304373 0.00897603] """ # Get effective peak parameters effective_param_values, effective_param_errors = fit_result.peakcollections[ 0].get_effective_params() assert effective_param_values.size == 3, '3 subruns' assert len( effective_param_values.dtype.names) == 7, '7 effective parameters' # TODO it is odd that there are only two in the the setup function and 3 in the result np.testing.assert_allclose(param_values_lp['Height'][:2], target_values['peak_height'], atol=20.) np.testing.assert_allclose(param_values_lp['PeakCentre'][:2], target_values['peak_center'], rtol=50.) np.testing.assert_allclose(param_values_lp['Sigma'][:2], target_values['sigma'], rtol=50.) np.testing.assert_allclose(param_values_lp['A0'][:2], target_values['background_A0'], rtol=50.) np.testing.assert_allclose(param_values_lp['A1'][:2], target_values['background_A1'], rtol=50.) effective_param_values, effective_param_errors = fit_result.peakcollections[ 1].get_effective_params() assert effective_param_values.size == 3, '3 subruns' assert len( effective_param_values.dtype.names) == 7, '7 effective parameters'