Mantid
Loading...
Searching...
No Matches
ScanningWorkspaceBuilder.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 +
8
14#include "MantidHistogramData/BinEdges.h"
15#include "MantidHistogramData/Histogram.h"
16#include "MantidHistogramData/LinearGenerator.h"
17#include "MantidHistogramData/Points.h"
18#include "MantidTypes/SpectrumDefinition.h"
19
20using namespace Mantid::API;
21using namespace Mantid::HistogramData;
22using namespace Mantid::Indexing;
23
24namespace Mantid::DataObjects {
25
35ScanningWorkspaceBuilder::ScanningWorkspaceBuilder(const std::shared_ptr<const Geometry::Instrument> &instrument,
36 const size_t nTimeIndexes, const size_t nBins,
37 const bool isPointData)
38 : m_nDetectors(instrument->getNumberDetectors()), m_nTimeIndexes(nTimeIndexes), m_nBins(nBins),
39 m_instrument(instrument), m_histogram(BinEdges(nBins + 1, LinearGenerator(1.0, 1.0)), Counts(nBins, 0.0)),
40 m_indexingType(IndexingType::Default) {
41 if (isPointData)
42 m_histogram = HistogramData::Histogram(Points(nBins), Counts(nBins, 0.0));
43}
44
52void ScanningWorkspaceBuilder::setHistogram(HistogramData::Histogram histogram) {
53 if (histogram.size() != m_nBins)
54 throw std::logic_error("Histogram supplied does not have the correct size.");
55
56 m_histogram = std::move(histogram);
57}
58
66 std::vector<std::pair<Types::Core::DateAndTime, Types::Core::DateAndTime>> timeRanges) {
67 verifyTimeIndexSize(timeRanges.size(), "start time, end time pairs");
68 m_timeRanges = std::move(timeRanges);
69}
70
78void ScanningWorkspaceBuilder::setTimeRanges(const Types::Core::DateAndTime &startTime,
79 const std::vector<double> &durations) {
80 verifyTimeIndexSize(durations.size(), "time durations");
81
82 std::vector<std::pair<Types::Core::DateAndTime, Types::Core::DateAndTime>> timeRanges = {
83 std::pair<Types::Core::DateAndTime, Types::Core::DateAndTime>(startTime, startTime + durations[0])};
84
85 for (size_t i = 1; i < m_nTimeIndexes; ++i) {
86 const auto newStartTime = timeRanges[i - 1].second;
87 const auto endTime = newStartTime + durations[i];
88 timeRanges.emplace_back(std::pair<Types::Core::DateAndTime, Types::Core::DateAndTime>(newStartTime, endTime));
89 }
90
91 setTimeRanges(std::move(timeRanges));
92}
93
101void ScanningWorkspaceBuilder::setPositions(std::vector<std::vector<Kernel::V3D>> positions) {
102
103 if (!m_positions.empty() || !m_instrumentAngles.empty())
104 throw std::logic_error("Can not set positions, as positions or instrument "
105 "angles have already been set.");
106
107 for (const auto &vector : positions) {
108 verifyTimeIndexSize(vector.size(), "positions");
109 }
110 verifyDetectorSize(positions.size(), "positions");
111
112 m_positions = std::move(positions);
113}
114
122void ScanningWorkspaceBuilder::setRotations(std::vector<std::vector<Kernel::Quat>> rotations) {
123
124 if (!m_rotations.empty() || !m_instrumentAngles.empty())
125 throw std::logic_error("Can not set rotations, as rotations or instrument "
126 "angles have already been set.");
127
128 for (const auto &vector : rotations) {
129 verifyTimeIndexSize(vector.size(), "rotations");
130 }
131 verifyDetectorSize(rotations.size(), "rotations");
132
133 m_rotations = std::move(rotations);
134}
135
152void ScanningWorkspaceBuilder::setRelativeRotationsForScans(const std::vector<double> &relativeRotations,
153 const Kernel::V3D &rotationPosition,
154 const Kernel::V3D &rotationAxis) {
155
156 if (!m_positions.empty() || !m_rotations.empty())
157 throw std::logic_error("Can not set instrument angles, as positions and/or "
158 "rotations have already been set.");
159
160 verifyTimeIndexSize(relativeRotations.size(), "instrument angles");
161 m_instrumentAngles = std::move(relativeRotations);
162 m_rotationPosition = rotationPosition;
163 m_rotationAxis = rotationAxis;
164}
165
173 throw std::logic_error("Indexing type has been set already.");
174
175 m_indexingType = indexingType;
176}
177
185
186 auto outputWorkspace = create<Workspace2D>(m_instrument, m_nDetectors * m_nTimeIndexes, m_histogram);
187
188 auto &outputComponentInfo = outputWorkspace->mutableComponentInfo();
189 outputComponentInfo.setScanInterval(m_timeRanges[0]);
190
191 buildOutputComponentInfo(outputComponentInfo);
192
193 auto &outputDetectorInfo = outputWorkspace->mutableDetectorInfo();
194
195 if (!m_positions.empty())
196 buildPositions(outputDetectorInfo);
197
198 if (!m_rotations.empty())
199 buildRotations(outputDetectorInfo);
200
201 if (!m_instrumentAngles.empty())
202 buildRelativeRotationsForScans(outputDetectorInfo);
203
204 switch (m_indexingType) {
206 outputWorkspace->setIndexInfo(Indexing::IndexInfo(m_nDetectors * m_nTimeIndexes));
207 break;
209 createTimeOrientedIndexInfo(*outputWorkspace);
210 break;
212 createDetectorOrientedIndexInfo(*outputWorkspace);
213 break;
214 }
215
216 return std::shared_ptr<MatrixWorkspace>(std::move(outputWorkspace));
217}
218
220 auto mergeWorkspace = create<Workspace2D>(m_instrument, m_nDetectors, m_histogram.binEdges());
221 for (size_t i = 1; i < m_nTimeIndexes; ++i) {
222 auto &mergeComponentInfo = mergeWorkspace->mutableComponentInfo();
223 mergeComponentInfo.setScanInterval(m_timeRanges[i]);
224 outputComponentInfo.merge(mergeComponentInfo);
225 }
226}
227
229 for (size_t i = 0; i < m_nDetectors; ++i) {
230 for (size_t j = 0; j < m_nTimeIndexes; ++j) {
231 outputDetectorInfo.setRotation({i, j}, m_rotations[i][j]);
232 }
233 }
234}
235
237 for (size_t i = 0; i < m_nDetectors; ++i) {
238 for (size_t j = 0; j < m_nTimeIndexes; ++j) {
239 outputDetectorInfo.setPosition({i, j}, m_positions[i][j]);
240 }
241 }
242}
243
245 for (size_t i = 0; i < outputDetectorInfo.size(); ++i) {
246 for (size_t j = 0; j < outputDetectorInfo.scanCount(); ++j) {
247 if (outputDetectorInfo.isMonitor({i, j}))
248 continue;
249 auto position = outputDetectorInfo.position({i, j});
254 outputDetectorInfo.setPosition({i, j}, position);
255 const auto &oldRotation = outputDetectorInfo.rotation({i, j});
256 outputDetectorInfo.setRotation({i, j}, rotation * oldRotation);
257 }
258 }
259}
260
262 auto indexInfo = ws.indexInfo();
263 auto spectrumDefinitions = std::vector<SpectrumDefinition>(m_nDetectors * m_nTimeIndexes);
264
265 for (size_t detIndex = 0; detIndex < m_nDetectors; ++detIndex) {
266 for (size_t timeIndex = 0; timeIndex < m_nTimeIndexes; ++timeIndex) {
267 spectrumDefinitions[detIndex * m_nTimeIndexes + timeIndex].add(detIndex, timeIndex);
268 }
269 }
270
271 indexInfo.setSpectrumDefinitions(spectrumDefinitions);
272 ws.setIndexInfo(indexInfo);
273}
274
276 auto indexInfo = ws.indexInfo();
277 auto spectrumDefinitions = std::vector<SpectrumDefinition>(m_nDetectors * m_nTimeIndexes);
278
279 for (size_t timeIndex = 0; timeIndex < m_nTimeIndexes; ++timeIndex) {
280 for (size_t detIndex = 0; detIndex < m_nDetectors; ++detIndex) {
281 spectrumDefinitions[timeIndex * m_nDetectors + detIndex].add(detIndex, timeIndex);
282 }
283 }
284
285 indexInfo.setSpectrumDefinitions(spectrumDefinitions);
286 ws.setIndexInfo(indexInfo);
287}
288
289void ScanningWorkspaceBuilder::verifyTimeIndexSize(const size_t timeIndexSize, const std::string &description) const {
290 if (timeIndexSize != m_nTimeIndexes) {
291 throw std::logic_error("Number of " + description + " supplied does not match the number of time indexes.");
292 }
293}
294
295void ScanningWorkspaceBuilder::verifyDetectorSize(const size_t detectorSize, const std::string &description) const {
296 if (detectorSize != m_nDetectors) {
297 throw std::logic_error("Number of " + description + " supplied does not match the number of detectors.");
298 }
299}
300
302 if (m_timeRanges.empty())
303 throw std::logic_error("Can not build workspace - time ranges have not "
304 "been set. Please call setTimeRanges() before "
305 "building.");
306}
307
308} // namespace Mantid::DataObjects
double position
Definition: GetAllEi.cpp:154
Mantid::Kernel::Quat(ComponentInfo::* rotation)(const size_t) const
Base MatrixWorkspace Abstract Class.
const Indexing::IndexInfo & indexInfo() const
Returns a const reference to the IndexInfo object of the workspace.
void setIndexInfo(const Indexing::IndexInfo &indexInfo)
Sets the IndexInfo object of the workspace.
API::MatrixWorkspace_sptr buildWorkspace() const
Verify everything has been set that is required and return the workspace.
std::vector< std::pair< Types::Core::DateAndTime, Types::Core::DateAndTime > > m_timeRanges
void setTimeRanges(std::vector< std::pair< Types::Core::DateAndTime, Types::Core::DateAndTime > > timeRanges)
Set time ranges from a vector of start time, end time pairs.
void verifyDetectorSize(const size_t detectorSize, const std::string &description) const
void createDetectorOrientedIndexInfo(API::MatrixWorkspace &ws) const
void setHistogram(HistogramData::Histogram histogram)
Set a histogram to be used for all the workspace spectra.
void setRelativeRotationsForScans(const std::vector< double > &relativeRotations, const Kernel::V3D &rotationPosition, const Kernel::V3D &rotationAxis)
Set a vector of rotations corresponding to each time index.
void buildOutputComponentInfo(Geometry::ComponentInfo &outputComponentInfo) const
std::shared_ptr< const Geometry::Instrument > m_instrument
void verifyTimeIndexSize(const size_t timeIndexSize, const std::string &description) const
void buildRelativeRotationsForScans(Geometry::DetectorInfo &outputDetectorInfo) const
void buildPositions(Geometry::DetectorInfo &outputDetectorInfo) const
void setIndexingType(const IndexingType indexingType)
Set the indexing type, either to time or detector oriented indexing.
void buildRotations(Geometry::DetectorInfo &outputDetectorInfo) const
std::vector< std::vector< Kernel::V3D > > m_positions
void createTimeOrientedIndexInfo(API::MatrixWorkspace &ws) const
ScanningWorkspaceBuilder(const std::shared_ptr< const Geometry::Instrument > &instrument, const size_t nTimeIndexes, const size_t nBins, const bool isPointData=false)
Create the scanning workspace builder.
std::vector< std::vector< Kernel::Quat > > m_rotations
void setPositions(std::vector< std::vector< Kernel::V3D > > positions)
Supply a vector of vectors which contain positions.
void setRotations(std::vector< std::vector< Kernel::Quat > > rotations)
Supply a vector of vectors which contain rotations.
ComponentInfo : Provides a component centric view on to the instrument.
Definition: ComponentInfo.h:40
void merge(const ComponentInfo &other)
Geometry::DetectorInfo is an intermediate step towards a DetectorInfo that is part of Instrument-2....
Definition: DetectorInfo.h:49
size_t scanCount() const
Returns the scan count of the detector with given detector index.
void setPosition(const size_t index, const Kernel::V3D &position)
Set the absolute position of the detector with given index. Not thread safe.
Kernel::Quat rotation(const size_t index) const
Returns the rotation of the detector with given index.
Kernel::V3D position(const size_t index) const
Returns the position of the detector with given index.
void setRotation(const size_t index, const Kernel::Quat &rotation)
Set the absolute rotation of the detector with given index. Not thread safe.
size_t size() const
Returns the size of the DetectorInfo, i.e., the number of detectors in the instrument.
bool isMonitor(const size_t index) const
Returns true if the detector is a monitor.
Class for quaternions.
Definition: Quat.h:39
void rotate(V3D &) const
Rotate a vector.
Definition: Quat.cpp:397
Class for 3D vectors.
Definition: V3D.h:34
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class