Mantid
Loading...
Searching...
No Matches
ConvToMDEventsWSIndexing.h
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 +
7#pragma once
8
11#include <mutex>
12#include <queue>
13#include <thread>
14
15namespace Mantid {
16// Forward declarations
17namespace API {
18class Progress;
19}
20namespace MDAlgorithms {
31
32 size_t initialize(const MDWSDescription &WSD, std::shared_ptr<MDEventWSWrapper> inWSWrapper,
33 bool ignoreZeros) override;
34 // Interface function
35 void appendEventsFromInputWS(API::Progress *pProgress, const API::BoxController_sptr &bc) override;
36
37public:
38 template <typename T> static bool isSplitValid(const std::vector<T> &split_into) {
39 bool validSplitInfo = !split_into.empty();
40 if (validSplitInfo) {
41 const T &n = split_into[0];
42 validSplitInfo &= (n > 1 && ((n & (n - 1)) == 0));
43 if (validSplitInfo)
44 validSplitInfo &= all_of(split_into.begin(), split_into.end(), [&n](T i) { return i == n; });
45 }
46 return validSplitInfo;
47 }
48
49private:
50 // Returns number of workers for parallel parts
51 int numWorkers() { return this->m_NumThreads < 0 ? PARALLEL_GET_MAX_THREADS : std::max(1, this->m_NumThreads); }
52
53 template <size_t ND> MD_EVENT_TYPE mdEventType();
54
55 // Wrapper to have the proper functions, for Nd in range 2 to maxDim
56 template <size_t maxDim> void appendEventsFromInputWS(API::Progress *pProgress, const API::BoxController_sptr &bc);
57
58 // Wrapper for ToF events of different types, number of dims, MD event type
59 template <typename EventType, size_t ND, template <size_t> class MDEventType>
60 void appendEvents(API::Progress *pProgress, const API::BoxController_sptr &bc);
61
62 // Specialization for ToF events of different types
63 template <size_t ND, template <size_t> class MDEventType>
64 void appendEvents(API::Progress *pProgress, const API::BoxController_sptr &bc);
65
66 // Specilization for MD event types
67 template <size_t ND> void appendEvents(API::Progress *pProgress, const API::BoxController_sptr &bc);
68
69 template <typename EventType, size_t ND, template <size_t> class MDEventType>
70 std::vector<MDEventType<ND>> convertEvents();
71
72 template <size_t ND, template <size_t> class MDEventType> struct MDEventMaker {
73 static MDEventType<ND> makeMDEvent(const double &sig, const double &err, const uint16_t &expInfoIndex,
74 const uint16_t &goniometer_index, const uint32_t &det_id, coord_t *coord) {
75 return MDEventType<ND>(sig, err, expInfoIndex, goniometer_index, det_id, coord);
76 }
77 };
78};
79
80/*-------------------------------definitions-------------------------------------*/
81
82template <typename EventType, size_t ND, template <size_t> class MDEventType>
83std::vector<MDEventType<ND>> ConvToMDEventsWSIndexing::convertEvents() {
84 std::vector<MDEventType<ND>> mdEvents;
85 mdEvents.reserve(m_EventWS->getNumberEvents());
86
87 const auto &pws = m_OutWSWrapper->pWorkspace();
88 std::array<std::pair<coord_t, coord_t>, ND> bounds;
89 for (size_t ax = 0; ax < ND; ++ax) {
90 bounds[ax] = std::make_pair(pws->getDimension(ax)->getMinimum(), pws->getDimension(ax)->getMaximum());
91 }
92
93 std::vector<MDTransf_sptr> qConverters;
94 for (int i = 0; i < numWorkers(); ++i)
95 qConverters.emplace_back(m_QConverter->clone());
96#pragma omp parallel for num_threads(numWorkers())
97 for (int workspaceIndex = 0; workspaceIndex < static_cast<int>(m_NSpectra); ++workspaceIndex) {
98 const Mantid::DataObjects::EventList &el = m_EventWS->getSpectrum(workspaceIndex);
99
100 size_t numEvents = el.getNumberEvents();
101 if (numEvents == 0)
102 continue;
103
104 // create local unit conversion class
106 // create local QConverter
107 MDTransf_sptr localQConverter = qConverters[PARALLEL_THREAD_NUMBER];
108 int32_t detID = m_detID[workspaceIndex];
109 uint16_t expInfoIndexLoc = m_ExpInfoIndex;
110 uint16_t goniometerIndex(0); // default value
111
112 std::vector<coord_t> locCoord(ND);
113 // set up unit conversion and calculate up all coordinates, which depend on
114 // spectra index only
115 if (!localQConverter->calcYDepCoordinates(locCoord, workspaceIndex))
116 continue; // skip if any y outsize of the range of interest;
117 localUnitConv.updateConversion(workspaceIndex);
118 // This little dance makes the getting vector of events more general (since
119 // you can't overload by return type).
120 typename std::vector<EventType> const *events_ptr;
121 getEventsFrom(el, events_ptr);
122 const typename std::vector<EventType> &events = *events_ptr;
123 std::vector<MDEventType<ND>> mdEventsForSpectrum;
124 // Iterators to start/end
125 for (const auto &event : events) {
126 double val = localUnitConv.convertUnits(event.tof());
127 double signal = event.weight();
128 double errorSq = event.errorSquared();
129
130 if (!localQConverter->calcMatrixCoord(val, locCoord, signal, errorSq))
131 continue; // skip ND outside the range
132
133 mdEventsForSpectrum.emplace_back(MDEventMaker<ND, MDEventType>::makeMDEvent(
134 signal, errorSq, expInfoIndexLoc, goniometerIndex, detID, &locCoord[0]));
135
136 // Filter events before adding to the ndEvents vector to add in workspace
137 // The bounds of the resulting WS have to be already defined
138 bool isInOutWSBox = true;
139 for (size_t ax = 0; ax < ND; ++ax) {
140 const coord_t &coord{mdEventsForSpectrum.back().getCenter(ax)};
141 if (coord < bounds[ax].first || coord > bounds[ax].second)
142 isInOutWSBox = false;
143 }
144
145 if (!isInOutWSBox)
146 mdEventsForSpectrum.pop_back();
147 }
148
149#pragma omp critical
150 {
151 /* Add to event list */
152 mdEvents.insert(mdEvents.cend(), mdEventsForSpectrum.begin(), mdEventsForSpectrum.end());
153 }
154 }
155 return mdEvents;
156}
157
158template <typename EventType, size_t ND, template <size_t> class MDEventType>
160 bc->clearBoxesCounter(1);
161 bc->clearGridBoxesCounter(0);
162 pProgress->resetNumSteps(2, 0, 1);
163
164 std::vector<MDEventType<ND>> mdEvents = convertEvents<EventType, ND, MDEventType>();
165
167 const auto &pws = m_OutWSWrapper->pWorkspace();
168 for (size_t ax = 0; ax < ND; ++ax) {
169 space(ax, 0) = pws->getDimension(ax)->getMinimum();
170 space(ax, 1) = pws->getDimension(ax)->getMaximum();
171 }
172
173 pProgress->report(0);
174
175 auto nThreads = numWorkers();
177 EventDistributor distributor(nThreads, mdEvents.size() / nThreads / 10, bc, space);
178
179 auto rootAndErr = distributor.distribute(mdEvents);
180 m_OutWSWrapper->pWorkspace()->setBox(rootAndErr.root);
181 rootAndErr.root->calculateGridCaches();
182
183 std::stringstream ss;
184 ss << rootAndErr.err;
185 g_Log.information("Error with using Morton indexes is:\n" + ss.str());
186 pProgress->report(1);
187}
188
189// Specialization for ToF events of different types
190template <size_t ND, template <size_t> class MDEventType>
192 switch (m_EventWS->getSpectrum(0).getEventType()) {
193 case Mantid::API::TOF:
194 appendEvents<Mantid::Types::Event::TofEvent, ND, MDEventType>(pProgress, bc);
195 break;
197 appendEvents<Mantid::DataObjects::WeightedEvent, ND, MDEventType>(pProgress, bc);
198 break;
200 appendEvents<Mantid::DataObjects::WeightedEventNoTime, ND, MDEventType>(pProgress, bc);
201 break;
202 default:
203 throw std::runtime_error("Events in event workspace had an unexpected data type!");
204 }
205}
206
207// Specilization for MD event types
208template <size_t ND>
210 switch (mdEventType<ND>()) {
211 case LEAN:
212 appendEvents<ND, DataObjects::MDLeanEvent>(pProgress, bc);
213 break;
214 case REGULAR:
215 appendEvents<ND, DataObjects::MDEvent>(pProgress, bc);
216 break;
217 default:
218 throw std::runtime_error("MD events in md event workspace had an unexpected data type!");
219 }
220}
221
222// Wrapper to have the proper functions, for Nd in range 2 to maxDim
223template <size_t maxDim>
225 auto ndim = m_OutWSWrapper->nDimensions();
226 if (ndim < 2)
227 throw std::runtime_error("Can't convert to MD workspace with dims " + std::to_string(ndim) + "less than 2");
228 if (ndim > maxDim)
229 return;
230 if (ndim == maxDim) {
231 appendEvents<maxDim>(pProgress, bc);
232 return;
233 } else
234 appendEventsFromInputWS<maxDim - 1>(pProgress, bc);
235}
236
238 static Mantid::DataObjects::MDLeanEvent<ND> makeMDEvent(const double &sig, const double &err, const uint16_t,
239 const uint16_t, const uint32_t, coord_t *coord) {
240 return Mantid::DataObjects::MDLeanEvent<ND>(sig, err, coord);
241 }
242};
243
245 if (dynamic_cast<DataObjects::MDEventWorkspace<DataObjects::MDEvent<ND>, ND> *>(m_OutWSWrapper->pWorkspace().get()))
246 return REGULAR;
247
249 m_OutWSWrapper->pWorkspace().get()))
250 return LEAN;
251 return NONE;
252}
253} // namespace MDAlgorithms
254} // namespace Mantid
#define PARALLEL_THREAD_NUMBER
#define PARALLEL_GET_MAX_THREADS
Helper class for reporting progress from algorithms.
Definition: Progress.h:25
A class for holding :
Definition: EventList.h:56
std::size_t getNumberEvents() const override
Return the number of events in the list.
Definition: EventList.cpp:1143
Templated class for the multi-dimensional event workspace.
Templated class holding data about a neutron detection event in N-dimensions (for example,...
Definition: MDLeanEvent.h:60
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
void resetNumSteps(int64_t nsteps, double start, double end)
Change the number of steps between start/end.
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
Definition: ProgressBase.h:51
static Mantid::Kernel::Logger g_Log
Definition: ConvToMDBase.h:76
std::vector< int32_t > m_detID
Definition: ConvToMDBase.h:72
std::shared_ptr< MDEventWSWrapper > m_OutWSWrapper
Definition: ConvToMDBase.h:60
UnitsConversionHelper m_UnitConversion
Definition: ConvToMDBase.h:80
This class creates the MDWorkspace from the collection of ToF events: converts to the MD events with ...
size_t initialize(const MDWSDescription &WSD, std::shared_ptr< MDEventWSWrapper > inWSWrapper, bool ignoreZeros) override
method sets up all internal variables necessary to convert from Event Workspace to MDEvent workspace
void appendEvents(API::Progress *pProgress, const API::BoxController_sptr &bc)
std::vector< MDEventType< ND > > convertEvents()
void appendEventsFromInputWS(API::Progress *pProgress, const API::BoxController_sptr &bc) override
static bool isSplitValid(const std::vector< T > &split_into)
The class specializes ConvToDataObjectsBase for the case when the conversion occurs from Events WS to...
DataObjects::EventWorkspace_const_sptr m_EventWS
Class to create the box structure of MDWorkspace.
helper class describes the properties of target MD workspace, which should be obtained as the result ...
void updateConversion(size_t i)
Method updates unit conversion given the index of detector parameters in the array of detectors.
double convertUnits(double val) const
do actual unit conversion from input to oputput data
std::shared_ptr< BoxController > BoxController_sptr
Shared ptr to BoxController.
@ WEIGHTED_NOTIME
Definition: IEventList.h:18
std::size_t numEvents(::NeXus::File &file, bool &hasTotalCounts, bool &oldNeXusFileNames, const std::string &prefix, const NexusHDF5Descriptor &descriptor)
Get the number of events in the currently opened group.
DLLExport void getEventsFrom(EventList &el, std::vector< Types::Event::TofEvent > *&events)
std::shared_ptr< MDTransfInterface > MDTransf_sptr
Helper class which provides the Collimation Length for SANS instruments.
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...
Definition: MDTypes.h:27
Eigen::Array< float, static_cast< int >(ND), 2 > MDSpaceBounds
Definition: Types.h:31
std::string to_string(const wide_integer< Bits, Signed > &n)
static Mantid::DataObjects::MDLeanEvent< ND > makeMDEvent(const double &sig, const double &err, const uint16_t, const uint16_t, const uint32_t, coord_t *coord)
static MDEventType< ND > makeMDEvent(const double &sig, const double &err, const uint16_t &expInfoIndex, const uint16_t &goniometer_index, const uint32_t &det_id, coord_t *coord)