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