Mantid
Loading...
Searching...
No Matches
ConjoinWorkspaces.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 +
14
15namespace Mantid::Algorithms {
16
17using std::size_t;
18using namespace Kernel;
19using namespace API;
20using namespace DataObjects;
21
22// Register the algorithm into the AlgorithmFactory
23DECLARE_ALGORITHM(ConjoinWorkspaces)
24
25//----------------------------------------------------------------------------------------------
27void ConjoinWorkspaces::init() {
28 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace1", "", Direction::InOut),
29 "The name of the first input workspace");
30 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace2", "", Direction::Input),
31 "The name of the second input workspace");
32 declareProperty(std::make_unique<PropertyWithValue<bool>>("CheckOverlapping", true, Direction::Input),
33 "Verify that the supplied data do not overlap");
34 declareProperty(std::make_unique<PropertyWithValue<std::string>>("YAxisLabel", "", Direction::Input),
35 "The label to set the Y axis to");
36 declareProperty(std::make_unique<PropertyWithValue<std::string>>("YAxisUnit", "", Direction::Input),
37 "The unit to set the Y axis to");
38}
39
40//----------------------------------------------------------------------------------------------
46 // Retrieve the input workspaces
47 MatrixWorkspace_const_sptr ws1 = getProperty("InputWorkspace1");
48 MatrixWorkspace_const_sptr ws2 = getProperty("InputWorkspace2");
49 DataObjects::EventWorkspace_const_sptr eventWs1 = std::dynamic_pointer_cast<const EventWorkspace>(ws1);
50 DataObjects::EventWorkspace_const_sptr eventWs2 = std::dynamic_pointer_cast<const EventWorkspace>(ws2);
51
52 // Make sure that we are not mis-matching EventWorkspaces and other types of
53 // workspaces
54 if (((eventWs1) && (!eventWs2)) || ((!eventWs1) && (eventWs2))) {
55 const std::string message("Only one of the input workspaces are of type "
56 "EventWorkspace; please use matching workspace "
57 "types (both EventWorkspace's or both "
58 "Workspace2D's).");
59 g_log.error(message);
60 throw std::invalid_argument(message);
61 }
62
63 if (eventWs1 && eventWs2) {
64 this->checkCompatibility(*eventWs1, *eventWs2);
65 auto output = conjoinEvents(*eventWs1, *eventWs2);
66 setYUnitAndLabel(*output);
67 // Set the result workspace to the first input
68 setProperty("InputWorkspace1", output);
69 } else {
70 auto output = conjoinHistograms(*ws1, *ws2);
71 setYUnitAndLabel(*output);
72 // Set the result workspace to the first input
73 setProperty("InputWorkspace1", output);
74 }
75
76 // Delete the second input workspace from the ADS
77 AnalysisDataService::Instance().remove(getPropertyValue("InputWorkspace2"));
78}
79
80//----------------------------------------------------------------------------------------------
90 bool checkSpectra) const {
91 // Loop through the first workspace adding all the spectrum numbers & UDETS to
92 // a set
93 std::set<specnum_t> spectra;
94 std::set<detid_t> detectors;
95 const size_t &nhist1 = ws1.getNumberHistograms();
96 for (size_t i = 0; i < nhist1; ++i) {
97 const auto &spec = ws1.getSpectrum(i);
98 const specnum_t spectrum = spec.getSpectrumNo();
99 spectra.insert(spectrum);
100 const auto &dets = spec.getDetectorIDs();
101 for (auto const &det : dets) {
102 detectors.insert(det);
103 }
104 }
105
106 // Now go throught the spectrum numbers & UDETS in the 2nd workspace, making
107 // sure that there's no overlap
108 const size_t &nhist2 = ws2.getNumberHistograms();
109 for (size_t j = 0; j < nhist2; ++j) {
110 const auto &spec = ws2.getSpectrum(j);
111 const specnum_t spectrum = spec.getSpectrumNo();
112 if (checkSpectra) {
113 if (spectrum > 0 && spectra.find(spectrum) != spectra.end()) {
114 g_log.error() << "The input workspaces have overlapping spectrum numbers " << spectrum << "\n";
115 throw std::invalid_argument("The input workspaces have overlapping spectrum numbers");
116 }
117 }
118 const auto &dets = spec.getDetectorIDs();
119 for (const auto &det : dets) {
120 if (detectors.find(det) != detectors.end()) {
121 g_log.error() << "The input workspaces have common detectors: " << (det) << "\n";
122 throw std::invalid_argument("The input workspaces have common detectors");
123 }
124 }
125 }
126}
127
136 const DataObjects::EventWorkspace &ws2) {
137 this->checkCompatibility(ws1, ws2);
138
139 // Check there is no overlap
140 if (this->getProperty("CheckOverlapping")) {
141 this->checkForOverlap(ws1, ws2, false);
142 m_overlapChecked = true;
143 }
144
145 // Both are event workspaces. Use the special method
146 auto output = this->execEvent(ws1, ws2);
147
148 // Copy the history from the original workspace
149 output->history().addHistory(ws1.getHistory());
150 return output;
151}
152
161 const API::MatrixWorkspace &ws2) {
162 // Check that the input workspaces meet the requirements for this algorithm
163 this->checkCompatibility(ws1, ws2);
164
165 if (this->getProperty("CheckOverlapping")) {
166 this->checkForOverlap(ws1, ws2, true);
167 m_overlapChecked = true;
168 }
169
170 auto output = execWS2D(ws1, ws2);
171
172 // Copy the history from the original workspace
173 output->history().addHistory(ws1.getHistory());
174 return output;
175}
176
177/***
178 * This will ensure the spectrum numbers do not overlap by starting the second
179 *on at the first + 1
180 *
181 * @param ws1 The first workspace supplied to the algorithm.
182 * @param ws2 The second workspace supplied to the algorithm.
183 * @param output The workspace that is going to be returned by the algorithm.
184 */
186 MatrixWorkspace &output) {
187
188 if (this->getProperty("CheckOverlapping")) {
189 // If CheckOverlapping is required, then either skip fixing spectrum number
190 // or get stopped by an exception
191 if (!m_overlapChecked)
192 // This throws if the spectrum numbers overlap
193 checkForOverlap(ws1, ws2, true);
194 // At this point, we don't have to do anything
195 return;
196 }
197
198 // Because we were told not to check overlapping, fix up any errors we might
199 // run into
200 specnum_t min = -1;
201 specnum_t max = -1;
202 getMinMax(output, min, max);
203 if (max - min >= static_cast<specnum_t>(output.getNumberHistograms())) // nothing to do then
204 return;
205
206 // information for remapping the spectra numbers
207 specnum_t ws1min = -1;
208 specnum_t ws1max = -1;
209 getMinMax(ws1, ws1min, ws1max);
210
211 // change the axis by adding the maximum existing spectrum number to the
212 // current value
213 for (size_t i = ws1.getNumberHistograms(); i < output.getNumberHistograms(); i++) {
214 specnum_t origid = output.getSpectrum(i).getSpectrumNo();
215 output.getSpectrum(i).setSpectrumNo(origid + ws1max);
216 }
217}
218
222 // Call the base class method for most of the functionality
223 const bool retval = Algorithm::processGroups();
224
225 // If that was successful, remove the now empty group in the second input
226 // workspace property
227 if (retval)
228 AnalysisDataService::Instance().remove(getPropertyValue("InputWorkspace2"));
229
230 return retval;
231}
232
234 const std::string yLabel = getPropertyValue("YAXisLabel");
235 const std::string yUnit = getPropertyValue("YAxisUnit");
236
237 // Unit must be moved before label, as changing the unit resets the label
238 if (!yUnit.empty())
239 ws.setYUnit(yUnit);
240
241 if (!yLabel.empty())
242 ws.setYUnitLabel(yLabel);
243}
244
245} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
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
virtual bool processGroups()
Process WorkspaceGroup inputs.
Definition: Algorithm.cpp:1365
specnum_t getSpectrumNo() const
Definition: ISpectrum.cpp:123
void setSpectrumNo(specnum_t num)
Sets the the spectrum number of this spectrum.
Definition: ISpectrum.cpp:127
Base MatrixWorkspace Abstract Class.
virtual ISpectrum & getSpectrum(const size_t index)=0
Return the underlying ISpectrum ptr at the given workspace index.
virtual std::size_t getNumberHistograms() const =0
Returns the number of histograms in the workspace.
void setYUnitLabel(const std::string &newLabel)
Sets a new caption for the data (Y axis) in the workspace.
void setYUnit(const std::string &newUnit)
Sets a new unit for the data (Y axis) in the workspace.
A property class for workspaces.
const WorkspaceHistory & getHistory() const
Returns a reference to the WorkspaceHistory const.
Definition: Workspace.h:84
Joins two partial, non-overlapping workspaces into one.
void checkForOverlap(const API::MatrixWorkspace &ws1, const API::MatrixWorkspace &ws2, bool checkSpectra) const
Checks that the two input workspaces have non-overlapping spectra numbers and contributing detectors.
bool processGroups() override
Appends the removal of the empty group after execution to the Algorithm::processGroups() method.
void exec() override
Executes the algorithm.
void fixSpectrumNumbers(const API::MatrixWorkspace &ws1, const API::MatrixWorkspace &ws2, API::MatrixWorkspace &output) override
Abstract method to be implemented in concrete algorithm classes.
bool m_overlapChecked
True if spectra overlap.
API::MatrixWorkspace_sptr conjoinHistograms(const API::MatrixWorkspace &ws1, const API::MatrixWorkspace &ws2)
Conjoin two histogram workspaces together, including the history.
void setYUnitAndLabel(API::MatrixWorkspace &ws) const
API::MatrixWorkspace_sptr conjoinEvents(const DataObjects::EventWorkspace &ws1, const DataObjects::EventWorkspace &ws2)
Conjoin two event workspaces together, including the history.
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.
This class is intended to fulfill the design specified in <https://github.com/mantidproject/documents...
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
The concrete, templated class for properties.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
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
int32_t specnum_t
Typedef for a spectrum Number.
Definition: IDTypes.h:16
@ InOut
Both an input & output workspace.
Definition: Property.h:55
@ Input
An input workspace.
Definition: Property.h:53