Mantid
Loading...
Searching...
No Matches
AppendSpectra.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 +
10#include "MantidAPI/Run.h"
11#include "MantidAPI/TextAxis.h"
14#include "MantidIndexing/IndexInfo.h"
17
18using namespace Mantid::Indexing;
19using namespace Mantid::Kernel;
20using namespace Mantid::API;
21using namespace Mantid::DataObjects;
22
23namespace Mantid::Algorithms {
24// Register the algorithm into the AlgorithmFactory
25DECLARE_ALGORITHM(AppendSpectra)
26
27
28const std::string AppendSpectra::name() const { return "AppendSpectra"; }
29
31int AppendSpectra::version() const { return 1; }
32
36 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace1", "", Direction::Input,
37 std::make_shared<CommonBinsValidator>()),
38 "The name of the first input workspace");
39 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace2", "", Direction::Input,
40 std::make_shared<CommonBinsValidator>()),
41 "The name of the second input workspace");
42
43 declareProperty("ValidateInputs", true, "Perform a set of checks that the two input workspaces are compatible.");
44
45 declareProperty("Number", 1, std::make_shared<BoundedValidator<int>>(1, EMPTY_INT()),
46 "Append the spectra from InputWorkspace2 multiple times.");
47
48 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
49 "The name of the output workspace");
50
51 declareProperty("MergeLogs", false, "Whether to combine the logs of the two input workspaces");
52}
53
57 // Retrieve the input workspaces
58 MatrixWorkspace_const_sptr ws1 = getProperty("InputWorkspace1");
59 MatrixWorkspace_const_sptr ws2 = getProperty("InputWorkspace2");
60 DataObjects::EventWorkspace_const_sptr eventWs1 = std::dynamic_pointer_cast<const EventWorkspace>(ws1);
61 DataObjects::EventWorkspace_const_sptr eventWs2 = std::dynamic_pointer_cast<const EventWorkspace>(ws2);
62
63 // Make sure that we are not mis-matching EventWorkspaces and other types of
64 // workspaces
65 if (((eventWs1) && (!eventWs2)) || ((!eventWs1) && (eventWs2))) {
66 const std::string message("Only one of the input workspaces are of type "
67 "EventWorkspace; please use matching workspace "
68 "types (both EventWorkspace's or both "
69 "Workspace2D's).");
70 g_log.error(message);
71 throw std::invalid_argument(message);
72 }
73
74 bool ValidateInputs = this->getProperty("ValidateInputs");
75 if (ValidateInputs) {
76 // Check that the input workspaces meet the requirements for this algorithm
77 this->checkCompatibility(*ws1, *ws2);
78 }
79
80 const bool mergeLogs = getProperty("MergeLogs");
81 const int number = getProperty("Number");
83
84 if (eventWs1 && eventWs2) {
85 // Both are event workspaces. Use the special method
86 DataObjects::EventWorkspace_sptr eOutput = this->execEvent(*eventWs1, *eventWs2);
87 for (int i = 1; i < number; i++) {
88 eOutput = this->execEvent(*eOutput, *eventWs2);
89 }
90 output = std::static_pointer_cast<MatrixWorkspace>(eOutput);
91 } else { // So it is a workspace 2D.
92 // The only restriction, even with ValidateInputs=false
93 if (ws1->blocksize() != ws2->blocksize())
94 throw std::runtime_error("Workspace2D's must have the same number of bins.");
95
96 output = execWS2D(*ws1, *ws2);
97 for (int i = 1; i < number; i++) {
98 output = execWS2D(*output, *ws2);
99 }
100 }
101
102 if (mergeLogs)
103 combineLogs(ws1->run(), ws2->run(), output->mutableRun());
104
105 // Set the output workspace
106 setProperty("OutputWorkspace", std::dynamic_pointer_cast<MatrixWorkspace>(output));
107}
108
118 MatrixWorkspace &output) {
119 specnum_t ws1min;
120 specnum_t ws1max;
121 getMinMax(ws1, ws1min, ws1max);
122
123 specnum_t ws2min;
124 specnum_t ws2max;
125 getMinMax(ws2, ws2min, ws2max);
126
127 // is everything possibly ok?
128 if (ws2min > ws1max)
129 return;
130
131 auto indexInfo = output.indexInfo();
132 indexInfo.setSpectrumNumbers(0, static_cast<int32_t>(output.getNumberHistograms() - 1));
133 output.setIndexInfo(indexInfo);
134
135 const int yAxisNum = 1;
136 const auto yAxisWS1 = ws1.getAxis(yAxisNum);
137 const auto yAxisWS2 = ws2.getAxis(yAxisNum);
138 auto outputYAxis = output.getAxis(yAxisNum);
139 const auto ws1len = ws1.getNumberHistograms();
140
141 const bool isTextAxis = yAxisWS1->isText() && yAxisWS2->isText();
142 const bool isNumericAxis = yAxisWS1->isNumeric() && yAxisWS2->isNumeric();
143
144 auto outputTextAxis = dynamic_cast<TextAxis *>(outputYAxis);
145 for (size_t i = 0; i < output.getNumberHistograms(); ++i) {
146 if (isTextAxis) {
147 // check if we're outside the spectra of the first workspace
148 const std::string inputLabel = i < ws1len ? yAxisWS1->label(i) : yAxisWS2->label(i - ws1len);
149 outputTextAxis->setLabel(i, !inputLabel.empty() ? inputLabel : "");
150
151 } else if (isNumericAxis) {
152 // check if we're outside the spectra of the first workspace
153 const double inputVal = i < ws1len ? yAxisWS1->getValue(i) : yAxisWS2->getValue(i - ws1len);
154 outputYAxis->setValue(i, inputVal);
155 }
156 }
157}
158
160 // No need to worry about ordering here as for Plus - they have to be
161 // different workspaces
162 if (&lhs != &rhs) {
163 ans = lhs;
164 ans += rhs;
165 }
166}
167
168} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
const std::vector< double > & rhs
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
Kernel::Logger & g_log
Definition: Algorithm.h:451
Base MatrixWorkspace Abstract Class.
virtual std::size_t getNumberHistograms() const =0
Returns the number of histograms in the workspace.
const Indexing::IndexInfo & indexInfo() const
Returns a const reference to the IndexInfo object of the workspace.
virtual Axis * getAxis(const std::size_t &axisIndex) const
Get a non owning pointer to a workspace axis.
void setIndexInfo(const Indexing::IndexInfo &indexInfo)
Sets the IndexInfo object of the workspace.
This class stores information regarding an experimental run as a series of log entries.
Definition: Run.h:38
Class to represent a text axis of a workspace.
Definition: TextAxis.h:36
std::string label(const std::size_t &index) const override
Get the label at the specified index.
Definition: TextAxis.cpp:97
A property class for workspaces.
Joins two partial, non-overlapping workspaces into one.
Definition: AppendSpectra.h:29
void combineLogs(const API::Run &lhs, const API::Run &rhs, API::Run &ans)
void fixSpectrumNumbers(const API::MatrixWorkspace &ws1, const API::MatrixWorkspace &ws2, API::MatrixWorkspace &output) override
If there is an overlap in spectrum numbers between ws1 and ws2, then the spectrum numbers are reset a...
int version() const override
Algorithm's version for identification.
void init() override
Initialize the algorithm's properties.
void exec() override
Execute the algorithm.
void checkCompatibility(const API::MatrixWorkspace &ws1, const API::MatrixWorkspace &ws2)
Checks that the two input workspace have common size and the same instrument & unit.
DataObjects::EventWorkspace_sptr execEvent(const DataObjects::EventWorkspace &eventWs1, const DataObjects::EventWorkspace &eventWs2)
Executes the algorithm for event workspace inputs.
void getMinMax(const API::MatrixWorkspace &ws, specnum_t &min, specnum_t &max)
Determine the minimum and maximum spectra ids.
API::MatrixWorkspace_sptr execWS2D(const API::MatrixWorkspace &ws1, const API::MatrixWorkspace &ws2)
Executes the algorithm for histogram workspace inputs.
BoundedValidator is a validator that requires the values to be between upper or lower bounds,...
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.
Definition: Logger.cpp:77
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< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
Definition: EmptyValues.h:25
int32_t specnum_t
Typedef for a spectrum Number.
Definition: IDTypes.h:16
STL namespace.
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54