33
33
#include " MantidKernel/IValidator.h"
34
34
#include " MantidKernel/ListValidator.h"
35
35
#include " MantidKernel/StartsWithValidator.h"
36
+ #include " MantidKernel/VectorHelper.h"
36
37
37
38
#include " boost/algorithm/string.hpp"
38
39
#include " boost/algorithm/string/trim.hpp"
@@ -82,6 +83,7 @@ const std::string OUTPUT_WKSP_PARAM_ERRS("OutputParameterFitErrorsWorkspace");
82
83
const std::string RAW_PARAMS (" RawPeakParameters" );
83
84
const std::string PEAK_MIN_SIGNAL_TO_NOISE_RATIO (" MinimumSignalToNoiseRatio" );
84
85
const std::string PEAK_MIN_TOTAL_COUNT (" MinimumPeakTotalCount" );
86
+ const std::string PEAK_MIN_SIGNAL_TO_SIGMA_RATIO (" MinimumSignalToSigmaRatio" );
85
87
} // namespace PropertyNames
86
88
} // namespace
87
89
@@ -431,6 +433,10 @@ void FitPeaks::init() {
431
433
" Used for validating peaks before fitting. If the total peak window Y-value count "
432
434
" is under this value, the peak will be excluded from fitting and calibration." );
433
435
436
+ declareProperty (PropertyNames::PEAK_MIN_SIGNAL_TO_SIGMA_RATIO, 0 .,
437
+ " Used for validating peaks before fitting. If the signal-to-sigma ratio is under this value, "
438
+ " the peak will be excluded from fitting and calibration." );
439
+
434
440
const std::string addoutgrp (" Analysis" );
435
441
setPropertyGroup (PropertyNames::OUTPUT_WKSP_PARAMS, addoutgrp);
436
442
setPropertyGroup (PropertyNames::OUTPUT_WKSP_MODEL, addoutgrp);
@@ -445,7 +451,7 @@ std::map<std::string, std::string> FitPeaks::validateInputs() {
445
451
map<std::string, std::string> issues;
446
452
447
453
// check that min/max spectra indices make sense - only matters if both are specified
448
- if (!(isDefault (PropertyNames::START_WKSP_INDEX) && isDefault (PropertyNames::START_WKSP_INDEX ))) {
454
+ if (!(isDefault (PropertyNames::START_WKSP_INDEX) && isDefault (PropertyNames::STOP_WKSP_INDEX ))) {
449
455
const int startIndex = getProperty (PropertyNames::START_WKSP_INDEX);
450
456
const int stopIndex = getProperty (PropertyNames::STOP_WKSP_INDEX);
451
457
if (startIndex > stopIndex) {
@@ -922,6 +928,11 @@ void FitPeaks::processInputPeakTolerance() {
922
928
m_minSignalToNoiseRatio = getProperty (PropertyNames::PEAK_MIN_SIGNAL_TO_NOISE_RATIO);
923
929
if (isEmpty (m_minSignalToNoiseRatio) || m_minSignalToNoiseRatio < 0 .)
924
930
m_minSignalToNoiseRatio = 0 .;
931
+
932
+ // set the signal-to-sigma threshold to zero (default value) if not specified or invalid
933
+ m_minSignalToSigmaRatio = getProperty (PropertyNames::PEAK_MIN_SIGNAL_TO_SIGMA_RATIO);
934
+ if (isEmpty (m_minSignalToSigmaRatio) || m_minSignalToSigmaRatio < 0 .)
935
+ m_minSignalToSigmaRatio = 0 .;
925
936
}
926
937
927
938
// ----------------------------------------------------------------------------------------------
@@ -1281,6 +1292,13 @@ void FitPeaks::fitSpectrumPeaks(size_t wi, const std::vector<double> &expected_p
1281
1292
bkgdfunction, peak_pre_check_result);
1282
1293
if (peak_pre_check_result->isIndividualPeakRejected ())
1283
1294
fit_result->setBadRecord (peak_index, -1 .);
1295
+
1296
+ auto signalToSigma = calculateSignalToSigmaRatio (wi, peak_window_i, peakfunction, bkgdfunction);
1297
+ if (m_minSignalToSigmaRatio > 0 && signalToSigma < m_minSignalToSigmaRatio) {
1298
+ fit_result->setBadRecord (peak_index, -1 .);
1299
+ cost = DBL_MAX;
1300
+ }
1301
+
1284
1302
*pre_check_result += *peak_pre_check_result; // keep track of the rejection count within the spectrum
1285
1303
}
1286
1304
pre_check_result->setNumberOfOutOfRangePeaks (number_of_out_of_range_peaks);
@@ -1530,6 +1548,38 @@ void FitPeaks::calculateFittedPeaks(const std::vector<std::shared_ptr<FitPeaksAl
1530
1548
1531
1549
return ;
1532
1550
}
1551
+
1552
+ double FitPeaks::calculateSignalToSigmaRatio (const size_t &iws, const std::pair<double , double > &peakWindow,
1553
+ const API::IPeakFunction_sptr &peakFunction,
1554
+ const API::IBackgroundFunction_sptr &backgroundFunction) {
1555
+ const auto &vecX = m_fittedPeakWS->points (iws);
1556
+ auto startX = std::lower_bound (vecX.begin (), vecX.end (), peakWindow.first );
1557
+ auto stopX = std::lower_bound (vecX.begin (), vecX.end (), peakWindow.second );
1558
+
1559
+ FunctionDomain1DVector domain (startX, stopX);
1560
+ FunctionValues values (domain);
1561
+ CompositeFunction_sptr compFunc = std::make_shared<API::CompositeFunction>();
1562
+
1563
+ compFunc->addFunction (backgroundFunction);
1564
+ compFunc->function (domain, values);
1565
+ auto bkgdValues = values.toVector ();
1566
+
1567
+ compFunc->addFunction (peakFunction);
1568
+ compFunc->function (domain, values);
1569
+ auto fittedValues = values.toVector ();
1570
+
1571
+ const auto &errors = m_fittedPeakWS->readE (iws);
1572
+ auto startE = std::lower_bound (errors.begin (), errors.end (), peakWindow.first );
1573
+ auto stopE = std::lower_bound (errors.begin (), errors.end (), peakWindow.second );
1574
+ std::vector<double > peakErrors (startE, stopE);
1575
+
1576
+ double fittedSum = std::accumulate (fittedValues.cbegin (), fittedValues.cend (), 0.0 );
1577
+ double bkgdSum = std::accumulate (bkgdValues.cbegin (), bkgdValues.cend (), 0.0 );
1578
+ double sigma = sqrt (std::accumulate (peakErrors.cbegin (), peakErrors.cend (), 0.0 , VectorHelper::SumSquares<double >()));
1579
+
1580
+ return (fittedSum - bkgdSum) / ((sigma == 0 ) ? 1 : sigma);
1581
+ }
1582
+
1533
1583
namespace {
1534
1584
bool estimateBackgroundParameters (const Histogram &histogram, const std::pair<size_t , size_t > &peak_window,
1535
1585
const API::IBackgroundFunction_sptr &bkgd_function) {
0 commit comments