Mantid
Loading...
Searching...
No Matches
FindPeaksConvolve.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2023 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7
9
13#include "MantidAPI/TableRow.h"
16#include "MantidHistogramData/Histogram.h"
20#include "MantidKernel/Logger.h"
22
23#include <algorithm>
24#include <boost/math/distributions/normal.hpp>
25#include <cmath>
26
27namespace {
28Mantid::Kernel::Logger g_log("FindPeaksConvolve");
29}
30
31namespace Mantid::Algorithms {
32
33// Register the algorithm into the AlgorithmFactory
34DECLARE_ALGORITHM(FindPeaksConvolve)
35
36//----------------------------------------------------------------------------------------------
37
38
39const std::string FindPeaksConvolve::name() const { return "FindPeaksConvolve"; }
40
42int FindPeaksConvolve::version() const { return 1; }
43
45const std::string FindPeaksConvolve::category() const { return "Optimization\\PeakFinding"; }
46
48const std::string FindPeaksConvolve::summary() const {
49 return "Finds peaks in a dataset through the use of a convolution vector";
50}
51
52//----------------------------------------------------------------------------------------------
57
58 declareProperty(std::make_unique<API::WorkspaceProperty<>>("InputWorkspace", "", Kernel::Direction::Input),
59 "An input workspace.");
61 std::make_unique<API::WorkspaceProperty<API::WorkspaceGroup>>("OutputWorkspace", "", Kernel::Direction::Output),
62 "An output workspace.");
63 declareProperty("CreateIntermediateWorkspaces", false, "Output workspaces showing intermediate working steps");
64 declareProperty("StartWorkspaceIndex", EMPTY_INT(), m_validators["mustBeNonNegative"]);
65 declareProperty("EndWorkspaceIndex", EMPTY_INT(), m_validators["mustBeNonNegative"]);
66 declareProperty("EstimatedPeakExtent", EMPTY_DBL(), m_validators["mustBeGreaterThanZero"],
67 "Estimated PeakExtent of the peaks to be found");
68 declareProperty("EstimatedPeakExtentNBins", EMPTY_INT(), m_validators["mustBeGreaterThanOne"],
69 "Optional: Estimated PeakExtent of the peaks to be found in number of bins");
70 declareProperty("IOverSigmaThreshold", 3.0, m_validators["mustBeGreaterThanZero"],
71 "Minimum Signal/Noise ratio for a peak to be considered significant");
72 declareProperty("MergeNearbyPeaks", true,
73 "Attempt to remove inflections in the data, where a local"
74 " minima/maxima occurs which is not signficiant enough to be considered a peak");
75 declareProperty("FindHighestDataPointInPeak", false,
76 "When searching for peaks in the raw data around the iOverSigma maxima, take the highest value,"
77 " rather than favouring datapoints closer to the maxima");
78}
79
80//----------------------------------------------------------------------------------------------
85 auto validation_res = secondaryValidation();
86 if (validation_res.second != 0) {
87 throw std::invalid_argument("Validation error: " + validation_res.first);
88 }
90 for (int i = 0; i < static_cast<int>(m_specCount); i++) {
94 }
96
98}
99
101 m_validators.reserve(3); // Update depending upon number of validators.
102
103 auto mustBeNonNegative{std::make_shared<Kernel::BoundedValidator<int>>()};
104 mustBeNonNegative->setLower(0);
105 m_validators.emplace(std::make_pair("mustBeNonNegative", std::move(mustBeNonNegative)));
106
107 auto mustBeGreaterThanZero{std::make_shared<Kernel::BoundedValidator<double>>()};
108 mustBeGreaterThanZero->setLowerExclusive(0.0);
109 m_validators.emplace("mustBeGreaterThanZero", std::move(mustBeGreaterThanZero));
110
111 auto mustBeGreaterThanOne{std::make_shared<Kernel::BoundedValidator<int>>()};
112 mustBeGreaterThanOne->setLowerExclusive(1);
113 m_validators.emplace("mustBeGreaterThanOne", std::move(mustBeGreaterThanOne));
114}
115
116std::pair<std::string, int> FindPeaksConvolve::secondaryValidation() const {
117 std::string err_str{};
118 int err_code{0};
119
120 err_str += validatePeakExtentInput();
121 err_str += validateWorkspaceIndexInput();
122
123 if (err_str != "") {
124 err_code = 1;
125 }
126 return std::make_pair(err_str, err_code);
127}
128
130 std::string err_str{};
131 const double peakExtent = getProperty("EstimatedPeakExtent");
132 const int peakExtentNBins = getProperty("EstimatedPeakExtentNBins");
133 if (peakExtent != EMPTY_DBL() && peakExtentNBins != EMPTY_INT()) {
134 err_str += "Peak Extent has been given in x units and in number of bins. Please specify one or the other. ";
135 } else if (peakExtent == EMPTY_DBL() && peakExtentNBins == EMPTY_INT()) {
136 err_str += "You must specify either peakExtent or peakExtentNBins. ";
137 }
138 return err_str;
139}
140
142 std::string err_str{};
143 if (m_specNums.empty()) {
144 err_str += "If both specified, EndWorkspaceIndex must be greater than StartWorkspaceIndex. ";
145 } else {
146 const int startWSIndex = m_specNums.front();
147 const int endWSIndex = m_specNums.back();
148 int specCount = static_cast<int>(m_inputDataWS->getNumberHistograms());
149 if (startWSIndex > specCount - 1 || endWSIndex > specCount - 1) {
150 err_str += "Specified Workspace indicies out of range. ";
151 }
152 }
153 return err_str;
154}
155
157 m_inputDataWS = getProperty("InputWorkspace");
158 m_createIntermediateWorkspaces = getProperty("CreateIntermediateWorkspaces");
159 m_findHighestDatapointInPeak = getProperty("FindHighestDataPointInPeak");
160 m_iOverSigmaThreshold = getProperty("IOverSigmaThreshold");
161 m_mergeNearbyPeaks = getProperty("MergeNearbyPeaks");
162 // can we assume all spectra are either centred or not?
163 if (m_inputDataWS->x(0).size() != m_inputDataWS->y(0).size()) {
164 m_centreBins = true;
165 } else {
166 m_centreBins = false;
167 }
168
169 int startWSIndex = getProperty("StartWorkspaceIndex");
170 int endWSIndex = getProperty("EndWorkspaceIndex");
171 int specCount = static_cast<int>(m_inputDataWS->getNumberHistograms());
172 if (startWSIndex == EMPTY_INT()) {
173 startWSIndex = 0;
174 }
175 if (endWSIndex == EMPTY_INT()) {
176 endWSIndex = specCount - 1;
177 }
178 m_specCount = endWSIndex - startWSIndex + 1;
179 m_specNums.resize(m_specCount);
180 std::iota(std::begin(m_specNums), std::end(m_specNums), startWSIndex);
182}
183
184void FindPeaksConvolve::performConvolution(const size_t dataIndex) {
185 const auto specNum{m_specNums[dataIndex]};
186 const HistogramData::HistogramX *xData{&m_inputDataWS->x(specNum)};
187 std::pair<const size_t, const bool> kernelBinCount{getKernelBinCount(xData)};
188 if (kernelBinCount.second) {
189 g_log.error("The kernel size for spectrum " + std::to_string(m_specNums[dataIndex]) +
190 " exceeds the range of the x axis. Please reduce the peak extent.");
191 } else {
192 const Tensor1D kernel{createKernel(static_cast<int>(kernelBinCount.first))};
193 const auto binCount{m_inputDataWS->getNumberBins(specNum)};
194 // Edge handling is performed by padding the input data with 0 values. Each convolution requires a padding of kernel
195 // size + 1. The 1st conv is performed with a kernel of size n, the second size n/2. The resultant pad is split
196 // either side of the data.
197 const double paddingSize = (std::ceil(static_cast<double>(kernelBinCount.first) * 1.5) - 2) / 2;
198 const TensorMap_const yData{&m_inputDataWS->y(specNum).front(), binCount};
199 Eigen::array<std::pair<double, double>, 1> paddings{
200 std::make_pair(std::ceil(paddingSize), std::floor(paddingSize))};
201 const auto yData_padded{yData.pad(paddings)};
202 const Eigen::array<ptrdiff_t, 1> dims({0});
203 const Tensor1D yConvOutput{yData_padded.convolve(kernel, dims)};
204 const auto eData{TensorMap_const{&m_inputDataWS->e(specNum).front(), binCount}.pad(paddings)};
205 const Tensor1D eConvOutput{eData.square().convolve(kernel.square(), dims).sqrt()};
206 const Tensor1D smoothKernel{
207 createSmoothKernel(static_cast<size_t>(std::ceil(static_cast<double>(kernelBinCount.first) / 2.0)))};
208 Tensor1D iOverSig{(yConvOutput / eConvOutput).unaryExpr([](double val) { return std::isfinite(val) ? val : 0.0; })};
209 const Tensor1D iOverSigConvOutput{iOverSig.convolve(smoothKernel, dims)};
210 extractPeaks(dataIndex, iOverSigConvOutput, xData, yData, kernelBinCount.first / 2);
212 auto wsNames = createIntermediateWorkspaces(dataIndex, kernel, iOverSigConvOutput, xData);
213 std::lock_guard<std::mutex> lock(m_mtx);
214 m_intermediateWsNames.insert(m_intermediateWsNames.end(), wsNames.cbegin(), wsNames.cend());
215 }
216 }
217}
218
219Tensor1D FindPeaksConvolve::createKernel(const int binCount) const {
220 Tensor1D kernel(binCount);
221 for (int i{0}; i < binCount; i++) {
222 // create integrating shoebox kernel with central positive region & negative background shell with ~the same
223 // elements in each.
224 if (i < std::ceil(binCount) * 0.25 || i >= binCount * 0.75) {
225 kernel.data()[i] = -1.0;
226 } else {
227 kernel.data()[i] = 1.0;
228 }
229 }
230 return kernel;
231}
232
233Tensor1D FindPeaksConvolve::createSmoothKernel(const size_t kernelSize) const {
234 Tensor1D kernel(kernelSize);
235 for (size_t i{0}; i < kernelSize; i++) {
236 kernel.data()[i] = 1.0 / static_cast<double>(kernelSize);
237 }
238 return kernel;
239}
240
241std::pair<size_t, bool> FindPeaksConvolve::getKernelBinCount(const HistogramData::HistogramX *xData) const {
242 const double peakExtent = getProperty("EstimatedPeakExtent");
243 const int peakExtentNBins = getProperty("EstimatedPeakExtentNBins");
244 bool sizeError{false};
245
246 size_t kernelBinCount{0};
247 if (peakExtent != EMPTY_DBL()) {
248 const double x1{xData->rawData()[static_cast<size_t>(std::floor((xData->size() - 1) / 2))]};
249 const double x2{xData->rawData()[static_cast<size_t>(std::floor((xData->size() - 1) / 2)) + 1]};
250 kernelBinCount = static_cast<size_t>(std::floor(peakExtent * 2 / (x2 - x1)));
251 } else {
252 kernelBinCount = static_cast<size_t>(peakExtentNBins);
253 }
254 if (kernelBinCount > xData->size()) {
255 sizeError = true;
256 }
257 return std::make_pair(kernelBinCount, sizeError);
258}
259
260Eigen::VectorXd FindPeaksConvolve::centreBinsXData(const HistogramData::HistogramX *xData) const {
261 Eigen::VectorXd xDataVec{0.5 * (EigenMap_const(&xData->front(), xData->size() - 1) +
262 EigenMap_const(&xData->front() + 1, xData->size() - 1))};
263 return xDataVec;
264}
265
266void FindPeaksConvolve::extractPeaks(const size_t dataIndex, const Tensor1D &iOverSigma,
267 const HistogramData::HistogramX *xData, const TensorMap_const &yData,
268 const size_t peakExtentBinNumber) {
269 int dataPointCount{0};
270 std::pair<int, double> dataRegionMax{0, 0.0};
271 std::vector<FindPeaksConvolve::PeakResult> peakCentres;
272 for (auto i{0}; i < iOverSigma.size(); i++) {
273 if (iOverSigma(i) > m_iOverSigmaThreshold) {
274 if (dataPointCount == 0) {
275 dataRegionMax = std::make_pair(i, iOverSigma(i));
276 } else {
277 if (iOverSigma.data()[i] > dataRegionMax.second) {
278 dataRegionMax = {i, iOverSigma(i)};
279 }
280 }
281 dataPointCount++;
282 } else if (iOverSigma(i) <= 0 || !m_mergeNearbyPeaks || i == iOverSigma.size() - 1) {
283 if (dataPointCount >= 2) {
284 size_t rawPeakIndex{findPeakInRawData(dataRegionMax.first, yData, peakExtentBinNumber)};
285 peakCentres.push_back(FindPeaksConvolve::PeakResult{getXDataValue(xData, rawPeakIndex),
286 yData.data()[rawPeakIndex], dataRegionMax.second});
287 }
288 if (dataPointCount > 0) {
289 dataPointCount = 0;
290 dataRegionMax = std::make_pair(0, 0.0);
291 }
292 }
293 }
294 storePeakResults(dataIndex, peakCentres);
295}
296
297double FindPeaksConvolve::getXDataValue(const HistogramData::HistogramX *xData, const size_t xIndex) const {
298 if (m_centreBins) {
299 return (xData->rawData()[xIndex] + xData->rawData()[xIndex + 1]) / 2;
300 } else {
301 return xData->rawData()[xIndex];
302 }
303}
304
305void FindPeaksConvolve::storePeakResults(const size_t dataIndex,
306 std::vector<FindPeaksConvolve::PeakResult> &peakCentres) {
307 const size_t peakCount = peakCentres.size();
308 if (peakCount) {
309 if (peakCount > m_maxPeakCount) {
310 m_maxPeakCount = peakCount;
311 }
312 std::lock_guard<std::mutex> lock(m_mtx);
313 m_peakResults[dataIndex] = std::move(peakCentres);
314 }
315}
316
317size_t FindPeaksConvolve::findPeakInRawData(const int xIndex, const TensorMap_const &yData,
318 size_t peakExtentBinNumber) {
319 peakExtentBinNumber = (peakExtentBinNumber % 2 == 0) ? peakExtentBinNumber + 1 : peakExtentBinNumber;
320 int sliceStart{xIndex - static_cast<int>(std::floor(static_cast<double>(peakExtentBinNumber) / 2.0))};
321 size_t adjPeakExtentBinNumber{peakExtentBinNumber};
322 int startAdj{0};
323
324 if (sliceStart < 0) {
325 startAdj = -sliceStart;
326 adjPeakExtentBinNumber = peakExtentBinNumber - startAdj;
327 sliceStart = 0;
328 }
329 if (sliceStart + adjPeakExtentBinNumber > static_cast<size_t>(yData.size()) - 1) {
330 adjPeakExtentBinNumber = static_cast<size_t>(yData.size()) - sliceStart;
331 }
332
333 Eigen::VectorXd::Index maxIndex;
335 const auto unweightedYData = EigenMap_const(yData.data() + sliceStart, adjPeakExtentBinNumber);
336 unweightedYData.maxCoeff(&maxIndex);
337 } else {
338 generateNormalPDF(static_cast<int>(peakExtentBinNumber));
339 const auto yDataMap = EigenMap_const(yData.data() + sliceStart, adjPeakExtentBinNumber);
340 {
341 std::lock_guard<std::mutex> lock(m_mtx);
342 const auto weightedYData = yDataMap.cwiseProduct(EigenMap_const(m_pdf.data() + startAdj, adjPeakExtentBinNumber));
343 weightedYData.maxCoeff(&maxIndex);
344 }
345 }
346 return static_cast<size_t>(maxIndex) + sliceStart;
347}
348
349void FindPeaksConvolve::generateNormalPDF(const int peakExtentBinNumber) {
350 std::lock_guard<std::mutex> lock(m_mtx);
351 if (m_pdf.size() == 0) {
352 m_pdf.resize(peakExtentBinNumber);
353 boost::math::normal_distribution<> dist(0.0,
354 peakExtentBinNumber / 2.0); // assures 2 stddevs in the resultant vector
355 const int meanIdx{peakExtentBinNumber / 2};
356 for (int i{0}; i < peakExtentBinNumber; ++i) {
357 int x{i - meanIdx};
358 m_pdf(i) = boost::math::pdf(dist, x);
359 }
360 }
361}
362
363std::vector<std::string> FindPeaksConvolve::createIntermediateWorkspaces(const size_t dataIndex, const Tensor1D &kernel,
364 const Tensor1D &iOverSigma,
365 const HistogramData::HistogramX *xData) {
366 std::unique_ptr<EigenMap_const> xDataMap;
367 Eigen::VectorXd xDataCentredBins;
368 if (m_centreBins) {
369 xDataCentredBins = centreBinsXData(xData);
370 xDataMap = std::make_unique<EigenMap_const>(xDataCentredBins.data(), xDataCentredBins.size());
371 } else {
372 xDataMap = std::make_unique<EigenMap_const>(&xData->front(), xData->size());
373 }
374
375 const std::string iOverSigmaOutputName =
376 m_inputDataWS->getName() + "_" + "iOverSigma" + "_" + std::to_string(m_specNums[dataIndex]);
377 outputIntermediateWorkspace(iOverSigmaOutputName,
378 std::vector<double>(xDataMap->data(), xDataMap->data() + xDataMap->rows()),
379 std::vector<double>(iOverSigma.data(), iOverSigma.data() + iOverSigma.size()));
380
381 std::vector<double> xKernelData(kernel.size());
382 std::iota(std::begin(xKernelData), std::end(xKernelData), 0.0);
383 const std::string kernelOutputName =
384 m_inputDataWS->getName() + "_" + "kernel" + "_" + std::to_string(m_specNums[dataIndex]);
385 outputIntermediateWorkspace(kernelOutputName, std::move(xKernelData),
386 std::vector<double>(kernel.data(), kernel.data() + kernel.size()));
387 return std::vector<std::string>{iOverSigmaOutputName, kernelOutputName};
388}
389
390void FindPeaksConvolve::outputIntermediateWorkspace(const std::string &outputWsName, const std::vector<double> &xData,
391 const std::vector<double> &yData) {
392 API::Algorithm_sptr alg{createChildAlgorithm("CreateWorkspace")};
393 alg->setProperty("OutputWorkspace", outputWsName);
394 alg->setProperty("DataX", xData);
395 alg->setProperty("DataY", yData);
396 alg->execute();
397 API::MatrixWorkspace_sptr algOutput = alg->getProperty("OutputWorkspace");
398 API::AnalysisDataService::Instance().addOrReplace(outputWsName, algOutput);
399}
400
402 const std::vector<std::string> outputTblNames{"PeakCentre", "PeakYPosition", "PeakIOverSigma"};
403 std::unordered_map<std::string, API::ITableWorkspace_sptr> outputTbls{createOutputTables(outputTblNames)};
404
405 std::string noPeaksStr{populateOutputWorkspaces(outputTblNames, outputTbls)};
406 if (noPeaksStr != "") {
407 g_log.warning("No peaks found for spectrum index: " + noPeaksStr);
408 }
409
410 API::WorkspaceGroup_sptr groupWs{groupOutputWorkspaces("resultsOutput", outputTblNames)};
411 setProperty("OutputWorkspace", groupWs);
412
413 if (m_intermediateWsNames.size() > 0) {
414 std::sort(m_intermediateWsNames.begin(), m_intermediateWsNames.end(),
415 [](const std::string &a, const std::string &b) {
416 return std::stoi(a.substr(a.find_last_of("_") + 1, a.size())) <
417 std::stoi(b.substr(b.find_last_of("_") + 1, b.size()));
418 });
419 auto groupedOutput = groupOutputWorkspaces("IntermediateWorkspaces", m_intermediateWsNames);
420 API::AnalysisDataService::Instance().addOrReplace("IntermediateWorkspaces", groupedOutput);
421 }
422}
423
424std::unordered_map<std::string, API::ITableWorkspace_sptr>
425FindPeaksConvolve::createOutputTables(const std::vector<std::string> &outputTblNames) {
426 std::unordered_map<std::string, API::ITableWorkspace_sptr> outputTbls;
427 for (const auto &outputTblName : outputTblNames) {
428 auto tbl = outputTbls.emplace(outputTblName, API::WorkspaceFactory::Instance().createTable("TableWorkspace"));
429 tbl.first->second->addColumn("int", "SpecIndex");
430 for (size_t i{0}; i < m_maxPeakCount; i++) {
431 tbl.first->second->addColumn("double", outputTblName + "_" + std::to_string(i));
432 }
433 API::AnalysisDataService::Instance().addOrReplace(outputTblName, tbl.first->second);
434 }
435 return outputTbls;
436}
437
439 const std::vector<std::string> &outputTblNames) {
440 API::Algorithm_sptr alg{createChildAlgorithm("GroupWorkspaces")};
441 alg->initialize();
442 alg->setProperty("InputWorkspaces", outputTblNames);
443 alg->setProperty("OutputWorkspace", outputName);
444 alg->execute();
445 API::WorkspaceGroup_sptr groupWs = alg->getProperty("OutputWorkspace");
446 return groupWs;
447}
448
450 const std::vector<std::string> &outputTblNames,
451 const std::unordered_map<std::string, API::ITableWorkspace_sptr> &outputTbls) {
452 std::string noPeaksStr{""};
453 for (size_t i{0}; i < m_peakResults.size(); i++) {
454 const auto spec = std::move(m_peakResults[i]);
455 if (!spec.empty()) {
456 for (const auto &outputTblName : outputTblNames) {
457 auto tbl = outputTbls.find(outputTblName);
458 API::TableRow row{tbl->second->appendRow()};
459 row << m_specNums[i];
460 for (size_t peak_i{0}; peak_i < m_maxPeakCount; peak_i++) {
461 if (peak_i < spec.size()) {
462 const auto &peak = spec[peak_i];
463 row << peak.getAttribute(outputTblName);
464 } else {
465 row << std::nan("");
466 }
467 }
468 }
469 } else {
470 noPeaksStr += std::to_string(i) + ", ";
471 }
472 }
473 return noPeaksStr;
474}
475
476double FindPeaksConvolve::PeakResult::getAttribute(const std::string &attrString) const {
477 if (attrString == "PeakCentre") {
478 return centre;
479 } else if (attrString == "PeakYPosition") {
480 return height;
481 } else if (attrString == "PeakIOverSigma") {
482 return iOverSigma;
483 } else {
484 return -1.0;
485 }
486}
487} // namespace Mantid::Algorithms
std::string name
Definition Run.cpp:60
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
Eigen::Map< const Eigen::VectorXd > EigenMap_const
Eigen::Tensor< double, 1 > Tensor1D
Eigen::TensorMap< const Eigen::Tensor< double, 1 > > TensorMap_const
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
Kernel::Logger & g_log
Definition Algorithm.h:422
TableRow represents a row in a TableWorkspace.
Definition TableRow.h:39
A property class for workspaces.
FindPeaksConvolve : Finds peak centres using convolution with a shoebox kernel to approximate the sec...
API::WorkspaceGroup_sptr groupOutputWorkspaces(const std::string &outputName, const std::vector< std::string > &outputTblNames)
const std::string validatePeakExtentInput() const
std::vector< std::vector< FindPeaksConvolve::PeakResult > > m_peakResults
std::unordered_map< std::string, API::ITableWorkspace_sptr > createOutputTables(const std::vector< std::string > &outputTblNames)
void init() override
Initialize the algorithm's properties.
std::vector< std::string > createIntermediateWorkspaces(const size_t dataIndex, const Tensor1D &kernel, const Tensor1D &iOverSigma, const HistogramData::HistogramX *xData)
double getXDataValue(const HistogramData::HistogramX *xData, const size_t xIndex) const
Tensor1D createKernel(const int binCount) const
void exec() override
Execute the algorithm.
Eigen::VectorXd centreBinsXData(const HistogramData::HistogramX *xData) const
void generateNormalPDF(const int peakExtentBinNumber)
std::vector< std::string > m_intermediateWsNames
int version() const override
Algorithm's version for identification.
size_t findPeakInRawData(const int xIndex, const TensorMap_const &yData, size_t peakExtentBinNumber)
void extractPeaks(const size_t dataIndex, const Tensor1D &iOverSigma, const HistogramData::HistogramX *xData, const TensorMap_const &yData, const size_t peakExtentBinNumber)
void performConvolution(const size_t dataIndex)
API::MatrixWorkspace_sptr m_inputDataWS
const std::string validateWorkspaceIndexInput() const
std::pair< size_t, bool > getKernelBinCount(const HistogramData::HistogramX *xData) const
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
void storePeakResults(const size_t dataIndex, std::vector< FindPeaksConvolve::PeakResult > &peakCentres)
Tensor1D createSmoothKernel(const size_t kernelSize) const
const std::string category() const override
Algorithm's category for identification.
std::unordered_map< std::string, Kernel::IValidator_sptr > m_validators
std::pair< std::string, int > secondaryValidation() const
void outputIntermediateWorkspace(const std::string &wsName, const std::vector< double > &xData, const std::vector< double > &yData)
std::string populateOutputWorkspaces(const std::vector< std::string > &outputTblNames, const std::unordered_map< std::string, API::ITableWorkspace_sptr > &outputTbls)
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition Logger.h:51
void error(const std::string &msg)
Logs at error level.
Definition Logger.cpp:108
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< WorkspaceGroup > WorkspaceGroup_sptr
shared pointer to Mantid::API::WorkspaceGroup
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
Definition Algorithm.h:52
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
Kernel::Logger g_log("DetermineSpinStateOrder")
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
Definition EmptyValues.h:24
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition EmptyValues.h:42
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)
double getAttribute(const std::string &attrString) const
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54