Mantid
Loading...
Searching...
No Matches
Multiply.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
9using namespace Mantid::API;
10using namespace Mantid::Kernel;
11using namespace Mantid::DataObjects;
12using std::size_t;
13
14namespace Mantid::Algorithms {
15// Register the class into the algorithm factory
16DECLARE_ALGORITHM(Multiply)
17
18void Multiply::performBinaryOperation(const HistogramData::Histogram &lhs, const HistogramData::Histogram &rhs,
19 HistogramData::HistogramY &YOut, HistogramData::HistogramE &EOut) {
20 const size_t bins = lhs.e().size();
21 for (size_t j = 0; j < bins; ++j) {
22 // Get references to the input Y's
23 const double leftY = lhs.y()[j];
24 const double rightY = rhs.y()[j];
25
26 // error multiplying two uncorrelated numbers, re-arrange so that you don't
27 // get infinity if leftY or rightY == 0
28 // (Sa/a)2 + (Sb/b)2 = (Sc/c)2
29 // (Sc)2 = (Sa c/a)2 + (Sb c/b)2
30 // = (Sa b)2 + (Sb a)2
31 EOut[j] = sqrt(pow(lhs.e()[j] * rightY, 2) + pow(rhs.e()[j] * leftY, 2));
32
33 // Copy the result last in case one of the input workspaces is also any
34 // output
35 YOut[j] = leftY * rightY;
36 }
37}
38
39void Multiply::performBinaryOperation(const HistogramData::Histogram &lhs, const double rhsY, const double rhsE,
40 HistogramData::HistogramY &YOut, HistogramData::HistogramE &EOut) {
41 const size_t bins = lhs.e().size();
42 for (size_t j = 0; j < bins; ++j) {
43 // Get reference to input Y
44 const double leftY = lhs.y()[j];
45
46 // see comment in the function above for the error formula
47 EOut[j] = sqrt(pow(lhs.e()[j] * rhsY, 2) + pow(rhsE * leftY, 2));
48
49 // Copy the result last in case one of the input workspaces is also any
50 // output
51 YOut[j] = leftY * rhsY;
52 }
53}
54
57 if (!lhs->isDistribution() || !rhs->isDistribution()) {
58 out->setDistribution(false);
59 }
60}
61
62// ===================================== EVENT LIST BINARY OPERATIONS
63// ==========================================
71 // We must histogram the rhs event list to multiply.
72 MantidVec rhsY, rhsE;
73 rhs.generateHistogram(rhs.x().rawData(), rhsY, rhsE);
74 lhs.multiply(rhs.x().rawData(), rhsY, rhsE);
75}
76
86 const MantidVec &rhsE) {
87 // Multiply is implemented at the EventList level.
88 lhs.multiply(rhsX, rhsY, rhsE);
89}
90
99void Multiply::performEventBinaryOperation(DataObjects::EventList &lhs, const double &rhsY, const double &rhsE) {
100 // Multiply is implemented at the EventList level.
101 lhs.multiply(rhsY, rhsE);
102}
103
104//---------------------------------------------------------------------------------------------
112 // Can commute workspaces?
113 m_flipSides = (m_rhs->size() > m_lhs->size());
114
115 // Both are vertical columns with one bin?
116 if ((m_rhsBlocksize == 1) && (m_lhsBlocksize == 1)) {
117 // Flip it if the RHS is event and you could keep events
118 if (m_erhs && !m_elhs)
119 m_flipSides = true;
120 }
121
122 // The RHS operand will be histogrammed first.
124
125 if ((m_elhs && !m_flipSides) || (m_flipSides && (m_erhs))) {
126 // The lhs (or RHS if it will get flipped) workspace
127 // is an EventWorkspace. It can be divided while keeping event-ishness
128 // Output will be EW
130 // Histogram sizes need not match
131 m_matchXSize = false;
132 } else {
133 m_keepEventWorkspace = false;
134 m_matchXSize = true;
135 }
136}
137
138//--------------------------------------------------------------------------------------------
152 // Fallback on the default checks
154 } else {
155
156 // A SingleValueWorkspace on the right, or matches anything
157 if (rhs->size() == 1)
158 return "";
159
160 // A SingleValueWorkspace on the left only matches if rhs was single value
161 // too. Why are you using mantid to do simple math?!?
162 if (lhs->size() == 1)
163 return "The left side cannot contain a single value if the right side "
164 "isn't also a single value.";
165
166 // RHS only has one value (1D vertical), so the number of histograms needs
167 // to match.
168 // Each lhs spectrum will be divided by that scalar
169 if (m_rhsBlocksize == 1 && lhs->getNumberHistograms() == rhs->getNumberHistograms())
170 return "";
171
172 if (m_matchXSize) {
173 // Past this point, for a 2D WS operation, we require the X arrays to
174 // match. Note this only checks the first spectrum except for ragged workspaces
176 return "X arrays must match when multiplying 2D workspaces.";
177 }
178 }
179
180 // We don't need to check for matching bins for events. Yay events!
181 const size_t rhsSpec = rhs->getNumberHistograms();
182
183 // If the rhs has a single spectrum, then we can divide. The block size does
184 // NOT need to match,
185 if (rhsSpec == 1)
186 return "";
187
188 // Are we allowing the division by different # of spectra, using detector
189 // IDs to match up?
191 return "";
192 }
193
194 // Otherwise, the number of histograms needs to match, but the block size of
195 // each does NOT need to match.
196
197 if (lhs->getNumberHistograms() == rhs->getNumberHistograms()) {
198 return "";
199 } else {
200 return "Number of histograms not identical.";
201 }
202 }
203}
204
205} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
const std::vector< double > & rhs
bool m_lhsRagged
Cache for if LHS workspace's is ragged.
size_t m_rhsBlocksize
Cache for RHS workspace's blocksize.
bool m_keepEventWorkspace
Variable set to true if the operation allows the output to stay as an EventWorkspace.
bool m_rhsRagged
Cache for if RHS workspace's is ragged.
bool m_AllowDifferentNumberSpectra
The property value.
bool m_useHistogramForRhsEventWorkspace
Are we going to use the histogram representation of the RHS event list when performing the operation?...
bool m_matchXSize
matchXSize set to true if the X sizes of histograms must match.
bool m_flipSides
flipSides set to true if the rhs and lhs operands should be flipped - for commutative binary operatio...
DataObjects::EventWorkspace_const_sptr m_erhs
Right-hand side EventWorkspace.
size_t m_lhsBlocksize
Cache for LHS workspace's blocksize.
DataObjects::EventWorkspace_const_sptr m_elhs
Left-hand side EventWorkspace.
API::MatrixWorkspace_const_sptr m_rhs
Right-hand side workspace.
API::MatrixWorkspace_const_sptr m_lhs
Left-hand side workspace.
std::string checkSizeCompatibility(const API::MatrixWorkspace_const_sptr lhs, const API::MatrixWorkspace_const_sptr rhs) const override
Checks the overall size compatability of two workspaces.
Multiply performs the product of two input workspaces.
Definition Multiply.h:29
void performBinaryOperation(const HistogramData::Histogram &lhs, const HistogramData::Histogram &rhs, HistogramData::HistogramY &YOut, HistogramData::HistogramE &EOut) override
Carries out the binary operation on a single spectrum, with another spectrum as the right-hand operan...
Definition Multiply.cpp:18
void checkRequirements() override
Check what operation will be needed in order to apply the operation to these two types of workspaces.
Definition Multiply.cpp:111
std::string checkSizeCompatibility(const API::MatrixWorkspace_const_sptr lhs, const API::MatrixWorkspace_const_sptr rhs) const override
Performs a simple check to see if the sizes of two workspaces are compatible for a binary operation I...
Definition Multiply.cpp:149
void setOutputUnits(const API::MatrixWorkspace_const_sptr lhs, const API::MatrixWorkspace_const_sptr rhs, API::MatrixWorkspace_sptr out) override
Should be overridden by operations that need to manipulate the units of the output workspace.
Definition Multiply.cpp:55
void performEventBinaryOperation(DataObjects::EventList &lhs, const DataObjects::EventList &rhs) override
Carries out the binary operation IN-PLACE on a single EventList, with another EventList as the right-...
Definition Multiply.cpp:70
A class for holding :
Definition EventList.h:57
void multiply(const double value, const double error=0.0) override
Multiply the weights in this event list by a scalar variable with an error; though the error can be 0...
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::vector< double > MantidVec
typedef for the data storage used in Mantid matrix workspaces
Definition cow_ptr.h:172
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.