Mantid
Loading...
Searching...
No Matches
Stitch.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2021 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 +
7
8#include <utility>
9
13#include "MantidAPI/Run.h"
21
22using namespace Mantid::API;
23using namespace Mantid::DataObjects;
24using namespace Mantid::Kernel;
25
26namespace {
27static const std::string INPUT_WORKSPACE_PROPERTY = "InputWorkspaces";
28static const std::string REFERENCE_WORKSPACE_PROPERTY = "ReferenceWorkspace";
29static const std::string COMBINATION_BEHAVIOUR_PROPERTY = "CombinationBehaviour";
30static const std::string SCALE_FACTOR_CALCULATION_PROPERTY = "ScaleFactorCalculation";
31static const std::string MANUAL_SCALE_FACTORS_PROPERTY = "ManualScaleFactors";
32static const std::string TIE_SCALE_FACTORS_PROPERTY = "TieScaleFactors";
33static const std::string OUTPUT_WORKSPACE_PROPERTY = "OutputWorkspace";
34static const std::string OUTPUT_SCALE_FACTORS_PROPERTY = "OutputScaleFactorsWorkspace";
35
43std::pair<double, double> getInterval(const MatrixWorkspace &ws) {
44 return std::make_pair(ws.readX(0).front(), ws.readX(0).back());
45}
46
53bool compareInterval(const MatrixWorkspace_sptr &ws1, const MatrixWorkspace_sptr &ws2) {
54 const auto minmax1 = getInterval(*ws1);
55 const auto minmax2 = getInterval(*ws2);
56 if (minmax1.first < minmax2.first) {
57 return true;
58 } else if (minmax1.first > minmax2.first) {
59 return false;
60 } else {
61 return minmax1.second < minmax2.second;
62 }
63}
64
72std::pair<double, double> getOverlap(const MatrixWorkspace_sptr &ws1, const MatrixWorkspace_sptr &ws2) {
73 const auto minmax1 = getInterval(*ws1);
74 const auto minmax2 = getInterval(*ws2);
75 if (minmax1.second < minmax2.first || minmax2.second < minmax1.first) {
76 std::stringstream ss;
77 ss << "No overlap is found between the intervals: [" << minmax1.first << "," << minmax1.second << "] and ["
78 << minmax2.first << ", " << minmax2.second << "]";
79 throw std::runtime_error(ss.str());
80 }
81 return std::make_pair(std::max(minmax1.first, minmax2.first), std::min(minmax1.second, minmax2.second));
82}
83
89double median(const std::vector<double> &vec) {
90 if (vec.empty())
91 return 1;
92 const size_t s = vec.size();
93 std::vector<double> sorted = vec;
94 std::sort(sorted.begin(), sorted.end());
95 if (s % 2 == 0) {
96 return 0.5 * (sorted[s / 2] + sorted[s / 2 - 1]);
97 } else {
98 return sorted[s / 2];
99 }
100}
101
107MatrixWorkspace_sptr medianWorkspaceLocal(const MatrixWorkspace_sptr &ws) {
108 const size_t nSpectra = ws->getNumberHistograms();
109 MatrixWorkspace_sptr out = WorkspaceFactory::Instance().create("Workspace2D", nSpectra, 1, 1);
110 PARALLEL_FOR_IF(threadSafe(*ws, *out))
111 for (int i = 0; i < static_cast<int>(nSpectra); ++i) {
112 const size_t wsIndex = static_cast<size_t>(i);
113 auto &y = out->mutableY(wsIndex);
114 y = std::vector<double>(1, median(ws->readY(wsIndex)));
115 }
116 return out;
117}
118
124MatrixWorkspace_sptr medianWorkspaceGlobal(const MatrixWorkspace_sptr &ws) {
125 MatrixWorkspace_sptr out = WorkspaceFactory::Instance().create("Workspace2D", 1, 1, 1);
126 std::vector<double> allY;
127 allY.reserve(ws->getNumberHistograms() * ws->blocksize());
128 for (size_t i = 0; i < ws->getNumberHistograms(); ++i) {
129 const auto spectrum = ws->mutableY(i).rawData();
130 std::copy(spectrum.cbegin(), spectrum.cend(), std::back_inserter(allY));
131 }
132 auto &y = out->mutableY(0);
133 y = std::vector<double>(1, median(allY));
134 return out;
135}
136
143MatrixWorkspace_sptr initScaleFactorsWorkspace(const size_t nSpectra, const size_t nPoints) {
144 MatrixWorkspace_sptr ws = WorkspaceFactory::Instance().create("Workspace2D", nSpectra, nPoints, nPoints);
146 for (int i = 0; i < static_cast<int>(nSpectra); ++i) {
147 ws->mutableY(static_cast<size_t>(i)) = std::vector<double>(nPoints, 1.);
148 }
149 return ws;
150}
151
152} // namespace
153
154namespace Mantid::Algorithms {
155
156// Register the algorithm into the AlgorithmFactory
157DECLARE_ALGORITHM(Stitch)
158
159//----------------------------------------------------------------------------------------------
160
161
162const std::string Stitch::name() const { return "Stitch"; }
163
165int Stitch::version() const { return 1; }
166
168const std::string Stitch::category() const { return "Transforms\\Merging"; }
169
171const std::string Stitch::summary() const { return "Stitches overlapping spectra from multiple 2D workspaces."; }
172
174std::map<std::string, std::string> Stitch::validateInputs() {
175 std::map<std::string, std::string> issues;
176 const std::vector<std::string> inputs_given = getProperty(INPUT_WORKSPACE_PROPERTY);
177 std::vector<std::string> workspaces;
178 RunCombinationHelper combHelper;
179 try {
180 workspaces = combHelper.unWrapGroups(inputs_given);
181 } catch (const std::exception &e) {
182 issues[INPUT_WORKSPACE_PROPERTY] = std::string(e.what());
183 return issues;
184 }
185 if (workspaces.size() < 2) {
186 issues[INPUT_WORKSPACE_PROPERTY] = "Please provide at least 2 workspaces to stitch.";
187 return issues;
188 }
189 if (getPropertyValue(SCALE_FACTOR_CALCULATION_PROPERTY) == "Manual") {
190 const std::vector<double> factors = getProperty(MANUAL_SCALE_FACTORS_PROPERTY);
191 if (factors.size() != workspaces.size()) {
192 issues[MANUAL_SCALE_FACTORS_PROPERTY] = "If manual scale factors are requested, the number of scale factors must "
193 "match the number of input workspaces.";
194 }
195 }
196 try {
197 const auto first = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(workspaces.front());
198 combHelper.setReferenceProperties(first);
199 } catch (const std::exception &e) {
200 issues[INPUT_WORKSPACE_PROPERTY] =
201 std::string("Please provide MatrixWorkspaces as or groups of those as input: ") + e.what();
202 return issues;
203 }
204 if (!isDefault(REFERENCE_WORKSPACE_PROPERTY)) {
205 const auto referenceName = getPropertyValue(REFERENCE_WORKSPACE_PROPERTY);
206 if (std::find_if(workspaces.cbegin(), workspaces.cend(),
207 [&referenceName](const auto wsName) { return wsName == referenceName; }) == workspaces.cend()) {
208 issues[REFERENCE_WORKSPACE_PROPERTY] = "Reference workspace must be one of the input workspaces";
209 return issues;
210 }
211 }
212 for (const auto &wsName : workspaces) {
213 const auto ws = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(wsName);
214 // check if all the others are compatible with the first one
215 const std::string compatible = combHelper.checkCompatibility(ws, true);
216 if (!compatible.empty()) {
217 issues[INPUT_WORKSPACE_PROPERTY] += "Workspace " + ws->getName() + " is not compatible: " + compatible + "\n";
218 }
219 // check that the workspaces are not ragged
220 if (!ws->isCommonBins()) {
221 issues[INPUT_WORKSPACE_PROPERTY] += "Workspace " + ws->getName() + " is ragged which is not supported.\n";
222 }
223 if (ws->isHistogramData()) {
224 issues[INPUT_WORKSPACE_PROPERTY] +=
225 "Workspace " + ws->getName() + " contains histogram data, only point data are supported.\n";
226 }
227 }
228 return issues;
229}
230
231//----------------------------------------------------------------------------------------------
236 std::make_unique<ArrayProperty<std::string>>(INPUT_WORKSPACE_PROPERTY, std::make_unique<ADSValidator>()),
237 "The names of the input workspaces or groups of those as a list. "
238 "At least two compatible MatrixWorkspaces are required, having one spectrum each. ");
239 declareProperty(REFERENCE_WORKSPACE_PROPERTY, "",
240 "The name of the workspace that will serve as the reference; "
241 "that is, the one that will not be scaled. If left blank, "
242 "stitching will be performed left to right in the order of x-axes ascending, "
243 "no matter the order of workspaces names in the input.");
244 declareProperty(COMBINATION_BEHAVIOUR_PROPERTY, "Interleave",
245 std::make_unique<ListValidator<std::string>>(std::array<std::string, 1>{"Interleave"}));
246 declareProperty(SCALE_FACTOR_CALCULATION_PROPERTY, "MedianOfRatios",
247 std::make_unique<ListValidator<std::string>>(std::array<std::string, 2>{"MedianOfRatios", "Manual"}));
248 declareProperty(std::make_unique<ArrayProperty<double>>(MANUAL_SCALE_FACTORS_PROPERTY),
249 "Manually specified scale factors, must follow the same order of the workspaces in the list.");
250 setPropertySettings(MANUAL_SCALE_FACTORS_PROPERTY,
251 std::make_unique<EnabledWhenProperty>(SCALE_FACTOR_CALCULATION_PROPERTY, IS_EQUAL_TO, "Manual"));
252 declareProperty(TIE_SCALE_FACTORS_PROPERTY, false,
253 "Whether or not to calculate a single scale factor per workspace for all the spectra.");
255 std::make_unique<WorkspaceProperty<MatrixWorkspace>>(OUTPUT_WORKSPACE_PROPERTY, "", Direction::Output),
256 "The output workspace.");
257 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>(OUTPUT_SCALE_FACTORS_PROPERTY, "",
259 "The output workspace containing the applied scale factors.");
260}
261
262//----------------------------------------------------------------------------------------------
266 const auto referenceName = getPropertyValue(REFERENCE_WORKSPACE_PROPERTY);
267 const auto combinationBehaviour = getPropertyValue(COMBINATION_BEHAVIOUR_PROPERTY);
268 const auto scaleFactorCalculation = getPropertyValue(SCALE_FACTOR_CALCULATION_PROPERTY);
269 const auto inputs = RunCombinationHelper::unWrapGroups(getProperty(INPUT_WORKSPACE_PROPERTY));
270 MatrixWorkspace_sptr scaleFactorsWorkspace;
271 cloneWorkspaces(inputs);
272 std::vector<std::string> clones;
273 std::transform(inputs.cbegin(), inputs.cend(), std::back_inserter(clones),
274 [](const auto ws) { return "__cloned_" + ws; });
275 if (scaleFactorCalculation == "Manual") {
276 scaleFactorsWorkspace = initScaleFactorsWorkspace(1, clones.size());
277 scaleManual(clones, getProperty(MANUAL_SCALE_FACTORS_PROPERTY), scaleFactorsWorkspace);
278 } else {
279 scaleWithMedianRatios(clones, referenceName, scaleFactorsWorkspace);
280 }
281 setProperty(OUTPUT_WORKSPACE_PROPERTY, merge(clones));
282 for (const auto &ws : clones) {
284 }
285 if (!isDefault(OUTPUT_SCALE_FACTORS_PROPERTY)) {
286 setProperty(OUTPUT_SCALE_FACTORS_PROPERTY, scaleFactorsWorkspace);
287 }
288}
289
296void Stitch::scaleWithMedianRatios(const std::vector<std::string> &clones, const std::string &referenceName,
297 MatrixWorkspace_sptr &scaleFactorsWorkspace) {
298 std::vector<MatrixWorkspace_sptr> workspaces;
299 std::transform(clones.cbegin(), clones.cend(), std::back_inserter(workspaces),
300 [](const auto ws) { return AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(ws); });
301 const size_t nSpectrumInScaleFactors =
302 isDefault(TIE_SCALE_FACTORS_PROPERTY) ? workspaces[0]->getNumberHistograms() : 1;
303 scaleFactorsWorkspace = initScaleFactorsWorkspace(nSpectrumInScaleFactors, workspaces.size());
304 // sort internally by the x-extent interval ascending, but the scale factors will be stored in the original order
305 std::sort(workspaces.begin(), workspaces.end(), compareInterval);
306 auto progress = std::make_unique<Progress>(this, 0.0, 1.0, workspaces.size());
307 const size_t referenceIndex = getReferenceIndex(workspaces, referenceName);
308 size_t leftIterator = referenceIndex, rightIterator = referenceIndex;
309 // we start from the reference index and iterate to the left, then to the right
310 // note that these loops are delibarately serial, as the subsequent scale factors need to be computed wrt already
311 // scaled previous workspaces
312 while (leftIterator > 0) {
313 scale(workspaces[leftIterator], workspaces[leftIterator - 1], scaleFactorsWorkspace, clones);
314 progress->report();
315 --leftIterator;
316 }
317 while (rightIterator < workspaces.size() - 1) {
318 scale(workspaces[rightIterator], workspaces[rightIterator + 1], scaleFactorsWorkspace, clones);
319 progress->report();
320 ++rightIterator;
321 }
322}
323
330size_t Stitch::getReferenceIndex(const std::vector<MatrixWorkspace_sptr> &workspaces,
331 const std::string &referenceName) {
332 size_t referenceIndex = 0;
333 if (!isDefault(REFERENCE_WORKSPACE_PROPERTY)) {
334 const auto ref = std::find_if(workspaces.cbegin(), workspaces.cend(), [&referenceName](const auto ws) {
335 return ws->getName() == "__cloned_" + referenceName;
336 });
337 referenceIndex = std::distance(workspaces.cbegin(), ref);
338 }
339 return referenceIndex;
340}
341
347void Stitch::cloneWorkspaces(const std::vector<std::string> &inputs) {
348 auto cloner = createChildAlgorithm("CloneWorkspace");
349 cloner->setAlwaysStoreInADS(true);
350 for (const auto &ws : inputs) {
351 cloner->setProperty("InputWorkspace", ws);
352 cloner->setProperty("OutputWorkspace", "__cloned_" + ws);
353 cloner->execute();
354 }
355}
356
363MatrixWorkspace_sptr Stitch::merge(const std::vector<std::string> &inputs) {
364 // interleave option is equivalent to concatenation followed by sort X axis
365 auto joiner = createChildAlgorithm("ConjoinXRuns");
366 joiner->setProperty("InputWorkspaces", inputs);
367 joiner->execute();
368 Workspace_sptr output = joiner->getProperty("OutputWorkspace");
369 MatrixWorkspace_sptr joined = std::dynamic_pointer_cast<MatrixWorkspace>(output);
370
371 auto sorter = createChildAlgorithm("SortXAxis");
372 sorter->setProperty("InputWorkspace", joined);
373 sorter->execute();
374 MatrixWorkspace_sptr sorted = sorter->getProperty("OutputWorkspace");
375 return sorted;
376}
377
387void Stitch::scale(const MatrixWorkspace_sptr &wsToMatch, const MatrixWorkspace_sptr &wsToScale,
388 Mantid::API::MatrixWorkspace_sptr scaleFactorsWorkspace, const std::vector<std::string> &inputs) {
389 const auto overlap = getOverlap(wsToMatch, wsToScale);
390 auto cropper = createChildAlgorithm("CropWorkspaceRagged");
391 cropper->setProperty("XMin", std::vector<double>({overlap.first}));
392 cropper->setProperty("XMax", std::vector<double>({overlap.second}));
393
394 cropper->setProperty("InputWorkspace", wsToMatch);
395 cropper->execute();
396 MatrixWorkspace_sptr croppedToMatch = cropper->getProperty("OutputWorkspace");
397 cropper->setProperty("InputWorkspace", wsToScale);
398 cropper->execute();
399 MatrixWorkspace_sptr croppedToScale = cropper->getProperty("OutputWorkspace");
400
401 MatrixWorkspace_sptr rebinnedToScale;
402 if (croppedToMatch->blocksize() > 1) {
403 auto interpolator = createChildAlgorithm("SplineInterpolation");
404 interpolator->setProperty("WorkspaceToMatch", croppedToMatch);
405 interpolator->setProperty("WorkspaceToInterpolate", croppedToScale);
406 interpolator->setProperty("Linear2Points", true);
407 interpolator->execute();
408 rebinnedToScale = interpolator->getProperty("OutputWorkspace");
409 } else {
410 if (croppedToMatch->readX(0) != croppedToScale->readX(0)) {
411 throw std::runtime_error(
412 "Unable to make the ratio; only one overlapping point is found and it is at different x");
413 } else {
414 rebinnedToScale = croppedToScale;
415 }
416 }
417
418 auto divider = createChildAlgorithm("Divide");
419 divider->setProperty("LHSWorkspace", rebinnedToScale);
420 divider->setProperty("RHSWorkspace", croppedToMatch);
421 divider->execute();
422 MatrixWorkspace_sptr ratio = divider->getProperty("OutputWorkspace");
423 MatrixWorkspace_sptr median =
424 getProperty("TieScaleFactors") ? medianWorkspaceGlobal(ratio) : medianWorkspaceLocal(ratio);
425
426 auto scaler = createChildAlgorithm("Divide");
427 scaler->setAlwaysStoreInADS(true);
428 scaler->setProperty("LHSWorkspace", wsToScale);
429 scaler->setProperty("RHSWorkspace", median);
430 scaler->setPropertyValue("OutputWorkspace", wsToScale->getName());
431 scaler->execute();
432
433 recordScaleFactor(scaleFactorsWorkspace, median, wsToScale, inputs);
434}
435
445 const Mantid::API::MatrixWorkspace_sptr &medianWorkspace,
446 const Mantid::API::MatrixWorkspace_sptr &scaledWorkspace,
447 const std::vector<std::string> &inputs) {
448 const auto it = std::find(inputs.cbegin(), inputs.cend(), scaledWorkspace->getName());
449 const size_t index = std::distance(inputs.cbegin(), it);
450 PARALLEL_FOR_IF(threadSafe(*scaleFactorWorkspace))
451 for (int i = 0; i < static_cast<int>(scaleFactorWorkspace->getNumberHistograms()); ++i) {
452 scaleFactorWorkspace->mutableY(i)[index] = 1. / medianWorkspace->readY(i)[0];
453 }
454}
455
464void Stitch::scaleManual(const std::vector<std::string> &inputs, const std::vector<double> &scaleFactors,
465 const MatrixWorkspace_sptr &scaleFactorsWorkspace) {
466 auto &outputFactors = scaleFactorsWorkspace->mutableY(0);
467 auto progress = std::make_unique<Progress>(this, 0.0, 1.0, inputs.size());
468 PARALLEL_FOR_IF(threadSafe(*scaleFactorsWorkspace))
469 for (int i = 0; i < static_cast<int>(inputs.size()); ++i) {
470 outputFactors[i] = scaleFactors[i];
471 auto scaler = createChildAlgorithm("Scale");
472 scaler->setAlwaysStoreInADS(true);
473 scaler->setPropertyValue("InputWorkspace", inputs[i]);
474 scaler->setProperty("Factor", scaleFactors[i]);
475 scaler->setPropertyValue("OutputWorkspace", inputs[i]);
476 scaler->execute();
477 progress->report();
478 }
479}
480
481} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
int nSpectra
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
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
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
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.
Definition: Algorithm.cpp:842
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Definition: Algorithm.cpp:231
bool isDefault(const std::string &name) const
Definition: Algorithm.cpp:2084
Base MatrixWorkspace Abstract Class.
const MantidVec & readX(std::size_t const index) const
Deprecated, use x() instead.
A property class for workspaces.
static std::vector< std::string > unWrapGroups(const std::vector< std::string > &)
Flattens the list of group workspaces (if any) into list of workspaces.
void setReferenceProperties(const API::MatrixWorkspace_sptr &)
Sets the properties of the reference (usually first) workspace, to later check the compatibility of t...
std::string checkCompatibility(const API::MatrixWorkspace_sptr &, bool checkNumberHistograms=false)
Compares the properties of the input workspace with the reference.
Stitches overlapping spectra from multiple 2D workspaces.
Definition: Stitch.h:17
void cloneWorkspaces(const std::vector< std::string > &inputs)
Clones all the input workspaces so that they can be scaled in-place without altering the inputs Clone...
Definition: Stitch.cpp:347
void scaleWithMedianRatios(const std::vector< std::string > &clones, const std::string &referenceName, API::MatrixWorkspace_sptr &scaleFactorsWorkspace)
Scales workspaces by medians of point-wise ratios in the overlap regions.
Definition: Stitch.cpp:296
void init() override
Initialize the algorithm's properties.
Definition: Stitch.cpp:234
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
Definition: Stitch.cpp:171
API::MatrixWorkspace_sptr merge(const std::vector< std::string > &workspaces)
Combines the scaled workspaces together by interleaving their data This is equivalent to concatenatio...
Definition: Stitch.cpp:363
void scale(const API::MatrixWorkspace_sptr &wsToMatch, const API::MatrixWorkspace_sptr &wsToScale, API::MatrixWorkspace_sptr scaleFactorsWorkspace, const std::vector< std::string > &inputs)
Scales one workspace to match the scale of the other The scale factors are calculated as medians of p...
Definition: Stitch.cpp:387
int version() const override
Algorithm's version for identification.
Definition: Stitch.cpp:165
std::map< std::string, std::string > validateInputs() override
Validate the input workspaces for compatibility.
Definition: Stitch.cpp:174
void exec() override
Execute the algorithm.
Definition: Stitch.cpp:265
void recordScaleFactor(const API::MatrixWorkspace_sptr &scaleFactorWorkspace, const API::MatrixWorkspace_sptr &medianWorkspace, const API::MatrixWorkspace_sptr &scaledWorkspace, const std::vector< std::string > &inputs)
Stores the multiplicative scale factors into a workspace Note that the scale factors are stored in th...
Definition: Stitch.cpp:444
size_t getReferenceIndex(const std::vector< API::MatrixWorkspace_sptr > &workspaces, const std::string &referenceName)
Returns the index of the reference workspace in the sorted workspace list.
Definition: Stitch.cpp:330
void scaleManual(const std::vector< std::string > &inputs, const std::vector< double > &scaleFactors, const API::MatrixWorkspace_sptr &scaleFactorsWorkspace)
Performs scaling with manual scale factors, which are treated as global, i.e.
Definition: Stitch.cpp:464
const std::string category() const override
Algorithm's category for identification.
Definition: Stitch.cpp:168
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void setPropertySettings(const std::string &name, std::unique_ptr< IPropertySettings > settings)
ListValidator is a validator that requires the value of a property to be one of a defined list of pos...
Definition: ListValidator.h:29
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
Definition: Workspace_fwd.h:20
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
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.
Definition: MultiThreaded.h:22
STL namespace.
@ Output
An output workspace.
Definition: Property.h:54