Mantid
Loading...
Searching...
No Matches
ConvToMDEventsWS.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
9#include "MantidAPI/Run.h"
11
12namespace Mantid::MDAlgorithms {
13
14// This method sets a generic variable set as an extra dimensions from the log value at the event time.
15bool ConvToMDEventsWS::setGenericVariableFromLogs(const Mantid::Types::Core::DateAndTime &pT,
16 std::vector<coord_t> &localCoord) const {
17 if (!m_useLogTimes || m_Logs.size() <= m_GonioIndex.size()) {
18 return true;
19 }
20 int ic(0);
21 for (size_t idxLog = m_GonioIndex.size(); idxLog < m_Logs.size(); idxLog++) {
22 auto logval = m_Logs[idxLog]->getSingleValue(pT);
23 if (std::isnan(logval) || logval < m_extraDimBounds[ic].first || logval >= m_extraDimBounds[ic].second) {
24 return false;
25 }
26 localCoord[m_NMatrixDimensions + ic] = static_cast<coord_t>(logval);
27 ic++;
28 }
29 return true;
30}
31
34template <class T> size_t ConvToMDEventsWS::convertEventList(size_t workspaceIndex) {
35
36 const Mantid::DataObjects::EventList &el = m_EventWS->getSpectrum(workspaceIndex);
37 size_t numEvents = el.getNumberEvents();
38 if (numEvents == 0)
39 return 0;
40
41 // create local unit conversion class
43
44 uint32_t detID = m_detID[workspaceIndex];
45 uint16_t expInfoIndexLoc = m_ExpInfoIndex;
46
47 std::vector<coord_t> locCoord(m_Coord);
48 // set up unit conversion and calculate up all coordinates, which depend on
49 // spectra index only
50 if (!m_QConverter->calcYDepCoordinates(locCoord, workspaceIndex))
51 return 0; // skip if any y outsize of the range of interest;
52 localUnitConv.updateConversion(workspaceIndex);
53 //
54 // allocate temporary buffers for MD Events data
55 // MD events coordinates buffer
56 std::vector<coord_t> allCoord;
57 std::vector<float> sig_err; // array for signal and error.
58 std::vector<uint16_t> expInfoIndex; // Buffer for associated experiment-info index for each event
59 std::vector<uint16_t> goniometer_index; // Buffer for goniometer index for each event
60 std::vector<uint32_t> det_ids; // Buffer of det Id-s for each event
61
62 allCoord.reserve(this->m_NDims * numEvents);
63 sig_err.reserve(2 * numEvents);
64 expInfoIndex.reserve(numEvents);
65 goniometer_index.reserve(numEvents);
66 det_ids.reserve(numEvents);
67
68 // This little dance makes the getting vector of events more general (since
69 // you can't overload by return type).
70 typename std::vector<T> const *events_ptr;
71 getEventsFrom(el, events_ptr);
72 const typename std::vector<T> &events = *events_ptr;
73 // Iterators to start/end
74 for (auto it = events.cbegin(); it != events.cend(); it++) {
75 double val = localUnitConv.convertUnits(it->tof());
76 double signal = it->weight();
77 double errorSq = it->errorSquared();
79 continue; // skip if log value is NaN
80 if (!setGenericVariableFromLogs(it->pulseTime(), locCoord))
81 continue; // skip if log value is NaN or out of bounds
82 if (!m_QConverter->calcMatrixCoord(val, locCoord, signal, errorSq))
83 continue; // skip ND outside the range
84
85 sig_err.emplace_back(static_cast<float>(signal));
86 sig_err.emplace_back(static_cast<float>(errorSq));
87 expInfoIndex.emplace_back(expInfoIndexLoc);
88 goniometer_index.emplace_back(0); // default value
89 det_ids.emplace_back(detID);
90 allCoord.insert(allCoord.end(), locCoord.begin(), locCoord.end());
91 }
92
93 // Add them to the MDEW
94 size_t n_added_events = expInfoIndex.size();
95 m_OutWSWrapper->addMDData(sig_err, expInfoIndex, goniometer_index, det_ids, allCoord, n_added_events);
96 return n_added_events;
97}
98
101size_t ConvToMDEventsWS::conversionChunk(size_t workspaceIndex) {
102
103 switch (m_EventWS->getSpectrum(workspaceIndex).getEventType()) {
104 case Mantid::API::TOF:
105 return this->convertEventList<Mantid::Types::Event::TofEvent>(workspaceIndex);
107 return this->convertEventList<Mantid::DataObjects::WeightedEvent>(workspaceIndex);
109 return this->convertEventList<Mantid::DataObjects::WeightedEventNoTime>(workspaceIndex);
110 default:
111 throw std::runtime_error("EventList had an unexpected data type!");
112 }
113}
114
125size_t ConvToMDEventsWS::initialize(const MDWSDescription &WSD, std::shared_ptr<MDEventWSWrapper> inWSWrapper,
126 bool ignoreZeros, bool useLogTimes) {
127 size_t numSpec = ConvToMDBase::initialize(WSD, std::move(inWSWrapper), ignoreZeros, useLogTimes);
128
129 m_EventWS = std::dynamic_pointer_cast<const DataObjects::EventWorkspace>(m_InWS2D);
130 if (!m_EventWS)
131 throw(std::logic_error(" ConvertToMDEventWS should work with defined event workspace"));
132
133 // Record any special coordinate system known to the description.
135
136 // Look up required logs is using log times
137 if (m_useLogTimes) {
138 // Saves the Q-cartesian transformation
139 m_Wtransf = WSD.m_Wtransf;
140 m_NMatrixDimensions = m_QConverter->getNMatrixDimensions(WSD.getEMode(), nullptr);
141
142 // Log values for Gonios
143 const Mantid::API::Run &run = WSD.getInWS()->run();
145 for (size_t n = 0; n < m_Goniometer.getNumberAxes(); n++) {
147 if (run.hasProperty(ax.name)) {
148 m_Logs.push_back(
149 std::unique_ptr<Kernel::TimeSeriesProperty<double>>(run.getTimeSeriesProperty<double>(ax.name)->clone()));
150 m_GonioIndex.push_back(n);
151 m_timeLogsName.push_back(ax.name);
152 }
153 }
154 const auto &dimNames = WSD.getDimNames();
155 for (auto it = dimNames.cbegin() + m_NMatrixDimensions; it != dimNames.cend(); ++it) {
156 m_Logs.push_back(
157 std::unique_ptr<Kernel::TimeSeriesProperty<double>>(run.getTimeSeriesProperty<double>(*it)->clone()));
158 m_extraDimBounds.push_back(m_QConverter->getDimBounds(it - dimNames.cbegin()));
159 }
160 if (!m_GonioIndex.empty()) {
162 m_QConverter->setInvertRot(true);
163 }
164 }
165
166 return numSpec;
167}
168
170
171 // Get the box controller
172 Mantid::API::BoxController_sptr bc = m_OutWSWrapper->pWorkspace()->getBoxController();
173
174 // if any property dimension is outside of the data range requested, the job
175 // is done;
176 if (!m_QConverter->calcGenericVariables(m_Coord, m_NDims))
177 return;
178
179 appendEventsFromInputWS(pProgress, bc);
180
181 pProgress->report();
182
184 m_OutWSWrapper->pWorkspace()->setCoordinateSystem(m_coordinateSystem);
185}
186
188 // Is the access to input events thread-safe?
189 // bool MultiThreadedAdding = m_EventWS->threadSafe();
190 // preprocessed detectors insure that each detector has its own spectra
191 size_t lastNumBoxes = bc->getTotalNumMDBoxes();
192 size_t nEventsInWS = m_OutWSWrapper->pWorkspace()->getNPoints();
193 //--->>> Thread control stuff
194 Kernel::ThreadSchedulerFIFO *ts(nullptr);
195
196 int nThreads(m_NumThreads);
197 if (nThreads < 0)
198 nThreads = 0; // negative m_NumThreads correspond to all cores used, 0 no
199 // threads and positive number -- nThreads requested;
200 bool runMultithreaded = false;
201 if (m_NumThreads != 0) {
202 runMultithreaded = true;
203 // Create the thread pool that will run all of these. It will be deleted by
204 // the threadpool
206 // it will initiate thread pool with number threads or machine's cores (0 in
207 // tp constructor)
208 pProgress->resetNumSteps(m_NSpectra, 0, 1);
209 }
210 Kernel::ThreadPool tp(ts, nThreads, new API::Progress());
211 //<<<-- Thread control stuff
212
213 // for continuous rotation, algorithm takes much longer. We increase report rate for QOL usage.
214 const bool frequentReport = !m_GonioIndex.empty();
215 const int div = 500;
216
217 size_t eventsAdded = 0;
218 for (size_t wi = 0; wi < m_NSpectra; wi++) {
219
220 size_t nConverted = conversionChunk(wi);
221 eventsAdded += nConverted;
222 nEventsInWS += nConverted;
223
224 if (frequentReport && wi % div == 0) {
225 pProgress->report(static_cast<int>(wi));
226 }
227
228 // Keep a running total of how many events we've added
229 if (bc->shouldSplitBoxes(nEventsInWS, eventsAdded, lastNumBoxes)) {
230 if (runMultithreaded) {
231 // Now do all the splitting tasks
232 m_OutWSWrapper->pWorkspace()->splitAllIfNeeded(ts);
233 if (ts->size() > 0)
234 tp.joinAll();
235 } else {
236 m_OutWSWrapper->pWorkspace()->splitAllIfNeeded(nullptr); // it is done this way as it is possible trying to do
237 // single
238 // threaded split more efficiently
239 }
240 // Count the new # of boxes.
241 lastNumBoxes = m_OutWSWrapper->pWorkspace()->getBoxController()->getTotalNumMDBoxes();
242 eventsAdded = 0;
243 pProgress->report(static_cast<int>(wi));
244 }
245 }
246 // Do a final splitting of everything
247 if (runMultithreaded) {
248 m_OutWSWrapper->pWorkspace()->splitAllIfNeeded(ts);
249 tp.joinAll();
250 } else {
251 m_OutWSWrapper->pWorkspace()->splitAllIfNeeded(nullptr);
252 }
253
254 // Recount totals at the end.
255 m_OutWSWrapper->pWorkspace()->refreshCache();
256}
257
258} // namespace Mantid::MDAlgorithms
static std::unique_ptr< QThreadPool > tp
bool hasProperty(const std::string &name) const
Does the property exist on the object.
Kernel::TimeSeriesProperty< T > * getTimeSeriesProperty(const std::string &name) const
Returns a property as a time series property.
Helper class for reporting progress from algorithms.
Definition Progress.h:25
This class stores information regarding an experimental run as a series of log entries.
Definition Run.h:35
const Geometry::Goniometer & getGoniometer() const
Return reference to the first const Goniometer object for this run.
Definition Run.cpp:525
A class for holding :
Definition EventList.h:57
std::size_t getNumberEvents() const override
Return the number of events in the list.
const GoniometerAxis & getAxis(size_t axisnumber) const
Get GoniometerAxis obfject using motor number.
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.
A Thread Pool implementation that keeps a certain number of threads running (normally,...
Definition ThreadPool.h:36
A First-In-First-Out Thread Scheduler.
size_t size() override
Returns the size of the queue.
A specialised Property class for holding a series of time-value pairs.
API::MatrixWorkspace_const_sptr m_InWS2D
std::vector< std::string > m_timeLogsName
virtual size_t initialize(const MDWSDescription &WSD, std::shared_ptr< MDEventWSWrapper > inWSWrapper, bool ignoreZeros, bool useLogTimes=false)
method which initiates all main class variables
std::vector< int32_t > m_detID
Mantid::Kernel::SpecialCoordinateSystem m_coordinateSystem
Any special coordinate system used.
bool m_useLogTimes
Flag to use log values corresponding to event pulse time instead of average values.
std::vector< coord_t > m_Coord
size_t m_NDims
number of target ws dimensions
std::shared_ptr< MDEventWSWrapper > m_OutWSWrapper
UnitsConversionHelper m_UnitConversion
std::vector< std::unique_ptr< Kernel::TimeSeriesProperty< double > > > m_Logs
size_t initialize(const MDWSDescription &WSD, std::shared_ptr< MDEventWSWrapper > inWSWrapper, bool ignoreZeros, bool useLogTimes) override
method sets up all internal variables necessary to convert from Event Workspace to MDEvent workspace
size_t convertEventList(size_t workspaceIndex)
function converts particular type of events into MD space and add these events to the workspace itsel...
size_t conversionChunk(size_t workspaceIndex) override
The method runs conversion for a single event list, corresponding to a particular workspace index.
std::vector< std::pair< coord_t, coord_t > > m_extraDimBounds
DataObjects::EventWorkspace_const_sptr m_EventWS
virtual void appendEventsFromInputWS(API::Progress *pProgress, const API::BoxController_sptr &bc)
bool setGenericVariableFromLogs(const Mantid::Types::Core::DateAndTime &pT, std::vector< coord_t > &localCoord) const
void runConversion(API::Progress *pProgress) override
method which starts the conversion procedure
helper class describes the properties of target MD workspace, which should be obtained as the result ...
API::MatrixWorkspace_const_sptr getInWS() const
std::vector< std::string > getDimNames() const
Mantid::Kernel::SpecialCoordinateSystem getCoordinateSystem() const
Kernel::DeltaEMode::Type getEMode() const
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.
std::size_t numEvents(Nexus::File &file, bool &hasTotalCounts, bool &oldNeXusFileNames, const std::string &prefix)
Get the number of events in the currently opened group.
DLLExport void getEventsFrom(EventList &el, std::vector< Types::Event::TofEvent > *&events)
Mantid::Kernel::Matrix< double > DblMatrix
Definition Matrix.h:206
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...
Definition MDTypes.h:27
Counter clockwise rotation.
Definition Goniometer.h:38