Mantid
Loading...
Searching...
No Matches
WorkspaceOpOverloads.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 +
18
19#include <numeric>
20
21namespace Mantid::API {
22namespace OperatorOverloads {
23
36template <typename LHSType, typename RHSType, typename ResultType>
37ResultType executeBinaryOperation(const std::string &algorithmName, const LHSType lhs, const RHSType rhs,
38 bool lhsAsOutput, bool child, const std::string &name, bool rethrow) {
39 auto alg = AlgorithmManager::Instance().createUnmanaged(algorithmName);
40 alg->setChild(child);
41 alg->setRethrows(rethrow);
42 alg->initialize();
43
44 if (lhs->getName().empty()) {
45 alg->setProperty<LHSType>("LHSWorkspace", lhs);
46 } else {
47 alg->setPropertyValue("LHSWorkspace", lhs->getName());
48 }
49 if (rhs->getName().empty()) {
50 alg->setProperty<RHSType>("RHSWorkspace", rhs);
51 } else {
52 alg->setPropertyValue("RHSWorkspace", rhs->getName());
53 }
54 if (lhsAsOutput) {
55 if (!lhs->getName().empty()) {
56 alg->setPropertyValue("OutputWorkspace", lhs->getName());
57 } else {
58 alg->setAlwaysStoreInADS(false);
59 alg->setPropertyValue("OutputWorkspace", "dummy-output-name");
60 alg->setProperty<LHSType>("OutputWorkspace", lhs);
61 }
62 } else {
63 if (name.empty()) {
64 alg->setAlwaysStoreInADS(false);
65 alg->setPropertyValue("OutputWorkspace", "dummy-output-name");
66 } else {
67 alg->setPropertyValue("OutputWorkspace", name);
68 }
69 }
70
71 alg->execute();
72
73 if (!alg->isExecuted()) {
74 std::string message = "Error while executing operation: " + algorithmName;
75 throw std::runtime_error(message);
76 }
77
78 // Get the output workspace property
79 if (!alg->getAlwaysStoreInADS()) {
80 API::MatrixWorkspace_sptr result = alg->getProperty("OutputWorkspace");
81 return std::dynamic_pointer_cast<typename ResultType::element_type>(result);
82 } else {
83 API::Workspace_sptr result =
84 API::AnalysisDataService::Instance().retrieve(alg->getPropertyValue("OutputWorkspace"));
85 return std::dynamic_pointer_cast<typename ResultType::element_type>(result);
86 }
87}
88
89template MANTID_API_DLL MatrixWorkspace_sptr executeBinaryOperation(const std::string &, const MatrixWorkspace_sptr,
90 const MatrixWorkspace_sptr, bool, bool,
91 const std::string &, bool);
92template MANTID_API_DLL WorkspaceGroup_sptr executeBinaryOperation(const std::string &, const WorkspaceGroup_sptr,
93 const WorkspaceGroup_sptr, bool, bool,
94 const std::string &, bool);
95template MANTID_API_DLL WorkspaceGroup_sptr executeBinaryOperation(const std::string &, const WorkspaceGroup_sptr,
96 const MatrixWorkspace_sptr, bool, bool,
97 const std::string &, bool);
98template MANTID_API_DLL WorkspaceGroup_sptr executeBinaryOperation(const std::string &, const MatrixWorkspace_sptr,
99 const WorkspaceGroup_sptr, bool, bool,
100 const std::string &, bool);
101
102template MANTID_API_DLL IMDWorkspace_sptr executeBinaryOperation(const std::string &, const IMDWorkspace_sptr,
103 const IMDWorkspace_sptr, bool, bool,
104 const std::string &, bool);
105template MANTID_API_DLL WorkspaceGroup_sptr executeBinaryOperation(const std::string &, const WorkspaceGroup_sptr,
106 const IMDWorkspace_sptr, bool, bool,
107 const std::string &, bool);
108template MANTID_API_DLL WorkspaceGroup_sptr executeBinaryOperation(const std::string &, const IMDWorkspace_sptr,
109 const WorkspaceGroup_sptr, bool, bool,
110 const std::string &, bool);
111
112template MANTID_API_DLL IMDWorkspace_sptr executeBinaryOperation(const std::string &, const IMDWorkspace_sptr,
113 const MatrixWorkspace_sptr, bool, bool,
114 const std::string &, bool);
115template MANTID_API_DLL IMDWorkspace_sptr executeBinaryOperation(const std::string &, const MatrixWorkspace_sptr,
116 const IMDWorkspace_sptr, bool, bool,
117 const std::string &, bool);
118
119template MANTID_API_DLL IMDHistoWorkspace_sptr executeBinaryOperation(const std::string &, const IMDHistoWorkspace_sptr,
120 const IMDHistoWorkspace_sptr, bool, bool,
121 const std::string &, bool);
122template MANTID_API_DLL IMDHistoWorkspace_sptr executeBinaryOperation(const std::string &, const IMDHistoWorkspace_sptr,
123 const MatrixWorkspace_sptr, bool, bool,
124 const std::string &, bool);
125template MANTID_API_DLL IMDHistoWorkspace_sptr executeBinaryOperation(const std::string &, const MatrixWorkspace_sptr,
126 const IMDHistoWorkspace_sptr, bool, bool,
127 const std::string &, bool);
128
129} // namespace OperatorOverloads
130
140 auto alg = AlgorithmManager::Instance().createUnmanaged("CompareWorkspaces");
141 alg->setChild(true);
142 alg->setRethrows(false);
143 alg->initialize();
144 alg->setProperty<MatrixWorkspace_sptr>("Workspace1", lhs);
145 alg->setProperty<MatrixWorkspace_sptr>("Workspace2", rhs);
146 alg->setProperty<double>("Tolerance", tolerance);
147 // Rest: use default
148
149 alg->execute();
150 if (!alg->isExecuted()) {
151 std::string message = "Error while executing operation: CompareWorkspaces";
152 throw std::runtime_error(message);
153 }
154 return alg->getProperty("Result");
155}
156
161static MatrixWorkspace_sptr createWorkspaceSingleValue(const double &rhsValue) {
162 MatrixWorkspace_sptr retVal = WorkspaceFactory::Instance().create("WorkspaceSingleValue", 1, 1, 1);
163 retVal->dataY(0)[0] = rhsValue;
164
165 return retVal;
166}
167
169
176 return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr, MatrixWorkspace_sptr>("Plus", lhs, rhs);
177}
178
184MatrixWorkspace_sptr operator+(const MatrixWorkspace_sptr &lhs, const double &rhsValue) {
185 return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr, MatrixWorkspace_sptr>(
186 "Plus", lhs, createWorkspaceSingleValue(rhsValue));
187}
188
195 return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr, MatrixWorkspace_sptr>("Minus", lhs, rhs);
196}
197
203MatrixWorkspace_sptr operator-(const MatrixWorkspace_sptr &lhs, const double &rhsValue) {
204 return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr, MatrixWorkspace_sptr>(
205 "Minus", lhs, createWorkspaceSingleValue(rhsValue));
206}
207
214 return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr, MatrixWorkspace_sptr>(
215 "Minus", createWorkspaceSingleValue(lhsValue), rhs);
216}
223 return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr, MatrixWorkspace_sptr>("Multiply", lhs, rhs);
224}
225
231MatrixWorkspace_sptr operator*(const MatrixWorkspace_sptr &lhs, const double &rhsValue) {
232 return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr, MatrixWorkspace_sptr>(
233 "Multiply", lhs, createWorkspaceSingleValue(rhsValue));
234}
235
243 return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr, MatrixWorkspace_sptr>(
244 "Multiply", createWorkspaceSingleValue(lhsValue), rhs);
245}
246
253 return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr, MatrixWorkspace_sptr>("Divide", lhs, rhs);
254}
255
261MatrixWorkspace_sptr operator/(const MatrixWorkspace_sptr &lhs, const double &rhsValue) {
262 return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr, MatrixWorkspace_sptr>(
263 "Divide", lhs, createWorkspaceSingleValue(rhsValue));
264}
265
273 return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr, MatrixWorkspace_sptr>(
274 "Divide", createWorkspaceSingleValue(lhsValue), rhs);
275}
276
283 return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr, MatrixWorkspace_sptr>("Plus", lhs, rhs,
284 true);
285}
286
292MatrixWorkspace_sptr operator+=(const MatrixWorkspace_sptr &lhs, const double &rhsValue) {
293 return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr, MatrixWorkspace_sptr>(
294 "Plus", lhs, createWorkspaceSingleValue(rhsValue), true);
295}
296
303 return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr, MatrixWorkspace_sptr>("Minus", lhs, rhs,
304 true);
305}
306
312MatrixWorkspace_sptr operator-=(const MatrixWorkspace_sptr &lhs, const double &rhsValue) {
313 return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr, MatrixWorkspace_sptr>(
314 "Minus", lhs, createWorkspaceSingleValue(rhsValue), true);
315}
316
323 return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr, MatrixWorkspace_sptr>("Multiply", lhs, rhs,
324 true);
325}
326
332MatrixWorkspace_sptr operator*=(const MatrixWorkspace_sptr &lhs, const double &rhsValue) {
333 return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr, MatrixWorkspace_sptr>(
334 "Multiply", lhs, createWorkspaceSingleValue(rhsValue), true);
335}
336
343 return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr, MatrixWorkspace_sptr>("Divide", lhs, rhs,
344 true);
345}
346
352MatrixWorkspace_sptr operator/=(const MatrixWorkspace_sptr &lhs, const double &rhsValue) {
353 return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr, MatrixWorkspace_sptr>(
354 "Divide", lhs, createWorkspaceSingleValue(rhsValue), true);
355}
356
357//----------------------------------------------------------------------
358// Now the WorkspaceHelpers methods
359//----------------------------------------------------------------------
360
370bool WorkspaceHelpers::matchingBins(const std::shared_ptr<const MatrixWorkspace> &ws1,
371 const std::shared_ptr<const MatrixWorkspace> &ws2, const bool firstOnly) {
372 // First of all, the first vector must be the same size
373 if (ws1->x(0).size() != ws2->x(0).size())
374 return false;
375
376 // Now check the first spectrum
377 const double firstWS = std::accumulate(ws1->x(0).begin(), ws1->x(0).end(), 0.);
378 const double secondWS = std::accumulate(ws2->x(0).begin(), ws2->x(0).end(), 0.);
379 if (std::abs(firstWS) < 1.0E-7 && std::abs(secondWS) < 1.0E-7) {
380 for (size_t i = 0; i < ws1->x(0).size(); i++) {
381 if (!Kernel::withinAbsoluteDifference(ws1->x(0)[i], ws2->x(0)[i], 1.0E-7))
382 return false;
383 }
384 } else if (!Kernel::withinRelativeDifference(firstWS, secondWS, 1.0E-7))
385 return false;
386
387 // If we were only asked to check the first spectrum, return now
388 if (firstOnly)
389 return true;
390
391 // Check that total size of workspace is the same
392 if (ws1->size() != ws2->size())
393 return false;
394 // If that passes then check whether all the X vectors are shared
395 if (sharedXData(ws1) && sharedXData(ws2))
396 return true;
397
398 // If that didn't pass then explicitly check 1 in 10 of the vectors (min 10,
399 // max 100)
400 const size_t numHist = ws1->getNumberHistograms();
401 size_t numberToCheck = numHist / 10;
402 if (numberToCheck < 10)
403 numberToCheck = 10;
404 if (numberToCheck > 100)
405 numberToCheck = 100;
406 size_t step = numHist / numberToCheck;
407 if (!step)
408 step = 1;
409 for (size_t i = step; i < numHist; i += step) {
410 const double firstWSLoop = std::accumulate(ws1->x(i).begin(), ws1->x(i).end(), 0.);
411 const double secondWSLoop = std::accumulate(ws2->x(i).begin(), ws2->x(i).end(), 0.);
412 if (std::abs(firstWSLoop) < 1.0E-7 && std::abs(secondWSLoop) < 1.0E-7) {
413 for (size_t j = 0; j < ws1->x(i).size(); j++) {
414 if (!Kernel::withinAbsoluteDifference(ws1->x(i)[j], ws2->x(i)[j], 1.0E-7))
415 return false;
416 }
417 } else if (!Kernel::withinRelativeDifference(firstWSLoop, secondWSLoop, 1.0E-7))
418 return false;
419 }
420
421 return true;
422}
423
425bool WorkspaceHelpers::sharedXData(const std::shared_ptr<const MatrixWorkspace> &WS) {
426 const double &first = WS->x(0)[0];
427 const size_t numHist = WS->getNumberHistograms();
428 for (size_t i = 1; i < numHist; ++i) {
429 if (&first != &(WS->x(i)[0]))
430 return false;
431 }
432 return true;
433}
434
443 // If we're not able to get a writable reference to Y, then this is an event
444 // workspace, which we can't operate on.
445 if (workspace->id() == "EventWorkspace")
446 throw std::runtime_error("Event workspaces cannot be directly converted "
447 "into distributions.");
448
449 const size_t numberOfSpectra = workspace->getNumberHistograms();
450 if (workspace->histogram(0).xMode() == HistogramData::Histogram::XMode::Points) {
451 throw std::runtime_error("Workspace is using point data for x (should be bin edges).");
452 }
453 for (size_t i = 0; i < numberOfSpectra; ++i) {
454 if (forwards) {
455 workspace->convertToFrequencies(i);
456 } else {
457 workspace->convertToCounts(i);
458 }
459 }
460}
461
462} // namespace Mantid::API
std::string name
Definition Run.cpp:60
const std::vector< double > & rhs
IPeaksWorkspace_sptr workspace
double tolerance
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
DLLExport ResultType executeBinaryOperation(const std::string &algorithmName, const LHSType lhs, const RHSType rhs, bool lhsAsOutput=false, bool child=true, const std::string &name="", bool rethrow=false)
Performs a binary operation on two workspaces.
MatrixWorkspace_sptr MANTID_API_DLL operator*(const MatrixWorkspace_sptr &lhs, const MatrixWorkspace_sptr &rhs)
Multiply two workspaces.
std::shared_ptr< WorkspaceGroup > WorkspaceGroup_sptr
shared pointer to Mantid::API::WorkspaceGroup
bool MANTID_API_DLL equals(const MatrixWorkspace_sptr &lhs, const MatrixWorkspace_sptr &rhs, double tolerance=0.0)
Performs a comparison operation on two workspaces, using the CompareWorkspaces algorithm.
MatrixWorkspace_sptr MANTID_API_DLL operator/=(const MatrixWorkspace_sptr &lhs, const MatrixWorkspace_sptr &rhs)
Divide two workspaces.
MatrixWorkspace_sptr MANTID_API_DLL operator+=(const MatrixWorkspace_sptr &lhs, const MatrixWorkspace_sptr &rhs)
Adds two workspaces.
MatrixWorkspace_sptr MANTID_API_DLL operator-=(const MatrixWorkspace_sptr &lhs, const MatrixWorkspace_sptr &rhs)
Subtracts two workspaces.
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::shared_ptr< IMDHistoWorkspace > IMDHistoWorkspace_sptr
shared pointer to Mantid::API::IMDHistoWorkspace
std::shared_ptr< IMDWorkspace > IMDWorkspace_sptr
Shared pointer to the IMDWorkspace base class.
MatrixWorkspace_sptr MANTID_API_DLL operator-(const MatrixWorkspace_sptr &lhs, const MatrixWorkspace_sptr &rhs)
Subtracts two workspaces.
MatrixWorkspace_sptr MANTID_API_DLL operator*=(const MatrixWorkspace_sptr &lhs, const MatrixWorkspace_sptr &rhs)
Multiply two workspaces.
MatrixWorkspace_sptr MANTID_API_DLL operator/(const MatrixWorkspace_sptr &lhs, const MatrixWorkspace_sptr &rhs)
Divide two workspaces.
static MatrixWorkspace_sptr createWorkspaceSingleValue(const double &rhsValue)
Creates a temporary single value workspace the error is set to zero.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
MatrixWorkspace_sptr MANTID_API_DLL operator+(const MatrixWorkspace_sptr &lhs, const MatrixWorkspace_sptr &rhs)
Adds two workspaces.
MANTID_KERNEL_DLL bool withinRelativeDifference(T const x, T const y, S const tolerance)
Test whether x, y are within relative tolerance tol.
MANTID_KERNEL_DLL bool withinAbsoluteDifference(T const x, T const y, S const tolerance)
Test whether x, y are within absolute tolerance tol.
static bool sharedXData(const std::shared_ptr< const MatrixWorkspace > &WS)
Checks whether all the X vectors in a workspace are the same one underneath.
static bool matchingBins(const std::shared_ptr< const MatrixWorkspace > &ws1, const std::shared_ptr< const MatrixWorkspace > &ws2, const bool firstOnly=false)
Checks whether the bins (X values) of two workspace are the same.
static void makeDistribution(const MatrixWorkspace_sptr &workspace, const bool forwards=true)
Divides the data in a workspace by the bin width to make it a distribution.