Mantid
Loading...
Searching...
No Matches
MaskNonOverlappingBins.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 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 +
8
9#include "MantidAPI/Axis.h"
13#include "MantidKernel/Unit.h"
14
15namespace {
17namespace Prop {
18std::string const CHECK_SORTING{"CheckSortedX"};
19std::string const COMPARISON_WS{"ComparisonWorkspace"};
20std::string const INPUT_WS{"InputWorkspace"};
21std::string const MASK_PARTIAL{"MaskPartiallyOverlapping"};
22std::string const OUTPUT_WS{"OutputWorkspace"};
23std::string const RAGGEDNESS{"RaggedInputs"};
24} // namespace Prop
26namespace Raggedness {
27std::string const CHECK{"Check"};
28std::string const RAGGED{"Ragged"};
29std::string const NONRAGGED{"Common Bins"};
30} // namespace Raggedness
31
33bool isXSorted(Mantid::API::MatrixWorkspace const &ws) {
34 int unsorted{0};
36 for (int64_t i = 0; i < static_cast<int64_t>(ws.getNumberHistograms()); ++i) {
37 auto const &Xs = ws.x(i);
38 if (!std::is_sorted(Xs.cbegin(), Xs.cend())) {
40 ++unsorted;
41 }
42 }
43 return unsorted == 0;
44}
45
47struct BinIndices {
48 size_t frontEndIndex;
49 size_t backBeginIndex;
50};
51
53BinIndices maskingLimits(Mantid::API::MatrixWorkspace const &ws, Mantid::API::MatrixWorkspace const &comparisonWS,
54 bool const maskPartial, size_t const histogramIndex) {
55 auto const &Xs = ws.x(histogramIndex);
56 auto const &comparisonXs = comparisonWS.x(histogramIndex);
57 // At the moment we only support increasing X.
58 auto const startX = comparisonXs.front();
59 auto const endX = comparisonXs.back();
60 // There is no Y corresponding to the last bin edge,
61 // therefore iterate only to cend() - 1.
62 auto frontEnd = std::lower_bound(Xs.cbegin(), Xs.cend() - 1, startX);
63 if (!maskPartial && frontEnd != Xs.cbegin() && *frontEnd != startX) {
64 --frontEnd;
65 }
66 auto backBegin = std::lower_bound(frontEnd, Xs.cend() - 1, endX);
67 if (maskPartial && backBegin != Xs.cbegin() && *backBegin > endX) {
68 --backBegin;
69 }
70 BinIndices limits;
71 limits.frontEndIndex = static_cast<size_t>(std::distance(Xs.cbegin(), frontEnd));
72 limits.backBeginIndex = static_cast<size_t>(std::distance(Xs.cbegin(), backBegin));
73 return limits;
74}
75
77void maskBinsWithinLimits(Mantid::API::MatrixWorkspace &ws, size_t const histogramIndex, BinIndices const &limits) {
78 auto const xSize = ws.x(histogramIndex).size();
79 for (size_t binIndex = 0; binIndex < limits.frontEndIndex; ++binIndex) {
80 ws.flagMasked(histogramIndex, binIndex);
81 }
82 for (size_t binIndex = limits.backBeginIndex; binIndex < xSize - 1; ++binIndex) {
83 ws.flagMasked(histogramIndex, binIndex);
84 }
85}
86} // namespace
87
88namespace Mantid::Algorithms {
89DECLARE_ALGORITHM(MaskNonOverlappingBins)
90
91
92std::string const MaskNonOverlappingBins::name() const { return "MaskNonOverlappingBins"; }
93
95int MaskNonOverlappingBins::version() const { return 1; }
96
98std::string const MaskNonOverlappingBins::category() const { return "Transforms\\Masking"; }
99
101std::string const MaskNonOverlappingBins::summary() const {
102 return "Marks bins in InputWorkspace which are out of the X range of the "
103 "second workspace.";
104}
105
107std::vector<std::string> const MaskNonOverlappingBins::seeAlso() const { return {"MaskBins", "MaskBinsIf"}; }
108
112 declareProperty(std::make_unique<API::WorkspaceProperty<>>(Prop::INPUT_WS, "", Kernel::Direction::Input),
113 "A workspace to mask.");
114 declareProperty(std::make_unique<API::WorkspaceProperty<>>(Prop::OUTPUT_WS, "", Kernel::Direction::Output),
115 "The masked workspace.");
116 declareProperty(std::make_unique<API::WorkspaceProperty<>>(Prop::COMPARISON_WS, "", Kernel::Direction::Input),
117 "A workspace to compare the InputWorkspace's binning to.");
118 declareProperty(Prop::MASK_PARTIAL, false, "If true, mask also bins that overlap only partially.");
119 std::vector<std::string> const options{Raggedness::CHECK, Raggedness::RAGGED, Raggedness::NONRAGGED};
120 auto raggednessOptions = std::make_shared<Kernel::ListValidator<std::string>>(options);
121 declareProperty(Prop::RAGGEDNESS, Raggedness::CHECK, raggednessOptions,
122 "Choose whether the input workspaces have common bins, are "
123 "ragged, or if the algorithm should check.");
124 declareProperty(Prop::CHECK_SORTING, true,
125 "If true, the algorithm ensures that both workspaces have X sorted in "
126 "ascending order.");
127}
128
130std::map<std::string, std::string> MaskNonOverlappingBins::validateInputs() {
131 std::map<std::string, std::string> issues;
132 API::MatrixWorkspace_const_sptr inputWS = getProperty(Prop::INPUT_WS);
133 API::MatrixWorkspace_const_sptr comparisonWS = getProperty(Prop::COMPARISON_WS);
134 if (!inputWS) {
135 issues[Prop::INPUT_WS] = "The " + Prop::INPUT_WS + " must be a MatrixWorkspace.";
136 }
137 if (!comparisonWS) {
138 issues[Prop::COMPARISON_WS] = "The " + Prop::COMPARISON_WS + " must be a MatrixWorkspace.";
139 }
140 if (!issues.empty()) {
141 return issues;
142 }
143 if (inputWS->getNumberHistograms() != comparisonWS->getNumberHistograms()) {
144 issues[Prop::COMPARISON_WS] = "The number of histogams mismatches with " + Prop::INPUT_WS;
145 }
146 if (!inputWS->isHistogramData()) {
147 issues[Prop::INPUT_WS] = "The workspace contains point data, not histograms.";
148 }
149 if (!comparisonWS->isHistogramData()) {
150 issues[Prop::COMPARISON_WS] = "The workspace contains point data, not histograms.";
151 }
152 auto const inputAxis = inputWS->getAxis(0);
153 auto const comparisonAxis = comparisonWS->getAxis(0);
154 if (inputAxis && comparisonAxis) {
155 if (*(inputAxis->unit()) != *(comparisonAxis->unit())) {
156 issues[Prop::COMPARISON_WS] = "X units do not match with " + Prop::INPUT_WS;
157 }
158 }
159 return issues;
160}
161
165 API::MatrixWorkspace_sptr inputWS = getProperty(Prop::INPUT_WS);
166 API::MatrixWorkspace_sptr outputWS = getProperty(Prop::OUTPUT_WS);
167 if (inputWS != outputWS) {
168 outputWS = inputWS->clone();
169 }
170 API::MatrixWorkspace_const_sptr comparisonWS = getProperty(Prop::COMPARISON_WS);
171 checkXSorting(*inputWS, *comparisonWS);
172 if (isCommonBins(*inputWS, *comparisonWS)) {
173 processNonRagged(*inputWS, *comparisonWS, *outputWS);
174 } else {
175 processRagged(*inputWS, *comparisonWS, *outputWS);
176 }
177 setProperty(Prop::OUTPUT_WS, outputWS);
178}
179
182 API::MatrixWorkspace const &comparisonWS) {
183 bool const checkSorting = getProperty(Prop::CHECK_SORTING);
184 if (checkSorting) {
185 if (!isXSorted(inputWS)) {
186 throw std::invalid_argument(Prop::INPUT_WS + " has unsorted X.");
187 }
188 if (!isXSorted(comparisonWS)) {
189 throw std::invalid_argument(Prop::COMPARISON_WS + " has unsorted X.");
190 }
191 }
192}
193
196 API::MatrixWorkspace const &comparisonWS) {
197 std::string const choice = getProperty(Prop::RAGGEDNESS);
198 if (choice == Raggedness::CHECK) {
199 return inputWS.isCommonBins() && comparisonWS.isCommonBins();
200 } else {
201 return choice == Raggedness::NONRAGGED;
202 }
203}
204
207 API::MatrixWorkspace const &comparisonWS, API::MatrixWorkspace &outputWS) {
208 bool const maskPartial = getProperty(Prop::MASK_PARTIAL);
209 auto const nHist = inputWS.getNumberHistograms();
210 API::Progress progress(this, 0., 1., nHist);
211 // Tried to parallelize this loop but the performance test showed
212 // regression. Hence no PARALLEL_FOR_IF.
213 for (size_t histogramIndex = 0; histogramIndex < nHist; ++histogramIndex) {
214 auto const limits = maskingLimits(inputWS, comparisonWS, maskPartial, histogramIndex);
215 maskBinsWithinLimits(outputWS, histogramIndex, limits);
216 progress.report("Masking nonoverlapping bins");
217 }
218}
219
222 API::MatrixWorkspace const &comparisonWS,
223 API::MatrixWorkspace &outputWS) {
224 bool const maskPartial = getProperty(Prop::MASK_PARTIAL);
225 auto const nHist = inputWS.getNumberHistograms();
226 API::Progress progress(this, 0., 1., nHist);
227 auto const limits = maskingLimits(inputWS, comparisonWS, maskPartial, 0);
228 for (size_t histogramIndex = 0; histogramIndex < nHist; ++histogramIndex) {
229 maskBinsWithinLimits(outputWS, histogramIndex, limits);
230 progress.report("Masking nonoverlapping bins");
231 }
232}
233
234} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
#define PARALLEL_ATOMIC
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Definition: Algorithm.cpp:231
Base MatrixWorkspace Abstract Class.
virtual std::size_t getNumberHistograms() const =0
Returns the number of histograms in the workspace.
const HistogramData::HistogramX & x(const size_t index) const
void flagMasked(const size_t &index, const size_t &binIndex, const double &weight=1.0)
Writes the masking weight to m_masks (doesn't alter y-values).
virtual bool isCommonBins() const
Returns true if the workspace contains common X bins.
Helper class for reporting progress from algorithms.
Definition: Progress.h:25
A property class for workspaces.
MaskNonOverlappingBins : Compares the X ranges of two workspace and masks the non-overlapping bins in...
void exec() override
Execute the algorithm.
void processNonRagged(API::MatrixWorkspace const &inputWS, API::MatrixWorkspace const &comparisonWS, API::MatrixWorkspace &outputWS)
Mask only workspace with same X in all histograms.
std::string const summary() const override
Algorithm's summary for use in the GUI and help.
std::vector< std::string > const seeAlso() const override
Return a list of the names of related algorithms.
void checkXSorting(API::MatrixWorkspace const &inputWS, API::MatrixWorkspace const &comparisonWS)
Throw if the workspaces don't have sorted X.
bool isCommonBins(API::MatrixWorkspace const &inputWS, API::MatrixWorkspace const &comparisonWS)
Return true if the workspaces should be considered as having common bins.
std::map< std::string, std::string > validateInputs() override
Returns a map from property name to message in case of invalid values.
std::string const category() const override
Algorithm's category for identification.
void processRagged(API::MatrixWorkspace const &inputWS, API::MatrixWorkspace const &comparisonWS, API::MatrixWorkspace &outputWS)
Mask all types of workspaces, ragged or nonragged.
int version() const override
Algorithm's version for identification.
void init() override
Initialize the algorithm's properties.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
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::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.
Definition: MultiThreaded.h:22
String constants for algorithm's properties.
Constants for the RaggedInputs property.
Eigen::Matrix< size_t, 1, static_cast< int >(ND)> BinIndices
Definition: Types.h:37
STL namespace.
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54