Mantid
Loading...
Searching...
No Matches
WorkspaceCreation.h
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2016 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#pragma once
8
9#include "MantidDataObjects/DllConfig.h"
10#include "MantidHistogramData/Histogram.h"
11
12#include <memory>
13#include <type_traits>
14
15namespace Mantid {
16namespace Indexing {
17class IndexInfo;
18}
19namespace Geometry {
20class Instrument;
21}
22namespace API {
23class MatrixWorkspace;
24class HistoWorkspace;
25} // namespace API
26namespace DataObjects {
27class EventWorkspace;
28class Workspace2D;
29
92namespace detail {
93MANTID_DATAOBJECTS_DLL HistogramData::Histogram stripData(HistogramData::Histogram histogram);
94
95template <class T> std::unique_ptr<T> createHelper() { return std::make_unique<T>(); }
96
97template <class T> std::unique_ptr<T> createConcreteHelper() { return std::make_unique<T>(); }
98
99template <> MANTID_DATAOBJECTS_DLL std::unique_ptr<API::HistoWorkspace> createHelper();
100
101// Dummy specialization, should never be called, must exist for compilation.
102template <> MANTID_DATAOBJECTS_DLL std::unique_ptr<EventWorkspace> createHelper();
103// Dummy specialization, should never be called, must exist for compilation.
104template <> MANTID_DATAOBJECTS_DLL std::unique_ptr<API::MatrixWorkspace> createHelper();
105
106// Dummy specialization, should never be called, must exist for compilation.
107template <> MANTID_DATAOBJECTS_DLL std::unique_ptr<API::MatrixWorkspace> createConcreteHelper();
108// Dummy specialization, should never be called, must exist for compilation.
109template <> MANTID_DATAOBJECTS_DLL std::unique_ptr<API::HistoWorkspace> createConcreteHelper();
110
111template <class HistArg> void fixDistributionFlag(API::MatrixWorkspace &, const HistArg &) {}
112
113template <>
114MANTID_DATAOBJECTS_DLL void fixDistributionFlag(API::MatrixWorkspace &workspace,
115 const HistogramData::Histogram &histArg);
116
117template <class T> struct IsIndexInfo { using type = std::false_type; };
118template <> struct IsIndexInfo<Indexing::IndexInfo> { using type = std::true_type; };
119template <class UseIndexInfo>
121} // namespace detail
122
126template <class T, class P, class IndexArg, class HistArg,
127 class = typename std::enable_if<std::is_base_of<API::MatrixWorkspace, P>::value>::type>
128std::unique_ptr<T> create(const P &parent, const IndexArg &indexArg, const HistArg &histArg) {
129 // Figure out (dynamic) target type:
130 // - Type is same as parent if T is base of parent
131 // - If T is not base of parent, conversion may occur. Currently only
132 // supported for EventWorkspace
133 std::unique_ptr<T> ws;
134 if (std::is_base_of<API::HistoWorkspace, T>::value && parent.id() == "EventWorkspace") {
135 // Drop events, create Workspace2D or T whichever is more derived.
136 ws = detail::createHelper<T>();
137 } else {
138 try {
139 // If parent is more derived than T: create type(parent)
140 ws = dynamic_cast<const T &>(parent).cloneEmpty();
141 } catch (std::bad_cast &) {
142 // If T is more derived than parent: create T
143 ws = detail::createConcreteHelper<T>();
144 }
145 }
146
147 // The instrument is also copied by initializeFromParent, but if indexArg is
148 // IndexInfo and contains non-empty spectrum definitions the initialize call
149 // will fail due to invalid indices in the spectrum definitions. Therefore, we
150 // copy the instrument first. This should be cleaned up once we figure out the
151 // future of WorkspaceFactory.
152 ws->setInstrument(parent.getInstrument());
153 ws->initialize(indexArg, HistogramData::Histogram(histArg));
154 detail::initializeFromParent<typename detail::IsIndexInfo<IndexArg>::type>(parent, *ws);
155 // initializeFromParent sets the distribution flag to the same value as
156 // parent. In case histArg is an actual Histogram that is not the correct
157 // behavior so we have to set it back to the value given by histArg.
158 detail::fixDistributionFlag(*ws, histArg);
159 return ws;
160}
161
162template <class T, class IndexArg, class HistArg,
163 typename std::enable_if<!std::is_base_of<API::MatrixWorkspace, IndexArg>::value>::type * = nullptr>
164std::unique_ptr<T> create(const IndexArg &indexArg, const HistArg &histArg) {
165 auto ws = std::make_unique<T>();
166 ws->initialize(indexArg, HistogramData::Histogram(histArg));
167 return ws;
168}
169
170template <class T, class IndexArg, class HistArg,
171 typename std::enable_if<!std::is_base_of<API::MatrixWorkspace, IndexArg>::value>::type * = nullptr>
172std::unique_ptr<T> create(const std::shared_ptr<const Geometry::Instrument> &instrument, const IndexArg &indexArg,
173 const HistArg &histArg) {
174 auto ws = std::make_unique<T>();
175 ws->setInstrument(std::move(instrument));
176 ws->initialize(indexArg, HistogramData::Histogram(histArg));
177 return ws;
178}
179
180template <class T, class P, typename std::enable_if<std::is_base_of<API::MatrixWorkspace, P>::value>::type * = nullptr>
181std::unique_ptr<T> create(const P &parent) {
182 const auto numHistograms = parent.getNumberHistograms();
183 auto ws = create<T>(parent, numHistograms, detail::stripData(parent.histogram(0)));
184 for (size_t i = 0; i < numHistograms; ++i) {
185 ws->setSharedX(i, parent.sharedX(i));
186 }
187 return ws;
188}
189
190// Templating with HistArg clashes with the IndexArg template above. Could be
191// fixed with many enable_if cases, but for now we simply provide 3 variants
192// (Histogram, BinEdges, Points) by hand.
193template <class T, class P, typename std::enable_if<std::is_base_of<API::MatrixWorkspace, P>::value>::type * = nullptr>
194std::unique_ptr<T> create(const P &parent, const HistogramData::Histogram &histogram) {
195 return create<T>(parent, parent.getNumberHistograms(), histogram);
196}
197
198template <class T, class P, typename std::enable_if<std::is_base_of<API::MatrixWorkspace, P>::value>::type * = nullptr>
199std::unique_ptr<T> create(const P &parent, const HistogramData::BinEdges &binEdges) {
200 return create<T>(parent, parent.getNumberHistograms(), binEdges);
201}
202
203template <class T, class P, typename std::enable_if<std::is_base_of<API::MatrixWorkspace, P>::value>::type * = nullptr>
204std::unique_ptr<T> create(const P &parent, const HistogramData::Points &points) {
205 return create<T>(parent, parent.getNumberHistograms(), points);
206}
207
208} // namespace DataObjects
209} // namespace Mantid
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
Base MatrixWorkspace Abstract Class.
MANTID_DATAOBJECTS_DLL HistogramData::Histogram stripData(HistogramData::Histogram histogram)
void initializeFromParent(const API::MatrixWorkspace &parent, API::MatrixWorkspace &workspace)
Initialize a MatrixWorkspace from its parent including instrument, unit, number of spectra and Run.
std::unique_ptr< T > createHelper()
std::unique_ptr< T > createConcreteHelper()
void fixDistributionFlag(API::MatrixWorkspace &, const HistArg &)
std::unique_ptr< T > create(const P &parent, const IndexArg &indexArg, const HistArg &histArg)
This is the create() method that all the other create() methods call.
Helper class which provides the Collimation Length for SANS instruments.