Mantid
Loading...
Searching...
No Matches
BinaryOperations.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
19
20#include <boost/python/def.hpp>
21#include <boost/python/return_value_policy.hpp>
22
24 using namespace Mantid::API;
26 using namespace boost::python;
27
28 // Typedefs the various function types
29 using binary_fn_md_md = IMDWorkspace_sptr (*)(const IMDWorkspace_sptr, const IMDWorkspace_sptr, const std::string &,
30 const std::string &, bool, bool);
31 using binary_fn_md_gp = WorkspaceGroup_sptr (*)(const IMDWorkspace_sptr, const WorkspaceGroup_sptr,
32 const std::string &, const std::string &, bool, bool);
33 using binary_fn_gp_md = WorkspaceGroup_sptr (*)(const WorkspaceGroup_sptr, const IMDWorkspace_sptr,
34 const std::string &, const std::string &, bool, bool);
35 using binary_fn_gp_gp = WorkspaceGroup_sptr (*)(const WorkspaceGroup_sptr, const WorkspaceGroup_sptr,
36 const std::string &, const std::string &, bool, bool);
37
38 using binary_fn_mh_mh = IMDHistoWorkspace_sptr (*)(const IMDHistoWorkspace_sptr, const IMDHistoWorkspace_sptr,
39 const std::string &, const std::string &, bool, bool);
40
41 using binary_fn_md_db =
42 IMDWorkspace_sptr (*)(const IMDWorkspace_sptr, double, const std::string &, const std::string &, bool, bool);
43 using binary_fn_mh_db = IMDHistoWorkspace_sptr (*)(const IMDHistoWorkspace_sptr, double, const std::string &,
44 const std::string &, bool, bool);
45 using binary_fn_gp_db =
46 WorkspaceGroup_sptr (*)(const WorkspaceGroup_sptr, double, const std::string &, const std::string &, bool, bool);
47
48 // Always a return a Workspace_sptr
49 using ReturnWorkspaceSptr = return_value_policy<AsType<Workspace_sptr>>;
50
51 // Binary operations that return a workspace
52 using boost::python::def;
55
56 def("performBinaryOp", (binary_fn_md_md)&performBinaryOp, ReturnWorkspaceSptr());
57 def("performBinaryOp", (binary_fn_md_gp)&performBinaryOp, ReturnWorkspaceSptr());
58 def("performBinaryOp", (binary_fn_gp_md)&performBinaryOp, ReturnWorkspaceSptr());
59 def("performBinaryOp", (binary_fn_gp_gp)&performBinaryOp, ReturnWorkspaceSptr());
60 def("performBinaryOp", (binary_fn_mh_mh)&performBinaryOp, ReturnWorkspaceSptr());
61
62 def("performBinaryOp", (binary_fn_md_db)&performBinaryOpWithDouble, ReturnWorkspaceSptr());
63 def("performBinaryOp", (binary_fn_mh_db)&performBinaryOpWithDouble, ReturnWorkspaceSptr());
64 def("performBinaryOp", (binary_fn_gp_db)&performBinaryOpWithDouble, ReturnWorkspaceSptr());
65}
66
68using namespace Mantid::API;
69
83template <typename LHSType, typename RHSType, typename ResultType>
84ResultType performBinaryOp(const LHSType lhs, const RHSType rhs, const std::string &op, const std::string &name,
85 bool inplace, bool reverse) {
86 // ----- Determine which version of the algo should be called -----
87 MatrixWorkspace_const_sptr lhs_mat = std::dynamic_pointer_cast<const MatrixWorkspace>(lhs);
88 MatrixWorkspace_const_sptr rhs_mat = std::dynamic_pointer_cast<const MatrixWorkspace>(rhs);
89 WorkspaceGroup_const_sptr lhs_grp = std::dynamic_pointer_cast<const WorkspaceGroup>(lhs);
90 WorkspaceGroup_const_sptr rhs_grp = std::dynamic_pointer_cast<const WorkspaceGroup>(rhs);
91
92 const auto algoName = (lhs_mat || lhs_grp) && (rhs_mat || rhs_grp) ? op : op + "MD";
93
94 ResultType result;
95 std::string error;
96 try {
98 if (reverse) {
99 result = API::OperatorOverloads::executeBinaryOperation<RHSType, LHSType, ResultType>(algoName, rhs, lhs, inplace,
100 false, name, true);
101 } else {
102 result = API::OperatorOverloads::executeBinaryOperation<LHSType, RHSType, ResultType>(algoName, lhs, rhs, inplace,
103 false, name, true);
104 }
105 } catch (std::runtime_error &exc) {
106 error = exc.what();
107 if (error == "algorithm") {
108 error = "Unknown binary operation requested: " + op;
109 throw std::runtime_error(error);
110 } else {
111 throw;
112 }
113 }
114 return result;
115}
116
131template <typename LHSType, typename ResultType>
132ResultType performBinaryOpWithDouble(const LHSType inputWS, const double value, const std::string &op,
133 const std::string &name, bool inplace, bool reverse) {
134 // RAII struct to add/remove workspace from ADS
135 struct ScopedADSEntry {
136 ScopedADSEntry(const std::string &entryName, const MatrixWorkspace_sptr &value) : name(entryName) {
137 ads.addOrReplace(entryName, value);
138 }
139 ~ScopedADSEntry() { ads.remove(name); }
140
141 const std::string &name;
142 API::AnalysisDataServiceImpl &ads = API::AnalysisDataService::Instance();
143 };
144
145 // In order to recreate a history record of the final binary operation
146 // there must be a record of the creation of the single value workspace used
147 // on the RHS here. This is achieved by running CreateSingleValuedWorkspace
148 // algorithm and adding the output workspace to the ADS. Adding the output
149 // to the ADS is critical so that workspace.name() is updated, by the ADS, to
150 // return the same string. WorkspaceProperty<TYPE>::createHistory() then
151 // records the correct workspace name for input into the final binary
152 // operation rather than creating a temporary name.
153 auto alg = API::AlgorithmManager::Instance().createUnmanaged("CreateSingleValuedWorkspace");
154 alg->setChild(false);
155 // we manually store the workspace as it's easier to retrieve the correct
156 // type from alg->getProperty rather than calling the ADS again and casting
157 alg->setAlwaysStoreInADS(false);
158 alg->initialize();
159 alg->setProperty<double>("DataValue", value);
160 const std::string tmpName("__python_binary_op_single_value");
161 alg->setPropertyValue("OutputWorkspace", tmpName);
162 { // instantiate releaseGIL in limited scope to allow for repeat in 'performBinaryOp'
164 alg->execute();
165 }
166
167 MatrixWorkspace_sptr singleValue;
168 if (alg->isExecuted()) {
169 singleValue = alg->getProperty("OutputWorkspace");
170 } else {
171 throw std::runtime_error("performBinaryOp: Error in execution of "
172 "CreateSingleValuedWorkspace");
173 }
174 ScopedADSEntry removeOnExit(tmpName, singleValue);
175 ResultType result =
176 performBinaryOp<LHSType, MatrixWorkspace_sptr, ResultType>(inputWS, singleValue, op, name, inplace, reverse);
177 return result;
178}
179
180// Concrete instantations
181template IMDWorkspace_sptr performBinaryOp(const IMDWorkspace_sptr, const IMDWorkspace_sptr, const std::string &,
182 const std::string &name, bool, bool);
184 const std::string &name, bool, bool);
186 const std::string &name, bool, bool);
188 const std::string &name, bool, bool);
189
191 const std::string &, const std::string &name, bool, bool);
193 const std::string &, const std::string &name, bool, bool);
194
195// Double variants
196template IMDWorkspace_sptr performBinaryOpWithDouble(const IMDWorkspace_sptr, const double, const std::string &op,
197 const std::string &, bool, bool);
199 const std::string &op, const std::string &, bool, bool);
200template WorkspaceGroup_sptr performBinaryOpWithDouble(const WorkspaceGroup_sptr, const double, const std::string &op,
201 const std::string &, bool, bool);
202} // namespace Mantid::PythonInterface
void export_BinaryOperations()
const std::vector< double > & rhs
double value
The value of the point.
Definition: FitMW.cpp:51
double error
Definition: IndexPeaks.cpp:133
The Analysis data service stores instances of the Workspace objects and anything that derives from te...
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
Defines a structure for releasing the Python GIL using the RAII pattern.
std::shared_ptr< WorkspaceGroup > WorkspaceGroup_sptr
shared pointer to Mantid::API::WorkspaceGroup
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
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
std::shared_ptr< const WorkspaceGroup > WorkspaceGroup_const_sptr
shared pointer to Mantid::API::WorkspaceGroup, pointer to const version
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
ResultType performBinaryOpWithDouble(const LHSType inputWS, const double value, const std::string &op, const std::string &name, bool inplace, bool reverse)
Binary op for a workspace and a double.
ResultType performBinaryOp(const LHSType lhs, const RHSType rhs, const std::string &op, const std::string &name, bool inplace, bool reverse)
Binary op for two workspaces.