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// ===================================== EVENT LIST BINARY OPERATIONS
62// ==========================================
70 // We must histogram the rhs event list to multiply.
71 MantidVec rhsY, rhsE;
72 rhs.generateHistogram(rhs.x().rawData(), rhsY, rhsE);
73 lhs.multiply(rhs.x().rawData(), rhsY, rhsE);
74}
75
85 const MantidVec &rhsE) {
86 // Multiply is implemented at the EventList level.
87 lhs.multiply(rhsX, rhsY, rhsE);
88}
89
98void Multiply::performEventBinaryOperation(DataObjects::EventList &lhs, const double &rhsY, const double &rhsE) {
99 // Multiply is implemented at the EventList level.
100 lhs.multiply(rhsY, rhsE);
101}
102
103//---------------------------------------------------------------------------------------------
111 // Can commute workspaces?
112 m_flipSides = (m_rhs->size() > m_lhs->size());
113
114 // Both are vertical columns with one bin?
115 if ((m_rhsBlocksize == 1) && (m_lhsBlocksize == 1)) {
116 // Flip it if the RHS is event and you could keep events
117 if (m_erhs && !m_elhs)
118 m_flipSides = true;
119 }
120
121 // The RHS operand will be histogrammed first.
123
124 if ((m_elhs && !m_flipSides) || (m_flipSides && (m_erhs))) {
125 // The lhs (or RHS if it will get flipped) workspace
126 // is an EventWorkspace. It can be divided while keeping event-ishness
127 // Output will be EW
129 // Histogram sizes need not match
130 m_matchXSize = false;
131 } else {
132 m_keepEventWorkspace = false;
133 m_matchXSize = true;
134 }
135}
136
137//--------------------------------------------------------------------------------------------
151 // Fallback on the default checks
153 } else {
154
155 // A SingleValueWorkspace on the right, or matches anything
156 if (rhs->size() == 1)
157 return "";
158
159 // A SingleValueWorkspace on the left only matches if rhs was single value
160 // too. Why are you using mantid to do simple math?!?
161 if (lhs->size() == 1)
162 return "The left side cannot contain a single value if the right side "
163 "isn't also a single value.";
164
165 // RHS only has one value (1D vertical), so the number of histograms needs
166 // to match.
167 // Each lhs spectrum will be divided by that scalar
168 if (m_rhsBlocksize == 1 && lhs->getNumberHistograms() == rhs->getNumberHistograms())
169 return "";
170
171 if (m_matchXSize) {
172 // Past this point, for a 2D WS operation, we require the X arrays to
173 // match. Note this only checks the first spectrum
174 if (!WorkspaceHelpers::matchingBins(*lhs, *rhs, true)) {
175 return "X arrays must match when multiplying 2D workspaces.";
176 }
177 }
178
179 // We don't need to check for matching bins for events. Yay events!
180 const size_t rhsSpec = rhs->getNumberHistograms();
181
182 // If the rhs has a single spectrum, then we can divide. The block size does
183 // NOT need to match,
184 if (rhsSpec == 1)
185 return "";
186
187 // Are we allowing the division by different # of spectra, using detector
188 // IDs to match up?
190 return "";
191 }
192
193 // Otherwise, the number of histograms needs to match, but the block size of
194 // each does NOT need to match.
195
196 if (lhs->getNumberHistograms() == rhs->getNumberHistograms()) {
197 return "";
198 } else {
199 return "Number of histograms not identical.";
200 }
201 }
202}
203
204} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
const std::vector< double > & rhs
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_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:110
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:148
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:69
A class for holding :
Definition: EventList.h:56
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...
Definition: EventList.cpp:3324
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 MatrixWorkspace &ws1, const MatrixWorkspace &ws2, const bool firstOnly=false)
Checks whether the bins (X values) of two workspace are the same.