21#include "MantidHistogramData/Histogram.h"
40 "The name of the input workspace on the left hand side of the operation");
42 "The name of the input workspace on the right hand side of "
45 "The name to call the output workspace");
47 "Are workspaces with different number of spectra allowed? "
48 "For example, the LHSWorkspace might have one spectrum per detector, "
49 "but the RHSWorkspace could have its spectra averaged per bank. If true, "
50 "then matching between the LHS and RHS spectra is performed (all "
52 "in a LHS spectrum have to be in the corresponding RHS) in order to "
53 "apply the RHS spectrum to the LHS.");
56 "For EventWorkspaces only. This will clear out event lists "
57 "from the RHS workspace as the binary operation is applied. "
58 "This can prevent excessive memory use, e.g. when subtracting "
59 "an EventWorkspace from another: memory use will be approximately "
60 "constant instead of increasing by 50%. At completion, the RHS workspace "
75 if (this->
name() ==
"Divide" && !
bool(rhs_singleVal)) {
79 pow->setProperty(
"InputWorkspace", std::const_pointer_cast<MatrixWorkspace>(
m_rhs));
80 pow->setProperty(
"Exponent", -1.0);
81 pow->setProperty(
"OutputWorkspace", out);
82 pow->executeAsChildAlg();
83 out = pow->getProperty(
"OutputWorkspace");
89 std::const_pointer_cast<MatrixWorkspace>(
m_lhs));
91 mult->executeAsChildAlg();
92 out = mult->getProperty(
"OutputWorkspace");
95 }
else if (this->
name() ==
"Minus") {
98 minusOne->dataY(0)[0] = -1.0;
99 minusOne->dataE(0)[0] = 0.0;
105 mult->setProperty(
"OutputWorkspace", out);
106 mult->executeAsChildAlg();
107 out = mult->getProperty(
"OutputWorkspace");
113 std::const_pointer_cast<MatrixWorkspace>(
m_lhs));
115 plus->executeAsChildAlg();
116 out = plus->getProperty(
"OutputWorkspace");
140 }
catch (std::length_error &) {
147 }
catch (std::length_error &) {
157 m_elhs = std::dynamic_pointer_cast<const EventWorkspace>(
m_lhs);
158 m_erhs = std::dynamic_pointer_cast<const EventWorkspace>(
m_rhs);
187 std::ostringstream ostr;
188 ostr <<
"The two workspaces are not compatible for algorithm " << this->
name();
190 throw std::invalid_argument(ostr.str());
196 m_eout = std::dynamic_pointer_cast<EventWorkspace>(
m_out);
204 throw std::runtime_error(
"BinaryOperation:: the output was set to be an "
205 "EventWorkspace (m_keepEventWorkspace == true), "
206 "but the lhs is not an EventWorkspace. There "
207 "must be a mistake in the algorithm. Contact "
213 throw std::runtime_error(
"BinaryOperation:: the output was set to be lhs, and to be an "
214 "EventWorkspace (m_keepEventWorkspace == true), but the output is "
215 "not an EventWorkspace. There must be a mistake in the algorithm. "
216 "Contact the developers.");
221 m_eout = std::dynamic_pointer_cast<EventWorkspace>(
m_out);
241 if (specialLHS && specialRHS) {
242 m_out = create<SpecialWorkspace2D>(*specialLHS);
253 m_progress = std::make_unique<Progress>(
this, 0.0, 1.0,
m_lhs->getNumberHistograms());
265 }
else if (
m_rhs->getNumberHistograms() == 1)
276 bool mismatchedSpectra =
278 do2D(mismatchedSpectra);
311 if (lhs->axes() &&
rhs->axes())
314 lhs_unit = lhs->getAxis(0)->unit();
315 rhs_unit =
rhs->getAxis(0)->unit();
318 const std::string lhs_unitID = (lhs_unit ? lhs_unit->unitID() :
"");
319 const std::string rhs_unitID = (rhs_unit ? rhs_unit->unitID() :
"");
323 g_log.
error(
"The two workspace are not compatible because they have "
324 "different units on the X axis.");
330 if (!checkSizeCompatibilityResult.empty()) {
331 throw std::invalid_argument(checkSizeCompatibilityResult);
363 const size_t lhsSize = lhs->size();
364 const size_t rhsSize =
rhs->size();
369 if (lhsSize < rhsSize)
370 return "Left hand side smaller than right hand side.";
376 if (lhs->getNumberHistograms() ==
rhs->getNumberHistograms()) {
379 return "Number of histograms not identical.";
384 if (
m_rhsBlocksize == 1 && lhs->getNumberHistograms() ==
rhs->getNumberHistograms())
389 return "X arrays must match when performing this operation on a 2D "
393 const size_t rhsSpec =
rhs->getNumberHistograms();
396 if (rhsSpec == 1 || lhs->getNumberHistograms() == rhsSpec) {
401 return "Left and right sides should contain the same amount of spectra "
402 "or the right side should contain only one spectra.";
407 if (rhsSpec == 1 || lhs->getNumberHistograms() == rhsSpec) {
408 return "Number of y values not equal on left and right sides.";
412 return "Number of y values not equal on left and right sides and the "
413 "right side contained neither only one spectra or the same amount "
414 "of spectra as the left.";
433 bool continueOp(
true);
454 const double rhsY =
m_rhs->y(0)[0];
455 const double rhsE =
m_rhs->e(0)[0];
459 const int64_t numHists =
m_lhs->getNumberHistograms();
464 for (int64_t i = 0; i < numHists; ++i) {
475 for (int64_t i = 0; i < numHists; ++i) {
482 HistogramData::HistogramY &outY =
m_out->mutableY(i);
483 HistogramData::HistogramE &outE =
m_out->mutableE(i);
503 const int64_t numHists =
m_lhs->getNumberHistograms();
504 auto &outSpectrumInfo =
m_out->mutableSpectrumInfo();
505 auto &lhsSpectrumInfo =
m_lhs->spectrumInfo();
506 auto &rhsSpectrumInfo =
m_rhs->spectrumInfo();
510 for (int64_t i = 0; i < numHists; ++i) {
512 const double rhsY =
m_rhs->y(i)[0];
513 const double rhsE =
m_rhs->e(i)[0];
524 for (int64_t i = 0; i < numHists; ++i) {
526 const double rhsY =
m_rhs->y(i)[0];
527 const double rhsE =
m_rhs->e(i)[0];
535 HistogramData::HistogramY &outY =
m_out->mutableY(i);
536 HistogramData::HistogramE &outE =
m_out->mutableE(i);
566 const int64_t numHists =
m_lhs->getNumberHistograms();
568 for (int64_t i = 0; i < numHists; ++i) {
585 const int64_t numHists =
m_lhs->getNumberHistograms();
588 for (int64_t i = 0; i < numHists; ++i) {
604 const auto rhs =
m_rhs->histogram(0);
608 const int64_t numHists =
m_lhs->getNumberHistograms();
611 for (int64_t i = 0; i < numHists; ++i) {
618 HistogramData::HistogramY &outY =
m_out->mutableY(i);
619 HistogramData::HistogramE &outE =
m_out->mutableE(i);
638 if (mismatchedSpectra) {
646 auto &outSpectrumInfo =
m_out->mutableSpectrumInfo();
647 auto &lhsSpectrumInfo =
m_lhs->spectrumInfo();
648 auto &rhsSpectrumInfo =
m_rhs->spectrumInfo();
656 const int64_t numHists =
m_lhs->getNumberHistograms();
658 for (int64_t i = 0; i < numHists; ++i) {
663 if (mismatchedSpectra && table) {
664 rhs_wi = (*table)[i];
687 const int64_t numHists =
m_lhs->getNumberHistograms();
690 for (int64_t i = 0; i < numHists; ++i) {
694 if (mismatchedSpectra && table) {
695 rhs_wi = (*table)[i];
706 m_rhs->readE(rhs_wi));
723 const int64_t numHists =
m_lhs->getNumberHistograms();
726 for (int64_t i = 0; i < numHists; ++i) {
731 if (mismatchedSpectra && table) {
732 rhs_wi = (*table)[i];
745 HistogramData::HistogramY &outY =
m_out->mutableY(i);
746 HistogramData::HistogramE &outE =
m_out->mutableE(i);
770 const int64_t outHists = out->getNumberHistograms();
771 const int64_t rhsHists =
rhs->getNumberHistograms();
772 for (int64_t i = 0; i < outHists; ++i) {
776 if (
rhs->hasMaskedBins((rhsHists == 1) ? 0 : i)) {
778 MatrixWorkspace::MaskList::const_iterator it;
779 for (it = masks.begin(); it != masks.end(); ++it) {
780 out->flagMasked(i, it->first, it->second);
897 auto table = std::make_shared<BinaryOperationTable>();
899 auto rhs_nhist =
static_cast<int>(
rhs->getNumberHistograms());
900 auto lhs_nhist =
static_cast<int>(lhs->getNumberHistograms());
903 table->resize(lhs_nhist, -1);
908 for (
int lhsWI = 0; lhsWI < lhs_nhist; lhsWI++) {
912 const auto &lhsDets = lhs->getSpectrum(lhsWI).getDetectorIDs();
918 int64_t rhsWI = lhsWI;
919 if (rhsWI < rhs_nhist)
922 const auto &rhsDets =
rhs->getSpectrum(rhsWI).getDetectorIDs();
925 if (std::includes(rhsDets.begin(), rhsDets.end(), lhsDets.begin(), lhsDets.end())) {
927 (*table)[lhsWI] = rhsWI;
934 if (!done && (lhsDets.size() == 1)) {
938 auto lhsDets_it = lhsDets.cbegin();
939 detid_t lhs_detector_ID = *lhsDets_it;
943 auto map_it = rhs_det_to_wi.find(lhs_detector_ID);
944 if (map_it != rhs_det_to_wi.end()) {
945 rhsWI = map_it->second;
957 (*table)[lhsWI] = rhsWI;
968 for (rhsWI = 0; rhsWI < static_cast<int64_t>(rhs_nhist); rhsWI++) {
969 const auto &rhsDets =
rhs->getSpectrum(rhsWI).getDetectorIDs();
972 if (std::includes(rhsDets.begin(), rhsDets.end(), lhsDets.begin(), lhsDets.end())) {
974 (*table)[lhsWI] = rhsWI;
983 (*table)[lhsWI] = -1;
const std::vector< double > & rhs
std::map< DeltaEMode::Type, std::string > index
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
#define PARALLEL_FOR_NO_WSP_CHECK()
#define PARALLEL_CRITICAL(name)
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
void clear() override
Clears all properties under management.
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.
const std::string name() const override=0
function to return a name of the algorithm, must be overridden in all algorithms
virtual void clearData()=0
void setSharedX(const Kernel::cow_ptr< HistogramData::HistogramX > &x) &
Base MatrixWorkspace Abstract Class.
virtual ISpectrum & getSpectrum(const size_t index)=0
Return the underlying ISpectrum ptr at the given workspace index.
std::map< size_t, double > MaskList
Masked bins for each spectrum are stored as a set of pairs containing <bin index, weight>
API::SpectrumInfo is an intermediate step towards a SpectrumInfo that is part of Instrument-2....
void setMasked(const size_t index, bool masked)
Set the mask flag of the spectrum with given index.
bool hasDetectors(const size_t index) const
Returns true if the spectrum is associated with detectors in the instrument.
bool isMasked(const size_t index) const
Returns true if the detector(s) associated with the spectrum are masked.
A property class for workspaces.
bool m_do2D_even_for_SingleColumn_on_rhs
Special case for plus/minus: if there is only one bin on the RHS, use the 2D method (appending event ...
bool m_lhsRagged
Cache for if LHS workspace's is ragged.
void doSingleSpectrum()
Called when the m_rhs operand is a single spectrum.
virtual void operateOnRun(const API::Run &lhs, const API::Run &rhs, API::Run &ans) const
Only overridden by operations that affect the properties of the run (e.g.
size_t m_rhsBlocksize
Cache for RHS workspace's blocksize.
virtual bool propagateSpectraMask(const API::SpectrumInfo &lhsSpectrumInfo, const API::SpectrumInfo &rhsSpectrumInfo, const int64_t index, API::MatrixWorkspace &out, API::SpectrumInfo &outSpectrumInfo)
Checks if the spectra at the given index of either input workspace is masked.
void doSingleValue()
Called when the rhs operand is a single value.
void propagateBinMasks(const API::MatrixWorkspace_const_sptr &rhs, const API::MatrixWorkspace_sptr &out)
Copies any bin masking from the smaller/rhs input workspace to the output.
virtual void setOutputUnits(const API::MatrixWorkspace_const_sptr lhs, const API::MatrixWorkspace_const_sptr rhs, API::MatrixWorkspace_sptr out)
Should be overridden by operations that need to manipulate the units of the output workspace.
static BinaryOperationTable_sptr buildBinaryOperationTable(const API::MatrixWorkspace_const_sptr &lhs, const API::MatrixWorkspace_const_sptr &rhs)
Build up an BinaryOperationTable for performing a binary operation e.g.
bool m_keepEventWorkspace
Variable set to true if the operation allows the output to stay as an EventWorkspace.
std::shared_ptr< BinaryOperationTable > BinaryOperationTable_sptr
virtual bool checkCompatibility(const API::MatrixWorkspace_const_sptr lhs, const API::MatrixWorkspace_const_sptr rhs) const
Checks the compatibility of the two workspaces.
DataObjects::EventWorkspace_sptr m_eout
Output EventWorkspace.
virtual std::string checkSizeCompatibility(const API::MatrixWorkspace_const_sptr lhs, const API::MatrixWorkspace_const_sptr rhs) const
Checks the overall size compatibility of two workspaces.
void init() override
Initialisation method.
void doSingleColumn()
Called when the m_rhs operand is a 2D workspace of single values.
API::MatrixWorkspace_sptr m_out
Output workspace.
virtual void execEvent(DataObjects::EventWorkspace_const_sptr lhs, DataObjects::EventWorkspace_const_sptr rhs)
Execution method for event workspaces, to be overridden as needed.
bool handleSpecialDivideMinus()
Special handling for 1-WS and 1/WS.
OperandType getOperandType(const API::MatrixWorkspace_const_sptr &ws)
Get the type of operand from a workspace.
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...
virtual std::string outputPropName() const
The name of the output workspace property.
DataObjects::EventWorkspace_const_sptr m_erhs
Right-hand side EventWorkspace.
virtual bool checkEventCompatibility(const API::MatrixWorkspace_const_sptr lhs, const API::MatrixWorkspace_const_sptr rhs)
Checks the compatibility of event-based processing of the two workspaces.
std::unique_ptr< API::Progress > m_progress
Progress reporting.
virtual void performEventBinaryOperation(DataObjects::EventList &lhs, const DataObjects::EventList &rhs)
Carries out the binary operation IN-PLACE on a single EventList, with another EventList as the right-...
virtual void performBinaryOperation(const HistogramData::Histogram &lhs, const HistogramData::Histogram &rhs, HistogramData::HistogramY &YOut, HistogramData::HistogramE &EOut)=0
Carries out the binary operation on a single spectrum, with another spectrum as the right-hand operan...
void do2D(bool mismatchedSpectra)
Called when the two workspaces are the same size.
size_t m_lhsBlocksize
Cache for LHS workspace's blocksize.
void exec() override
Executes the algorithm.
virtual std::string inputPropName1() const
The name of the first input workspace property.
DataObjects::EventWorkspace_const_sptr m_elhs
Left-hand side EventWorkspace.
API::MatrixWorkspace_const_sptr m_rhs
Right-hand side workspace.
bool m_ClearRHSWorkspace
Flag to clear RHS workspace in binary operation.
virtual void checkRequirements()
Check what operation will be needed in order to apply the operation to these two types of workspaces.
virtual std::string inputPropName2() const
The name of the second input workspace property.
API::MatrixWorkspace_const_sptr m_lhs
Left-hand side workspace.
Marks code as not implemented yet.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void error(const std::string &msg)
Logs at error level.
The concrete, templated class for properties.
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::shared_ptr< const EventWorkspace > EventWorkspace_const_sptr
shared pointer to a const Workspace2D
std::shared_ptr< const WorkspaceSingleValue > WorkspaceSingleValue_const_sptr
std::shared_ptr< const Unit > Unit_const_sptr
Shared pointer to the Unit base class (const version)
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
int32_t detid_t
Typedef for a detector ID.
std::unordered_map< detid_t, size_t > detid2index_map
Map with key = detector ID, value = workspace index.
std::vector< double > MantidVec
typedef for the data storage used in Mantid matrix workspaces
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.
@ Input
An input workspace.
@ Output
An output workspace.