def test_fit_cost_contains_correct_numbers(self): peak_table, refit_peak_table, fit_cost = FitGaussianPeaks( InputWorkspace=self.data_ws, PeakGuessTable=self.peak_guess_table, EstimatedPeakSigma=5, MinPeakSigma=3, MaxPeakSigma=12, GeneralFitTolerance=1) chi2 = fit_cost.column(0)[0] poisson = fit_cost.column(1)[0] peak1 = peak_table.row(0) peak2 = peak_table.row(1) yvals = self.gaussian(self.x_values, peak1['centre'], peak1['height'], peak1['sigma']) yvals += self.gaussian(self.x_values, peak2['centre'], peak2['height'], peak2['sigma']) real_chi2 = self.alg_instance.function_difference( self.y_values, yvals, np.sqrt(self.y_values)) real_poisson = self.alg_instance.poisson_cost( self.y_values + self.background, yvals + self.background) self.assertAlmostEqual(real_chi2, chi2, 3) self.assertAlmostEqual(real_poisson, poisson, 3)
def test_algorithm_estimates_fit_window(self): x_val = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22] y_val = [0, 0, 0, 0, 1, 7, 0, 0, 0, 0, 10, 7] ws = CreateWorkspace(x_val * 2, y_val + [0] * len(y_val), NSpec=2) table = CreateEmptyTableWorkspace() table.addColumn("float", "Centre") table.addRow([20]) with mock.patch( 'plugins.algorithms.WorkflowAlgorithms.FitGaussianPeaks.FitGaussianPeaks.' 'estimate_single_parameters') as mock_estimate_params: mock_estimate_params.return_value = None FitGaussianPeaks(InputWorkspace=ws, PeakGuessTable=table, EstimateFitWindow=True, FitWindowSize=11) centre_index = 10 """ win_size in this case is calculated from EstimatePeakSigma and is estimated to be 2 and FitWindowSize is ignored """ win_size = 2 arguements = mock_estimate_params.call_args_list[0][0] self.assertSequenceEqual(list(arguements[0]), x_val) self.assertSequenceEqual(list(arguements[1]), y_val) self.assertEqual(arguements[2], centre_index) self.assertEqual(arguements[3], win_size) self.assertEqual(len(arguements), 4)
def test_algorithm_uses_right_fit_window(self): x_val = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22] y_val = [0, 0, 0, 0, 1, 7, 0, 0, 0, 0, 10, 7] ws = CreateWorkspace(x_val * 2, y_val + [0] * len(y_val), NSpec=2) table = CreateEmptyTableWorkspace() table.addColumn("float", "Centre") table.addRow([20]) with mock.patch( 'plugins.algorithms.WorkflowAlgorithms.FitGaussianPeaks.FitGaussianPeaks.' 'estimate_single_parameters') as mock_estimate_params: mock_estimate_params.return_value = None FitGaussianPeaks(InputWorkspace=ws, PeakGuessTable=table, EstimateFitWindow=False, FitWindowSize=11) centre_index = 10 # win_size is ( FitWindowSize -1)/2 as method estimate_single_parameters expects in this form win_size = 5 arguements = mock_estimate_params.call_args_list[0][0] self.assertSequenceEqual(list(arguements[0]), x_val) self.assertSequenceEqual(list(arguements[1]), y_val) self.assertEqual(arguements[2], centre_index) self.assertEqual(arguements[3], win_size) self.assertEqual(len(arguements), 4)
def test_peak_parameters_are_correct(self): peak_table, refit_peak_table, fit_cost = FitGaussianPeaks( InputWorkspace=self.data_ws, PeakGuessTable=self.peak_guess_table, EstimatedPeakSigma=5, MinPeakSigma=3, MaxPeakSigma=12, GeneralFitTolerance=1) peak1 = peak_table.row(0) peak2 = peak_table.row(1) centre1, height1, sigma1 = peak1['centre'], peak1['height'], peak1[ 'sigma'] centre2, height2, sigma2 = peak2['centre'], peak2['height'], peak2[ 'sigma'] self.assertAlmostEqual(centre1, self.centre[0]) self.assertAlmostEqual(centre2, self.centre[1]) self.assertAlmostEqual(height1, self.height[0]) self.assertAlmostEqual(height2, self.height[1]) self.assertAlmostEqual(sigma1, self.width[0]) self.assertAlmostEqual(sigma2, self.width[1])
def test_algorithm_does_not_throw_an_error_when_no_valid_peaks_fitted( self): x_val = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22] y_val = [0, 0, 0, 0, 1, 7, 0, 0, 0, 0, 10, 7] ws = CreateWorkspace(x_val * 2, y_val + [0] * len(y_val), NSpec=2) table = CreateEmptyTableWorkspace() table.addColumn("float", "Centre") table.addRow([20]) FitGaussianPeaks(InputWorkspace=ws, PeakGuessTable=table) self.assertEqual(mtd["peak_table"].rowCount(), 0) self.assertEqual(mtd["refit_peak_table"].rowCount(), 0)
def test_algorithm_creates_correct_tables(self): FitGaussianPeaks(InputWorkspace=self.data_ws, PeakGuessTable=self.peak_guess_table) self.assertIn('peak_table', mtd) self.assertIn('refit_peak_table', mtd) self.assertIn('fit_cost', mtd) self.assertEqual(list(mtd['peak_table'].getColumnNames()), self.peak_table_header) self.assertEqual(list(mtd['refit_peak_table'].getColumnNames()), self.peak_table_header) self.assertEqual(list(mtd['fit_cost'].getColumnNames()), ['Chi2', 'Poisson'])
def test_algorithm_skips_invalid_peak(self): ws = CreateWorkspace([0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22] * 2, [0, 0, 0, 0, 1, 7, 0, 0, 0, 0, 10, 7] + [0] * 12, NSpec=2) table = CreateEmptyTableWorkspace() table.addColumn("float", "Centre") table.addRow([10]) table.addRow([20]) FitGaussianPeaks(InputWorkspace=ws, PeakGuessTable=table) peak_table = mtd["peak_table"] row = peak_table.row(0) self.assertEqual(mtd["peak_table"].rowCount(), 1) self.assertEqual(mtd["refit_peak_table"].rowCount(), 0) self.assertAlmostEqual(row["centre"], 9.641, places=3) self.assertAlmostEqual(row["error centre"], 0.225, places=3) self.assertAlmostEqual(row["height"], 7.7, places=3) self.assertAlmostEqual(row["error height"], 0.02242, places=3) self.assertAlmostEqual(row["sigma"], 0.8087, places=3) self.assertAlmostEqual(row["error sigma"], 0.1898, places=3) self.assertAlmostEqual(row["area"], 15.6085, places=3) self.assertAlmostEqual(row["error area"], 0.2347, places=3)
def find_good_peaks(self, xvals, peakids, acceptance, bad_peak_to_consider, use_poisson, fit_ws, peak_width_estimate): prog_reporter = Progress(self, start=0.1, end=1.0, nreports=2 + len(peakids)) actual_peaks = [] skipped = 0 cost_idx = 1 if use_poisson else 0 prog_reporter.report('Starting fit') logger.notice('Fitting null hypothesis') peak_table, refit_peak_table, cost = FitGaussianPeaks( InputWorkspace=fit_ws, PeakGuessTable=self.generate_peak_guess_table(xvals, []), CentreTolerance=1.0, EstimatedPeakSigma=peak_width_estimate, MinPeakSigma=self._min_sigma, MaxPeakSigma=self._max_sigma, GeneralFitTolerance=0.1, RefitTolerance=0.001, StoreInADS=False) old_cost = cost.column(cost_idx)[0] for idx, peak_idx in enumerate(peakids): peak_table, refit_peak_table, cost = FitGaussianPeaks( InputWorkspace=fit_ws, PeakGuessTable=self.generate_peak_guess_table( xvals, actual_peaks + [peak_idx]), CentreTolerance=1.0, EstimatedPeakSigma=peak_width_estimate, MinPeakSigma=self._min_sigma, MaxPeakSigma=self._max_sigma, GeneralFitTolerance=0.1, RefitTolerance=0.001, StoreInADS=False) new_cost = cost.column(cost_idx)[0] if use_poisson: # if p_new > p_old, but uses logs cost_change = new_cost - old_cost good_peak_condition = cost_change > np.log(acceptance) else: cost_change = abs(new_cost - old_cost) / new_cost good_peak_condition = (new_cost <= old_cost) and (cost_change > acceptance) if skipped > bad_peak_to_consider: break msg = '' if good_peak_condition: msg = '** peak found, ' skipped = 0 actual_peaks.append(peak_idx) old_cost = new_cost else: skipped += 1 prog_reporter.report('Iteration {}, {} peaks found'.format( idx + 1, len(actual_peaks))) msg += '{} peaks in total. cost={:.2}, cost change={:.5}' logger.information( msg.format(len(actual_peaks), new_cost, cost_change)) peak_table, refit_peak_table, cost = FitGaussianPeaks( InputWorkspace=fit_ws, PeakGuessTable=self.generate_peak_guess_table(xvals, actual_peaks), CentreTolerance=1.0, EstimatedPeakSigma=peak_width_estimate, MinPeakSigma=self._min_sigma, MaxPeakSigma=self._max_sigma, GeneralFitTolerance=0.1, RefitTolerance=0.001, StoreInADS=False) prog_reporter.report('Fitting done') logger.notice( 'Fitting done, {} good peaks and {} refitted peak found'.format( peak_table.rowCount(), refit_peak_table.rowCount())) return actual_peaks, peak_table, refit_peak_table
def test_algorithm_does_not_need_refitting_when_given_good_data(self): peak_table, refit_peak_table, fit_cost = FitGaussianPeaks( InputWorkspace=self.data_ws, PeakGuessTable=self.peak_guess_table) self.assertEqual(0, refit_peak_table.rowCount()) self.assertEqual(2, peak_table.rowCount())
def test_algorithm_with_negative_refit_tolerance_throws(self): with self.assertRaises(Exception): FitGaussianPeaks(InputWorkspace=self.data_ws, PeakGuessTable=self.peak_guess_table, RefitTolerance=-1.0)
def test_algorithm_with_negative_max_peak_sigma_throws(self): with self.assertRaises(Exception): FitGaussianPeaks(InputWorkspace=self.data_ws, PeakGuessTable=self.peak_guess_table, MaxPeakSigma=-1.0)
def test_algorithm_with_bad_input_workspace_throws(self): with self.assertRaises(Exception): FitGaussianPeaks(InputWorkspace='ws-that-does-not-exist')
def test_algorithm_with_negative_general_fit_tolerance_throws(self): with self.assertRaises(ValueError): FitGaussianPeaks(InputWorkspace=self.data_ws, PeakGuessTable=self.peak_guess_table, GeneralFitTolerance=-1.0)
def test_algorithm_with_float_fit_window_throws(self): with self.assertRaises(TypeError): FitGaussianPeaks(InputWorkspace=self.data_ws, PeakGuessTable=self.peak_guess_table, FitWindowSize=5.5)
def test_algorithm_with_fit_window_lower_than_5_throws(self): with self.assertRaises(ValueError): FitGaussianPeaks(InputWorkspace=self.data_ws, PeakGuessTable=self.peak_guess_table, FitWindowSize=3)
def test_algorithm_with_negative_min_peak_sigma_throws(self): with self.assertRaises(ValueError): FitGaussianPeaks(InputWorkspace=self.data_ws, PeakGuessTable=self.peak_guess_table, MinPeakSigma=-1.0)