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