29using namespace Kernel;
31using namespace DataObjects;
41bool validateSingleMatrixWorkspace(std::map<std::string, std::string> &validationOutput,
const MatrixWorkspace &ws,
42 const int minIndex,
const int maxIndex,
const std::vector<int> &indices) {
44 const auto numSpectra =
static_cast<int>(ws.getNumberHistograms());
46 if (minIndex >= numSpectra) {
47 validationOutput[
"StartWorkspaceIndex"] =
"Selected minimum workspace index is greater than available "
54 if (maxIndex >= numSpectra) {
55 validationOutput[
"EndWorkspaceIndex"] =
"Selected maximum workspace index is greater than available "
62 if (std::any_of(indices.cbegin(), indices.cend(),
63 [numSpectra](
const auto index) { return (index >= numSpectra) || (index < 0); })) {
64 validationOutput[
"ListOfWorkspaceIndices"] =
"One or more indices out of range of available spectra.";
77void validateWorkspaceName(std::map<std::string, std::string> &validationOutput,
const std::string &
name,
78 const int minIndex,
const int maxIndex,
const std::vector<int> &indices) {
79 const auto &ads = AnalysisDataService::Instance();
80 if (!ads.doesExist(
name))
82 auto wsGroup = ads.retrieveWS<WorkspaceGroup>(
name);
86 for (
const auto &item : *wsGroup) {
87 auto matrixWs = std::dynamic_pointer_cast<MatrixWorkspace>(item);
89 validationOutput[
"InputWorkspace"] =
"Input group contains an invalid workspace type at item " +
93 if (!validateSingleMatrixWorkspace(validationOutput, *matrixWs, minIndex, maxIndex, indices)) {
106 std::make_shared<CommonBinsValidator>()),
107 "The workspace containing the spectra to be summed.");
109 "The name of the workspace to be created as the output of the algorithm. "
110 " A workspace of this name will be created and stored in the Analysis "
113 auto mustBePositive = std::make_shared<BoundedValidator<int>>();
114 mustBePositive->setLower(0);
115 declareProperty(
"StartWorkspaceIndex", 0, mustBePositive,
"The first Workspace index to be included in the summing");
117 "The last Workspace index to be included in the summing");
120 "A list of workspace indices as a string with ranges, for "
121 "example: 5-10,15,20-23. \n"
122 "Optional: if not specified, then the "
123 "Start/EndWorkspaceIndex fields are used alone. "
124 "If specified, the range and the list are combined (without "
125 "duplicating indices). For example, a range of 10 to 20 and "
126 "a list '12,15,26,28' gives '10-20,26,28'.");
128 declareProperty(
"IncludeMonitors",
true,
"Whether to include monitor spectra in the summation.");
131 "Instead of the usual spectra sum, calculate the weighted "
132 "sum. This has the form: \n"
134 "\\times\\Sigma(Signal_i/Error_i^2)/\\Sigma(1/Error_i^2)`\n "
135 "This property is ignored for event workspace.\n"
136 "The sums are defined for :math:`Error_i != 0` only, so the "
137 "values with zero error are dropped from the summation. To "
138 "estimate the number of dropped values see the "
142 "If enabled floating point special values such as NaN or Inf"
143 " are removed before the spectra are summed.");
146 "For unnormalized data one should multiply the weighted sum "
147 "by the number of spectra contributing to the bin.");
151 "Normalize the output workspace to the fractional area for "
152 "RebinnedOutput workspaces.");
162 std::map<std::string, std::string> validationOutput;
165 const int minIndex =
getProperty(
"StartWorkspaceIndex");
166 const int maxIndex =
getProperty(
"EndWorkspaceIndex");
167 if (minIndex > maxIndex) {
168 validationOutput[
"StartWorkspaceIndex"] =
"Selected minimum workspace "
169 "index is greater than selected "
170 "maximum workspace index.";
171 validationOutput[
"EndWorkspaceIndex"] =
"Selected maximum workspace index "
172 "is lower than selected minimum "
175 const std::vector<int> indices =
getProperty(
"ListOfWorkspaceIndices");
177 validateSingleMatrixWorkspace(validationOutput, *singleWs, minIndex, maxIndex, indices);
179 validateWorkspaceName(validationOutput,
getPropertyValue(
"InputWorkspace"), minIndex, maxIndex, indices);
182 return validationOutput;
188bool useSpectrum(
const SpectrumInfo &spectrumInfo,
const size_t wsIndex,
const bool keepMonitors,
size_t &numMasked) {
191 if (!keepMonitors && spectrumInfo.
isMonitor(wsIndex))
194 if (spectrumInfo.
isMasked(wsIndex)) {
212 size_t numSpectra(0);
219 auto spectrumInfo = localworkspace->spectrumInfo();
223 throw std::runtime_error(
"No spectra selected for summing. Check the input parameters.");
242 outputWorkspace = create<EventWorkspace>(*eventW, 1, eventW->binEdges(0));
253 auto &outSpec = outputWorkspace->getSpectrum(0);
256 outSpec.setSharedX(localworkspace->sharedX(0));
260 outSpec.clearDetectorIDs();
263 outSpec.addDetectorIDs(localworkspace->getSpectrum(i).getDetectorIDs());
267 if (localworkspace->id() ==
"RebinnedOutput") {
288 outputWorkspace->mutableRun().addProperty(
"NumAllSpectra",
int(numSpectra),
"",
true);
289 outputWorkspace->mutableRun().addProperty(
"NumMaskSpectra",
int(numMasked),
"",
true);
290 outputWorkspace->mutableRun().addProperty(
"NumZeroSpectra",
int(numZeros),
"",
true);
301 const std::vector<int> indices_list =
getProperty(
"ListOfWorkspaceIndices");
302 std::transform(indices_list.cbegin(), indices_list.cend(), std::back_inserter(
m_indices),
303 [](
const int idx) { return static_cast<size_t>(idx); });
311 maxIndex =
static_cast<int>(numberOfSpectra - 1);
317 for (
int i = minIndex; i <= maxIndex; i++) {
320 if (useSpectrum(spectrumInfo,
static_cast<size_t>(i),
m_keepMonitors, numMasked)) {
321 m_indices.push_back(
static_cast<size_t>(i));
344 size_t totalSpec = localworkspace->getNumberHistograms();
348 if (
index < totalSpec) {
349 temp = localworkspace->getSpectrum(
index).getSpectrumNo();
370 std::string outName =
"_" + wksp->getName() +
"_clean";
371 alg->setProperty(
"OutputWorkspace", outName);
372 alg->setProperty(
"NaNValue", 0.0);
373 alg->setProperty(
"NaNError", 0.0);
374 alg->setProperty(
"InfinityValue", 0.0);
375 alg->setProperty(
"InfinityError", 0.0);
376 alg->executeAsChildAlg();
377 return alg->getProperty(
"OutputWorkspace");
397 auto &YErrorSum = outSpec.
mutableE();
399 std::fill(YSum.begin(), YSum.end(), 0.0);
400 std::fill(YErrorSum.begin(), YErrorSum.end(), 0.0);
404 const auto &
y = inWS->y(iwksp);
405 const auto &e = inWS->e(iwksp);
406 for (
size_t jbin = 0; jbin <
m_yLength; jbin++) {
407 YSum[jbin] +=
y[jbin];
408 const double ev = e[jbin];
409 YErrorSum[jbin] += ev * ev;
413 for (
size_t jbin = 0; jbin <
m_yLength; jbin++) {
414 YErrorSum[jbin] = std::sqrt(YErrorSum[jbin]);
433 auto &YErrorSum = outSpec.
mutableE();
435 std::fill(YSum.begin(), YSum.end(), 0.0);
436 std::fill(YErrorSum.begin(), YErrorSum.end(), 0.0);
438 std::vector<double> normalization(
m_yLength, 0.0);
439 std::vector<size_t> nZeroes(
m_yLength, 0);
443 const auto &
y = inWS->y(iwksp);
444 const auto &e = inWS->e(iwksp);
445 for (
size_t jbin = 0; jbin <
m_yLength; jbin++) {
446 const double ev = e[jbin];
447 if (std::isnormal(ev)) {
448 const double weight = 1.0 / (ev * ev);
449 normalization[jbin] += weight;
450 YSum[jbin] += weight *
y[jbin];
458 for (
size_t jbin = 0; jbin <
m_yLength; jbin++) {
459 if (normalization[jbin] != 0.) {
460 const double norm = 1.0 / normalization[jbin];
463 YErrorSum[jbin] = std::sqrt(norm);
467 const double scale = double(
m_indices.size() - nZeroes[jbin]);
469 YErrorSum[jbin] *= scale;
473 numZeros = std::accumulate(nZeroes.begin(), nZeroes.end(),
size_t(0));
485 Progress &progress,
size_t &numZeros) {
488 auto isFinalized = inWS->isFinalized();
491 auto &outSpec = outWS->getSpectrum(0);
492 auto &YSum = outSpec.mutableY();
493 auto &YErrorSum = outSpec.mutableE();
494 auto &FracSum = outWS->dataF(0);
496 std::fill(YSum.begin(), YSum.end(), 0.0);
497 std::fill(YErrorSum.begin(), YErrorSum.end(), 0.0);
498 std::fill(FracSum.begin(), FracSum.end(), 0.0);
502 const auto &
y = inWS->y(iwksp);
503 const auto &e = inWS->e(iwksp);
504 const auto &f = inWS->readF(iwksp);
505 for (
size_t jbin = 0; jbin <
m_yLength; jbin++) {
507 const double fracVal = (isFinalized ? f[jbin] : 1.0);
508 const double yv =
y[jbin] * fracVal;
509 const double ev = e[jbin] * fracVal;
512 YErrorSum[jbin] += ev * ev;
513 FracSum[jbin] += f[jbin];
517 for (
size_t jbin = 0; jbin <
m_yLength; jbin++)
518 YErrorSum[jbin] = std::sqrt(YErrorSum[jbin]);
523 auto useFractionalArea =
getProperty(
"UseFractionalArea");
524 if (useFractionalArea) {
525 outWS->finalize(
false);
538 Progress &progress,
size_t &numZeros) {
541 auto isFinalized = inWS->isFinalized();
544 auto &outSpec = outWS->getSpectrum(0);
545 auto &YSum = outSpec.mutableY();
546 auto &YErrorSum = outSpec.mutableE();
547 auto &FracSum = outWS->dataF(0);
549 std::fill(YSum.begin(), YSum.end(), 0.0);
550 std::fill(YErrorSum.begin(), YErrorSum.end(), 0.0);
551 std::fill(FracSum.begin(), FracSum.end(), 0.0);
553 std::vector<double> normalization(
m_yLength, 0.0);
554 std::vector<size_t> nZeroes(
m_yLength, 0);
558 const auto &
y = inWS->y(iwksp);
559 const auto &e = inWS->e(iwksp);
560 const auto &f = inWS->readF(iwksp);
561 for (
size_t jbin = 0; jbin <
m_yLength; jbin++) {
563 const double fracVal = (isFinalized ? f[jbin] : 1.0);
564 const double yv =
y[jbin] * fracVal;
565 const double ev = e[jbin] * fracVal;
567 if (std::isnormal(ev)) {
568 const double weight = 1.0 / (ev * ev);
569 normalization[jbin] += weight;
570 YSum[jbin] += weight * yv;
574 FracSum[jbin] += f[jbin];
579 for (
size_t jbin = 0; jbin <
m_yLength; jbin++) {
580 if (normalization[jbin] != 0.) {
581 const double norm = 1.0 / normalization[jbin];
584 YErrorSum[jbin] = std::sqrt(norm);
588 const double scale = double(
m_indices.size() - nZeroes[jbin]);
590 YErrorSum[jbin] *= scale;
593 numZeros = std::accumulate(nZeroes.begin(), nZeroes.end(),
size_t(0));
596 auto useFractionalArea =
getProperty(
"UseFractionalArea");
597 if (useFractionalArea) {
598 outWS->finalize(
false);
613 EventWorkspace_sptr outputEventWorkspace = std::dynamic_pointer_cast<EventWorkspace>(outputWorkspace);
614 EventList &outputEL = outputEventWorkspace->getSpectrum(0);
619 std::size_t numOutputEvents{0};
621 numOutputEvents += inputWorkspace->getSpectrum(i).getNumberEvents();
623 outputEL.
switchTo(inputWorkspace->getSpectrum(0).getEventType());
624 outputEL.
reserve(numOutputEvents);
629 const EventList &inputEL = inputWorkspace->getSpectrum(i);
630 if (inputEL.
empty()) {
#define DECLARE_ALGORITHM(classname)
std::map< DeltaEMode::Type, std::string > index
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
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.
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
static bool isEmpty(const NumT toCheck)
checks that the value was not set by users, uses the value in empty double/int.
A "spectrum" is an object that holds the data for a particular spectrum, in particular:
HistogramData::HistogramY & mutableY() &
void clearDetectorIDs()
Clear the detector IDs set.
void setSpectrumNo(specnum_t num)
Sets the spectrum number of this spectrum.
HistogramData::HistogramE & mutableE() &
Helper class for reporting progress from algorithms.
API::SpectrumInfo is an intermediate step towards a SpectrumInfo that is part of Instrument-2....
bool isMonitor(const size_t index) const
Returns true if the detector(s) associated with the spectrum are monitors.
bool hasDetectors(const size_t index) const
Returns true if the spectrum is associated with detectors in the instrument.
bool isMasked(const size_t index) const
Returns true if the detector(s) associated with the spectrum are masked.
A property class for workspaces.
void doFractionalSum(RebinnedOutput_const_sptr const &, RebinnedOutput_sptr const &, API::Progress &, size_t &)
Handle logic for RebinnedOutput workspaces.
void doSimpleWeightedSum(API::MatrixWorkspace_const_sptr const &, API::ISpectrum &, API::Progress &, size_t &)
Perform a weighted sum of the spectra in the input workspace, where values in each bin are weighted b...
size_t m_yLength
Blocksize of the input workspace.
size_t determineIndices(API::SpectrumInfo const &, const size_t numberOfSpectra)
bool m_keepMonitors
Set true to keep monitors.
void exec() override
Executes the algorithm.
std::map< std::string, std::string > validateInputs() override
Cross-input validation.
void doFractionalWeightedSum(RebinnedOutput_const_sptr const &, RebinnedOutput_sptr const &, API::Progress &, size_t &)
This function handles the logic for summing RebinnedOutput workspaces.
specnum_t m_outSpecNum
The output spectrum number.
specnum_t getOutputSpecNo(const API::MatrixWorkspace_const_sptr &localworkspace)
Determine the minimum spectrum No for summing.
void execEvent(const API::MatrixWorkspace_sptr &outputWorkspace, API::Progress &progress, size_t &numZeros)
Executes the algorithm.
bool m_calculateWeightedSum
void init() override
Initialisation method.
API::MatrixWorkspace_sptr replaceSpecialValues()
Calls an algorithm to replace special values within the workspace such as NaN or Inf to 0.
void doSimpleSum(API::MatrixWorkspace_const_sptr const &, API::ISpectrum &, API::Progress &, size_t &)
Handle logic for summing standard workspaces.
size_t m_numberOfSpectra
numberOfSpectra in the input
std::vector< size_t > m_indices
Sorted list of indices to sum.
void reserve(size_t num) override
Reserve a certain number of entries in event list of the specified eventType.
void switchTo(Mantid::API::EventType newType) override
Switch the EventList to use the given EventType (TOF, WEIGHTED, or WEIGHTED_NOTIME)
bool empty() const
Much like stl containers, returns true if there is nothing in the event list.
Support for a property that holds an array of values.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void setPropertySettings(const std::string &name, std::unique_ptr< IPropertySettings const > settings)
Add a PropertySettings instance to the chain of settings for a given property.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< const RebinnedOutput > RebinnedOutput_const_sptr
shared pointer to a const RebinnedOutput
std::shared_ptr< const EventWorkspace > EventWorkspace_const_sptr
shared pointer to a const Workspace2D
std::shared_ptr< RebinnedOutput > RebinnedOutput_sptr
shared pointer to the RebinnedOutput class
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
int32_t specnum_t
Typedef for a spectrum Number.
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Input
An input workspace.
@ Output
An output workspace.