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");
145 m_elhs = std::dynamic_pointer_cast<const EventWorkspace>(
m_lhs);
146 m_erhs = std::dynamic_pointer_cast<const EventWorkspace>(
m_rhs);
174 std::ostringstream ostr;
175 ostr <<
"The two workspaces are not compatible for algorithm " << this->
name();
177 throw std::invalid_argument(ostr.str());
183 m_eout = std::dynamic_pointer_cast<EventWorkspace>(
m_out);
191 throw std::runtime_error(
"BinaryOperation:: the output was set to be an "
192 "EventWorkspace (m_keepEventWorkspace == true), "
193 "but the lhs is not an EventWorkspace. There "
194 "must be a mistake in the algorithm. Contact "
200 throw std::runtime_error(
"BinaryOperation:: the output was set to be lhs, and to be an "
201 "EventWorkspace (m_keepEventWorkspace == true), but the output is "
202 "not an EventWorkspace. There must be a mistake in the algorithm. "
203 "Contact the developers.");
208 m_eout = std::dynamic_pointer_cast<EventWorkspace>(
m_out);
229 if (specialLHS && specialRHS) {
230 m_out = create<SpecialWorkspace2D>(*specialLHS);
241 m_progress = std::make_unique<Progress>(
this, 0.0, 1.0,
m_lhs->getNumberHistograms());
253 }
else if (
m_rhs->getNumberHistograms() == 1)
264 bool mismatchedSpectra =
266 do2D(mismatchedSpectra);
299 if (lhs->axes() &&
rhs->axes())
302 lhs_unit = lhs->getAxis(0)->unit();
303 rhs_unit =
rhs->getAxis(0)->unit();
306 const std::string lhs_unitID = (lhs_unit ? lhs_unit->unitID() :
"");
307 const std::string rhs_unitID = (rhs_unit ? rhs_unit->unitID() :
"");
311 g_log.
error(
"The two workspace are not compatible because they have "
312 "different units on the X axis.");
318 if (!checkSizeCompatibilityResult.empty()) {
319 throw std::invalid_argument(checkSizeCompatibilityResult);
351 const size_t lhsSize = lhs->size();
352 const size_t rhsSize =
rhs->size();
357 if (lhsSize < rhsSize)
358 return "Left hand side smaller than right hand side.";
364 if (lhs->getNumberHistograms() ==
rhs->getNumberHistograms()) {
367 return "Number of histograms not identical.";
372 if (
m_rhsBlocksize == 1 && lhs->getNumberHistograms() ==
rhs->getNumberHistograms())
377 return "X arrays must match when performing this operation on a 2D "
381 const size_t rhsSpec =
rhs->getNumberHistograms();
384 if (rhsSpec == 1 || lhs->getNumberHistograms() == rhsSpec) {
389 return "Left and right sides should contain the same amount of spectra "
390 "or the right side should contain only one spectra.";
395 if (rhsSpec == 1 || lhs->getNumberHistograms() == rhsSpec) {
396 return "Number of y values not equal on left and right sides.";
400 return "Number of y values not equal on left and right sides and the "
401 "right side contained neither only one spectra or the same amount "
402 "of spectra as the left.";
421 bool continueOp(
true);
442 const double rhsY =
m_rhs->y(0)[0];
443 const double rhsE =
m_rhs->e(0)[0];
447 const int64_t numHists =
m_lhs->getNumberHistograms();
452 for (int64_t i = 0; i < numHists; ++i) {
463 for (int64_t i = 0; i < numHists; ++i) {
470 HistogramData::HistogramY &outY =
m_out->mutableY(i);
471 HistogramData::HistogramE &outE =
m_out->mutableE(i);
491 const int64_t numHists =
m_lhs->getNumberHistograms();
492 auto &outSpectrumInfo =
m_out->mutableSpectrumInfo();
493 auto &lhsSpectrumInfo =
m_lhs->spectrumInfo();
494 auto &rhsSpectrumInfo =
m_rhs->spectrumInfo();
498 for (int64_t i = 0; i < numHists; ++i) {
500 const double rhsY =
m_rhs->y(i)[0];
501 const double rhsE =
m_rhs->e(i)[0];
512 for (int64_t i = 0; i < numHists; ++i) {
514 const double rhsY =
m_rhs->y(i)[0];
515 const double rhsE =
m_rhs->e(i)[0];
523 HistogramData::HistogramY &outY =
m_out->mutableY(i);
524 HistogramData::HistogramE &outE =
m_out->mutableE(i);
554 const int64_t numHists =
m_lhs->getNumberHistograms();
556 for (int64_t i = 0; i < numHists; ++i) {
573 const int64_t numHists =
m_lhs->getNumberHistograms();
576 for (int64_t i = 0; i < numHists; ++i) {
592 const auto rhs =
m_rhs->histogram(0);
596 const int64_t numHists =
m_lhs->getNumberHistograms();
599 for (int64_t i = 0; i < numHists; ++i) {
606 HistogramData::HistogramY &outY =
m_out->mutableY(i);
607 HistogramData::HistogramE &outE =
m_out->mutableE(i);
626 if (mismatchedSpectra) {
634 auto &outSpectrumInfo =
m_out->mutableSpectrumInfo();
635 auto &lhsSpectrumInfo =
m_lhs->spectrumInfo();
636 auto &rhsSpectrumInfo =
m_rhs->spectrumInfo();
644 const int64_t numHists =
m_lhs->getNumberHistograms();
646 for (int64_t i = 0; i < numHists; ++i) {
651 if (mismatchedSpectra && table) {
652 rhs_wi = (*table)[i];
675 const int64_t numHists =
m_lhs->getNumberHistograms();
678 for (int64_t i = 0; i < numHists; ++i) {
682 if (mismatchedSpectra && table) {
683 rhs_wi = (*table)[i];
694 m_rhs->readE(rhs_wi));
711 const int64_t numHists =
m_lhs->getNumberHistograms();
714 for (int64_t i = 0; i < numHists; ++i) {
719 if (mismatchedSpectra && table) {
720 rhs_wi = (*table)[i];
733 HistogramData::HistogramY &outY =
m_out->mutableY(i);
734 HistogramData::HistogramE &outE =
m_out->mutableE(i);
758 const int64_t outHists = out->getNumberHistograms();
759 const int64_t rhsHists =
rhs->getNumberHistograms();
760 for (int64_t i = 0; i < outHists; ++i) {
764 if (
rhs->hasMaskedBins((rhsHists == 1) ? 0 : i)) {
766 MatrixWorkspace::MaskList::const_iterator it;
767 for (it = masks.begin(); it != masks.end(); ++it) {
768 out->flagMasked(i, it->first, it->second);
885 auto table = std::make_shared<BinaryOperationTable>();
887 auto rhs_nhist =
static_cast<int>(
rhs->getNumberHistograms());
888 auto lhs_nhist =
static_cast<int>(lhs->getNumberHistograms());
891 table->resize(lhs_nhist, -1);
896 for (
int lhsWI = 0; lhsWI < lhs_nhist; lhsWI++) {
900 const auto &lhsDets = lhs->getSpectrum(lhsWI).getDetectorIDs();
906 int64_t rhsWI = lhsWI;
907 if (rhsWI < rhs_nhist)
910 const auto &rhsDets =
rhs->getSpectrum(rhsWI).getDetectorIDs();
913 if (std::includes(rhsDets.begin(), rhsDets.end(), lhsDets.begin(), lhsDets.end())) {
915 (*table)[lhsWI] = rhsWI;
922 if (!done && (lhsDets.size() == 1)) {
926 auto lhsDets_it = lhsDets.cbegin();
927 detid_t lhs_detector_ID = *lhsDets_it;
931 auto map_it = rhs_det_to_wi.find(lhs_detector_ID);
932 if (map_it != rhs_det_to_wi.end()) {
933 rhsWI = map_it->second;
945 (*table)[lhsWI] = rhsWI;
956 for (rhsWI = 0; rhsWI < static_cast<int64_t>(rhs_nhist); rhsWI++) {
957 const auto &rhsDets =
rhs->getSpectrum(rhsWI).getDetectorIDs();
960 if (std::includes(rhsDets.begin(), rhsDets.end(), lhsDets.begin(), lhsDets.end())) {
962 (*table)[lhsWI] = rhsWI;
971 (*table)[lhsWI] = -1;
984Parallel::ExecutionMode
986 if (
static_cast<bool>(
getProperty(
"AllowDifferentNumberSpectra")))
987 return Parallel::ExecutionMode::Invalid;
992 return getCorrespondingExecutionMode(storageModes.begin()->second);
994 if (
rhs == Parallel::StorageMode::Cloned) {
996 if (std::dynamic_pointer_cast<const WorkspaceSingleValue>(ws))
997 return getCorrespondingExecutionMode(lhs);
1000 return Parallel::ExecutionMode::Invalid;
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
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 ...
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_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.
Parallel::ExecutionMode getParallelExecutionMode(const std::map< std::string, Parallel::StorageMode > &storageModes) const override
Get correct execution mode based on input storage modes for an MPI run.
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 MatrixWorkspace &ws1, 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.