Mantid
Loading...
Searching...
No Matches
BinaryOperationMD.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 +
11#include "MantidAPI/Run.h"
17#include "MantidKernel/System.h"
18
19using namespace Mantid::Kernel;
20using namespace Mantid::API;
21using namespace Mantid::DataObjects;
22using namespace Mantid::DataObjects;
24
25namespace Mantid::MDAlgorithms {
26
28const std::string BinaryOperationMD::name() const { return "BinaryOperationMD"; }
29
31int BinaryOperationMD::version() const { return 1; }
32
34const std::string BinaryOperationMD::category() const { return "MDAlgorithms\\MDArithmetic"; }
35
40 "An MDEventWorkspace, MDHistoWorkspace or "
41 "WorkspaceSingleValue as the left-hand side of the "
42 "operation.");
44 "An MDEventWorkspace, MDHistoWorkspace or "
45 "WorkspaceSingleValue as the right-hand side of the "
46 "operation.");
48 "Name of the output MDEventWorkspace or MDHistoWorkspace.");
49 this->initExtraProperties();
50}
51
54
58 // Get the properties
62
63 // Flip LHS and RHS if commutative and :
64 // 1. A = B + A -> becomes -> A += B
65 // 1. C = 1 + A -> becomes -> C = A + 1 (number is always on RHS if
66 // possible)
67 if (this->commutative() && ((m_out == m_rhs) || std::dynamic_pointer_cast<WorkspaceSingleValue>(m_lhs))) {
68 // So we flip RHS/LHS
70 m_lhs = m_rhs;
71 m_rhs = temp;
72 }
73
74 // Do not compare conventions if one is single value
75 if (!std::dynamic_pointer_cast<WorkspaceSingleValue>(m_rhs)) {
76 if (m_lhs->getConvention() != m_rhs->getConvention()) {
77 throw std::runtime_error("Workspaces have different conventions for Q. "
78 "Use algorithm ChangeQConvention on one workspace. ");
79 }
80 }
81
82 // Can't do A = 1 / B
83 if (std::dynamic_pointer_cast<MatrixWorkspace>(m_lhs))
84 throw std::invalid_argument("BinaryOperationMD: can't have a "
85 "MatrixWorkspace (e.g. WorkspaceSingleValue) "
86 "as the LHS argument of " +
87 this->name() + ".");
88
89 // Check the inputs. First cast to everything
90 m_lhs_event = std::dynamic_pointer_cast<IMDEventWorkspace>(m_lhs);
91 m_lhs_histo = std::dynamic_pointer_cast<MDHistoWorkspace>(m_lhs);
92 m_lhs_scalar = std::dynamic_pointer_cast<WorkspaceSingleValue>(m_lhs);
93 m_rhs_event = std::dynamic_pointer_cast<IMDEventWorkspace>(m_rhs);
94 m_rhs_histo = std::dynamic_pointer_cast<MDHistoWorkspace>(m_rhs);
95 m_rhs_scalar = std::dynamic_pointer_cast<WorkspaceSingleValue>(m_rhs);
96
97 // MDEventWorkspaces only:
98 // If you have to clone any WS, and the operation is commutative, and is NOT
99 // in-place, then clone the one that is file-backed.
100 if (this->commutative() && (m_lhs_event && m_rhs_event) && (m_out != m_lhs)) {
101 if (m_rhs_event->isFileBacked() && !m_lhs_event->isFileBacked()) {
102 // So we flip RHS/LHS
104 m_lhs = m_rhs;
105 m_rhs = temp;
106 m_lhs_event = std::dynamic_pointer_cast<IMDEventWorkspace>(m_lhs);
107 m_rhs_event = std::dynamic_pointer_cast<IMDEventWorkspace>(m_rhs);
108 }
109 }
110
111 this->checkInputs();
112
113 if (m_out == m_lhs) {
114 // A = A * B. -> we will do A *= B
115 } else {
116 // C = A + B. -> So first we clone A (lhs) into C
117 auto clone = createChildAlgorithm("CloneMDWorkspace", 0.0, 0.5, true);
118 clone->setProperty("InputWorkspace", m_lhs);
119 clone->executeAsChildAlg();
120 m_out = clone->getProperty("OutputWorkspace");
121 }
122
123 // Okay, at this point we are ready to do, e.g.,
124 // "m_out /= m_rhs"
125 if (!m_out)
126 throw std::runtime_error("Error creating the output workspace");
127 if (!m_rhs)
128 throw std::runtime_error("No RHS workspace specified!");
129
130 m_operand_event = std::dynamic_pointer_cast<IMDEventWorkspace>(m_rhs);
131 m_operand_histo = std::dynamic_pointer_cast<MDHistoWorkspace>(m_rhs);
132 m_operand_scalar = std::dynamic_pointer_cast<WorkspaceSingleValue>(m_rhs);
133
134 m_out_event = std::dynamic_pointer_cast<IMDEventWorkspace>(m_out);
135 m_out_histo = std::dynamic_pointer_cast<MDHistoWorkspace>(m_out);
136
137 if (m_out_event) {
138 // Call the templated virtual function for this type of MDEventWorkspace
139 this->execEvent();
140 } else if (m_out_histo) {
141 // MDHistoWorkspace as the output
142 if (m_operand_histo) {
143 if (m_out_histo->getNumDims() != m_operand_histo->getNumDims())
144 throw std::invalid_argument("Cannot perform " + this->name() +
145 " on MDHistoWorkspace's with a different number of dimensions.");
146 if (m_out_histo->getNPoints() != m_operand_histo->getNPoints())
147 throw std::invalid_argument("Cannot perform " + this->name() +
148 " on MDHistoWorkspace's with a different number of points.");
149
150 // Check that the dimensions span the same size, warn if they don't
151 for (size_t d = 0; d < m_out_histo->getNumDims(); d++) {
152 IMDDimension_const_sptr dimA = m_out_histo->getDimension(0);
153 IMDDimension_const_sptr dimB = m_operand_histo->getDimension(0);
154 if (dimA->getMinimum() != dimB->getMinimum() || dimA->getMaximum() != dimB->getMaximum())
155 g_log.warning() << "Dimension " << d << " (" << dimA->getName()
156 << ") has different extents in the two "
157 "MDHistoWorkspaces. The operation may not make "
158 "sense!\n";
159 }
161 } else if (m_operand_scalar)
163 else
164 throw std::runtime_error("Unexpected operand workspace type. Expected MDHistoWorkspace or "
165 "WorkspaceSingleValue, got " +
166 m_rhs->id());
167
168 // Clear any masking flags from the output workspace
169 if (m_out) {
170 m_out->clearMDMasking();
171 }
172
173 // When operating on MDHistoWorkspaces, add a simple flag
174 // that will be checked in BinMD to avoid binning a modified workspace
175 if (m_out_histo->getNumExperimentInfo() == 0) // Create a run if needed
176 m_out_histo->addExperimentInfo(ExperimentInfo_sptr(new ExperimentInfo()));
177 m_out_histo->getExperimentInfo(0)->mutableRun().addProperty(
178 new PropertyWithValue<std::string>("mdhisto_was_modified", "1"), true);
179 } else {
180 throw std::runtime_error("Unexpected output workspace type. Expected MDEventWorkspace or "
181 "MDHistoWorkspace, got " +
182 m_out->id());
183 }
184
185 // Give the output
186 setProperty("OutputWorkspace", m_out);
187}
188
189} // namespace Mantid::MDAlgorithms
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
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.
Definition: Algorithm.cpp:842
Kernel::Logger & g_log
Definition: Algorithm.h:451
This class is shared by a few Workspace types and holds information related to a particular experimen...
A property class for workspaces.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
The concrete, templated class for properties.
Mantid::API::IMDEventWorkspace_sptr m_rhs_event
Mantid::DataObjects::WorkspaceSingleValue_sptr m_operand_scalar
Operand WorkspaceSingleValue.
virtual void execHistoHisto(Mantid::DataObjects::MDHistoWorkspace_sptr out, Mantid::DataObjects::MDHistoWorkspace_const_sptr operand)=0
Run the algorithm with a MDHisotWorkspace as output and operand.
virtual std::string outputPropName() const
The name of the output workspace property.
void init() override
Initialize the algorithm's properties.
virtual void execHistoScalar(Mantid::DataObjects::MDHistoWorkspace_sptr out, Mantid::DataObjects::WorkspaceSingleValue_const_sptr scalar)=0
Run the algorithm with a MDHisotWorkspace as output, scalar and operand.
virtual std::string inputPropName1() const
The name of the first input workspace property.
int version() const override
Algorithm's version for identification.
virtual void initExtraProperties()
Optional extra properties.
Mantid::API::IMDEventWorkspace_sptr m_lhs_event
For checkInputs.
virtual void execEvent()=0
Run the algorithm with an MDEventWorkspace as output.
Mantid::DataObjects::MDHistoWorkspace_sptr m_operand_histo
Operand MDHistoWorkspace.
Mantid::DataObjects::WorkspaceSingleValue_sptr m_rhs_scalar
Mantid::API::IMDEventWorkspace_sptr m_operand_event
Operand MDEventWorkspace.
virtual bool commutative() const =0
Is the operation commutative?
const std::string name() const override
Algorithm's name for identification.
Mantid::API::IMDWorkspace_sptr m_lhs
LHS workspace.
Mantid::DataObjects::MDHistoWorkspace_sptr m_out_histo
Output MDHistoWorkspace.
Mantid::DataObjects::WorkspaceSingleValue_sptr m_lhs_scalar
virtual std::string inputPropName2() const
The name of the second input workspace property.
Mantid::API::IMDWorkspace_sptr m_out
Output workspace.
Mantid::DataObjects::MDHistoWorkspace_sptr m_rhs_histo
virtual void checkInputs()=0
Check the inputs and throw if the algorithm cannot be run.
const std::string category() const override
Algorithm's category for identification.
Mantid::DataObjects::MDHistoWorkspace_sptr m_lhs_histo
void exec() override
Execute the algorithm.
Mantid::API::IMDWorkspace_sptr m_rhs
RHS workspace.
Mantid::API::IMDEventWorkspace_sptr m_out_event
Output MDEventWorkspace.
std::shared_ptr< ExperimentInfo > ExperimentInfo_sptr
Shared pointer to ExperimentInfo.
std::shared_ptr< IMDWorkspace > IMDWorkspace_sptr
Shared pointer to the IMDWorkspace base class.
Definition: IMDWorkspace.h:146
std::shared_ptr< const IMDDimension > IMDDimension_const_sptr
Shared Pointer to const IMDDimension.
Definition: IMDDimension.h:101
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54