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 +
11#include "MantidAPI/Run.h"
12#include "MantidAPI/TextAxis.h"
15#include "MantidIndexing/IndexInfo.h"
18
19using namespace Mantid::Indexing;
20using namespace Mantid::Kernel;
21using namespace Mantid::API;
22using namespace Mantid::DataObjects;
23
24namespace Mantid::Algorithms {
25// Register the algorithm into the AlgorithmFactory
26DECLARE_ALGORITHM(AppendSpectra)
27
28
29const std::string AppendSpectra::name() const { return "AppendSpectra"; }
30
32int AppendSpectra::version() const { return 1; }
33
37 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace1", "", Direction::Input,
38 std::make_shared<CommonBinsValidator>()),
39 "The name of the first input workspace");
40 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace2", "", Direction::Input,
41 std::make_shared<CommonBinsValidator>()),
42 "The name of the second input workspace");
43
44 declareProperty("ValidateInputs", true, "Perform a set of checks that the two input workspaces are compatible.");
45
46 declareProperty("Number", 1, std::make_shared<BoundedValidator<int>>(1, EMPTY_INT()),
47 "Append the spectra from InputWorkspace2 multiple times.");
48
49 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
50 "The name of the output workspace");
51
52 declareProperty("MergeLogs", false, "Whether to combine the logs of the two input workspaces");
53 declareProperty("AppendYAxisLabels", false,
54 "Whether to append y axis labels; this is done automatically if there is spectra overlap");
55}
56
60 // Retrieve the input workspaces
61 MatrixWorkspace_const_sptr ws1 = getProperty("InputWorkspace1");
62 MatrixWorkspace_const_sptr ws2 = getProperty("InputWorkspace2");
63 DataObjects::EventWorkspace_const_sptr eventWs1 = std::dynamic_pointer_cast<const EventWorkspace>(ws1);
64 DataObjects::EventWorkspace_const_sptr eventWs2 = std::dynamic_pointer_cast<const EventWorkspace>(ws2);
65
66 // Make sure that we are not mis-matching EventWorkspaces and other types of
67 // workspaces
68 if (((eventWs1) && (!eventWs2)) || ((!eventWs1) && (eventWs2))) {
69 const std::string message("Only one of the input workspaces are of type "
70 "EventWorkspace; please use matching workspace "
71 "types (both EventWorkspace or both "
72 "Workspace2D).");
73 g_log.error(message);
74 throw std::invalid_argument(message);
75 }
76
77 bool ValidateInputs = this->getProperty("ValidateInputs");
78 if (ValidateInputs) {
79 // Check that the input workspaces meet the requirements for this algorithm
80 this->checkCompatibility(*ws1, *ws2);
81 }
82
83 const bool mergeLogs = getProperty("MergeLogs");
84 const int number = getProperty("Number");
86
87 if (eventWs1 && eventWs2) {
88 // Both are event workspaces. Use the special method
89 DataObjects::EventWorkspace_sptr eOutput = this->execEvent(*eventWs1, *eventWs2);
90 for (int i = 1; i < number; i++) {
91 eOutput = this->execEvent(*eOutput, *eventWs2);
92 }
93 output = std::static_pointer_cast<MatrixWorkspace>(eOutput);
94 } else { // So it is a workspace 2D.
95 // The only restriction, even with ValidateInputs=false
96 if (ws1->blocksize() != ws2->blocksize())
97 throw std::runtime_error("Workspace2D's must have the same number of bins.");
98
99 output = execWS2D(*ws1, *ws2);
100 for (int i = 1; i < number; i++) {
101 output = execWS2D(*output, *ws2);
102 }
103 }
104
105 if (mergeLogs)
106 combineLogs(ws1->run(), ws2->run(), output->mutableRun());
107
108 // Set the output workspace
109 setProperty("OutputWorkspace", std::dynamic_pointer_cast<MatrixWorkspace>(output));
110}
111
121 MatrixWorkspace &output) {
122 specnum_t ws1min;
123 specnum_t ws1max;
124 getMinMax(ws1, ws1min, ws1max);
125
126 specnum_t ws2min;
127 specnum_t ws2max;
128 getMinMax(ws2, ws2min, ws2max);
129
130 const bool appendYAxis = getProperty("AppendYAxisLabels");
131 if (ws2min <= ws1max) {
132 auto indexInfo = output.indexInfo();
133 indexInfo.setSpectrumNumbers(0, static_cast<int32_t>(output.getNumberHistograms() - 1));
134 output.setIndexInfo(indexInfo);
135
136 appendYAxisLabels(ws1, ws2, output);
137 } else if (appendYAxis) {
138 appendYAxisLabels(ws1, ws2, output);
139 }
140}
141
143 const MatrixWorkspace &output) {
144 const auto yAxisNum = 1;
145 const auto yAxisWS1 = ws1.getAxis(yAxisNum);
146 const auto yAxisWS2 = ws2.getAxis(yAxisNum);
147 const auto outputYAxis = output.getAxis(yAxisNum);
148 const auto ws1Len = ws1.getNumberHistograms();
149
150 const bool isSpectra = yAxisWS1->isSpectra() && yAxisWS2->isSpectra();
151 const bool isTextAxis = yAxisWS1->isText() && yAxisWS2->isText();
152 const bool isNumericAxis = yAxisWS1->isNumeric() && yAxisWS2->isNumeric();
153
154 if (!isSpectra && !isTextAxis && !isNumericAxis) {
155 const std::string message(
156 "Y-Axis type mismatch. Ensure that the Y-axis types in both workspaces match. The Y-axis should be set to the "
157 "same type in each workspace, whether it be Numeric, Spectra, or Text.");
158
159 throw std::invalid_argument(message);
160 }
161
162 bool isBinEdgeAxis =
163 dynamic_cast<BinEdgeAxis *>(yAxisWS1) != nullptr && dynamic_cast<BinEdgeAxis *>(yAxisWS2) != nullptr;
164 auto outputTextAxis = dynamic_cast<TextAxis *>(outputYAxis);
165 const auto outputLen = output.getNumberHistograms() + (isBinEdgeAxis ? 1 : 0);
166 for (size_t i = 0; i < outputLen; ++i) {
167 if (isTextAxis) {
168 // check if we're outside the spectra of the first workspace
169 const std::string inputLabel = i < ws1Len ? yAxisWS1->label(i) : yAxisWS2->label(i - ws1Len);
170 outputTextAxis->setLabel(i, !inputLabel.empty() ? inputLabel : "");
171
172 } else if (isNumericAxis) {
173 // check if we're outside the spectra of the first workspace
174 const double inputVal = i < ws1Len ? yAxisWS1->getValue(i) : yAxisWS2->getValue(i - ws1Len);
175 outputYAxis->setValue(i, inputVal);
176 }
177 }
178}
179
181 // No need to worry about ordering here as for Plus - they have to be
182 // different workspaces
183 if (&lhs != &rhs) {
184 ans = lhs;
185 ans += rhs;
186 }
187}
188
189} // namespace Mantid::Algorithms
std::string name
Definition Run.cpp:60
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
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.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Stores numeric values that are assumed to be bin edge values.
Definition BinEdgeAxis.h:20
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:35
Class to represent a text axis of a workspace.
Definition TextAxis.h:36
A property class for workspaces.
Joins two partial, non-overlapping workspaces into one.
void combineLogs(const API::Run &lhs, const API::Run &rhs, API::Run &ans)
void appendYAxisLabels(const API::MatrixWorkspace &ws1, const API::MatrixWorkspace &ws2, const API::MatrixWorkspace &output)
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 or the y axis is a bin edges axis,...
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 the same instrument, unit and distribution flag.
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:108
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
Kernel::Logger g_log("DetermineSpinStateOrder")
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:24
int32_t specnum_t
Typedef for a spectrum Number.
Definition IDTypes.h:14
STL namespace.
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54