Mantid
Loading...
Searching...
No Matches
LoadBankFromDiskTask.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 +
14#include "MantidKernel/Timer.h"
15#include "MantidKernel/Unit.h"
18#include "MantidNexus/NexusFile.h"
20
21#include <algorithm>
22#include <utility>
23
24namespace {
25// this is used for unit conversion to correct units
26const std::string MICROSEC("microseconds");
27} // namespace
28
29namespace Mantid::DataHandling {
30
43LoadBankFromDiskTask::LoadBankFromDiskTask(DefaultEventLoader &loader, std::string entry_name, std::string entry_type,
44 const std::size_t numEvents, const bool oldNeXusFileNames,
45 API::Progress *prog, std::shared_ptr<std::mutex> ioMutex,
46 Kernel::ThreadScheduler &scheduler, std::vector<int> framePeriodNumbers)
47 : m_loader(loader), entry_name(std::move(entry_name)), entry_type(std::move(entry_type)), prog(prog),
48 scheduler(scheduler), m_loadError(false), m_have_weight(false),
49 m_framePeriodNumbers(std::move(framePeriodNumbers)) {
50 setMutex(ioMutex);
51 m_cost = static_cast<double>(numEvents);
52
53 // some field names changed over time
54 m_timeOfFlightFieldName = oldNeXusFileNames ? "event_time_of_flight" : "event_time_offset";
55 m_detIdFieldName = oldNeXusFileNames ? "event_pixel_id" : "event_id";
56
57 // detector id range
58 m_min_id = std::numeric_limits<uint32_t>::max();
59 m_max_id = 0;
60}
61
64void LoadBankFromDiskTask::loadPulseTimes(Nexus::File &file) {
65 try {
66 // First, get info about the event_time_zero field in this bank
67 file.openData("event_time_zero");
68 } catch (const Nexus::Exception &) {
69 // Field not found error is most likely.
70 // Use the "proton_charge" das logs.
72 return;
73 }
74 std::string thisStartTime;
75 size_t thispulseTimes = 0;
76 // If the offset is not present, use Unix epoch
77 if (!file.hasAttr("offset")) {
78 thisStartTime = "1970-01-01T00:00:00Z";
79 m_loader.alg->getLogger().warning() << "In loadPulseTimes: no ISO8601 offset attribute provided for "
80 "event_time_zero, using UNIX epoch instead\n";
81 } else {
82 file.getAttr("offset", thisStartTime);
83 }
84
85 if (!file.getInfo().dims.empty())
86 thispulseTimes = static_cast<size_t>(file.getInfo().dims[0]);
87 file.closeData();
88
89 // Now, we look through existing ones to see if it is already loaded
90 // thisBankPulseTimes = NULL;
91 for (auto &bankPulseTime : m_loader.m_bankPulseTimes) {
92 if (bankPulseTime->equals(thispulseTimes, thisStartTime)) {
93 thisBankPulseTimes = bankPulseTime;
94 return;
95 }
96 }
97
98 // Not found? Need to load and add it
99 thisBankPulseTimes = std::make_shared<BankPulseTimes>(file, m_framePeriodNumbers);
101}
102
107std::unique_ptr<std::vector<uint64_t>> LoadBankFromDiskTask::loadEventIndex(Nexus::File &file) {
108 // Get the event_index (a list of size of # of pulses giving the index in
109 // the event list for that pulse) as a uint64 vector.
110 // The Nexus standard does not specify if this is to be 32-bit or 64-bit
111 // integers, so we use the NeXusIOHelper to do the conversion on the fly.
112 auto event_index =
113 std::make_unique<std::vector<uint64_t>>(Nexus::IOHelper::readNexusVector<uint64_t>(file, "event_index"));
114
115 // Look for the sign that the bank is empty
116 if (event_index->size() == 1) {
117 if (event_index->at(0) == 0) {
118 // One entry, only zero. This means NO events in this bank.
119 m_loadError = true;
120 m_loader.alg->getLogger().debug() << "Bank " << entry_name << " is empty.\n";
121 }
122 }
123
124 return event_index;
125}
126
135void LoadBankFromDiskTask::prepareEventId(Nexus::File &file, uint64_t &start_event, uint64_t &stop_event,
136 const uint64_t &start_event_index) {
137 // Get the list of pixel ID's
138 file.openData(m_detIdFieldName);
139
140 // By default, use all available indices
141 start_event = start_event_index;
142 Nexus::Info id_info = file.getInfo();
143 // dims[0] can be negative in ISIS meaning 2^32 + dims[0]. Take that into
144 // account
145 uint64_t dim0 = recalculateDataSize(id_info.dims[0]);
146 stop_event = dim0;
147
148 // We are loading part - work out the event number range
149 if (m_loader.chunk != EMPTY_INT()) {
151 // Don't change stop_event for the final chunk
152 if (start_event + m_loader.eventsPerChunk < stop_event)
153 stop_event = start_event + m_loader.eventsPerChunk;
154 }
155
156 // Make sure it is within range
157 if (stop_event > dim0)
158 stop_event = dim0;
159
160 m_loader.alg->getLogger().debug() << entry_name << ": start_event " << start_event << " stop_event " << stop_event
161 << "\n";
162}
163
168std::unique_ptr<std::vector<uint32_t>> LoadBankFromDiskTask::loadEventId(Nexus::File &file) {
169 // This is the data size
170 Nexus::Info id_info = file.getInfo();
171 const Nexus::dimsize_t dim0 = recalculateDataSize(id_info.dims[0]);
172
173 // Check that the required space is there in the file.
174 if (dim0 < m_loadSize[0] + m_loadStart[0]) {
175 m_loader.alg->getLogger().warning() << "Entry " << entry_name << "'s event_id field is too small (" << dim0
176 << ") to load the desired data size (" << m_loadSize[0] + m_loadStart[0]
177 << ").\n";
178 m_loadError = true;
179 }
180
181 // Now we allocate the required arrays
182 auto event_id = std::make_unique<std::vector<uint32_t>>(dim0);
183
184 if (!m_loadError) {
185 Nexus::IOHelper::readNexusSlab<uint32_t, Nexus::IOHelper::Narrowing::Prevent>(*event_id, file, m_detIdFieldName,
187 file.closeData();
188
189 // determine the range of pixel ids
190 {
191 const auto [min_id, max_id] = Mantid::Kernel::parallel_minmax<uint32_t>(event_id);
192 m_min_id = min_id;
193 m_max_id = max_id;
194 }
195
196 if (m_min_id > static_cast<uint32_t>(m_loader.eventid_max)) {
197 // All the detector IDs in the bank are higher than the highest 'known'
198 // (from the IDF)
199 // ID. Setting this will abort the loading of the bank.
200 m_loadError = true;
201 }
202 // fixup the minimum pixel id in the case that it's lower than the lowest
203 // 'known' id. We test this by checking that when we add the offset we
204 // would not get a negative index into the vector. Note that m_min_id is
205 // a uint so we have to be cautious about adding it to an int which may be
206 // negative.
207 if (static_cast<int32_t>(m_min_id) + m_loader.pixelID_to_wi_offset < 0) {
208 m_min_id = static_cast<uint32_t>(abs(m_loader.pixelID_to_wi_offset));
209 }
210 // fixup the maximum pixel id in the case that it's higher than the
211 // highest 'known' id
212 if (m_max_id > static_cast<uint32_t>(m_loader.eventid_max))
213 m_max_id = static_cast<uint32_t>(m_loader.eventid_max);
214 }
215 return event_id;
216}
217
222std::unique_ptr<std::vector<float>> LoadBankFromDiskTask::loadTof(Nexus::File &file) {
223 // Get the list of event_time_of_flight's
224 file.openData(m_timeOfFlightFieldName);
225
226 // This is the data size
227 // Check that the required space is there in the file.
228 Nexus::Info tof_info = file.getInfo();
229 uint64_t tof_dim0 = recalculateDataSize(tof_info.dims[0]);
230 if (tof_dim0 < m_loadSize[0] + m_loadStart[0]) {
231 m_loader.alg->getLogger().warning() << "Entry " << entry_name
232 << "'s event_time_offset field is too small "
233 "to load the desired data.\n";
234 m_loadError = true;
235 }
236
237 // Allocate the array
238 auto event_time_of_flight = std::make_unique<std::vector<float>>(tof_dim0);
239
240 // Mantid assumes event_time_offset to be float.
241 // Nexus only requires event_time_offset to be a NXNumber.
242 // We thus have to consider 32-bit or 64-bit options, and we
243 // explicitly allow downcasting using the additional AllowDowncasting
244 // template argument.
245 // the memory is allocated earlier in the function
246 Nexus::IOHelper::readNexusSlab<float, Nexus::IOHelper::Narrowing::Allow>(
247 *event_time_of_flight, file, m_timeOfFlightFieldName, m_loadStart, m_loadSize);
248 std::string tof_unit;
249 try {
250 file.getAttr("units", tof_unit);
251 } catch (Nexus::Exception const &) {
252 }
253 file.closeData();
254
255 // Convert Tof to microseconds
256 if (tof_unit != MICROSEC)
257 Kernel::Units::timeConversionVector(*event_time_of_flight, tof_unit, MICROSEC);
258
259 return event_time_of_flight;
260}
261
267std::unique_ptr<std::vector<float>> LoadBankFromDiskTask::loadEventWeights(Nexus::File &file) {
268 try {
269 // First, get info about the event_weight field in this bank
270 file.openData("event_weight");
271 } catch (Nexus::Exception const &) {
272 // Field not found error is most likely.
273 m_have_weight = false;
274 return std::unique_ptr<std::vector<float>>();
275 }
276 // OK, we've got them
277 m_have_weight = true;
278
279 // Allocate the array
280 auto event_weight = std::make_unique<std::vector<float>>(m_loadSize[0]);
281
282 Nexus::Info weight_info = file.getInfo();
283 uint64_t weight_dim0 = recalculateDataSize(weight_info.dims[0]);
284 if (weight_dim0 < m_loadSize[0] + m_loadStart[0]) {
285 m_loader.alg->getLogger().warning() << "Entry " << entry_name
286 << "'s event_weight field is too small to load the desired data.\n";
287 m_loadError = true;
288 }
289
290 // Check that the type is what it is supposed to be
291 if (weight_info.type == NXnumtype::FLOAT32)
292 file.getSlab(event_weight->data(), m_loadStart, m_loadSize);
293 else {
294 m_loader.alg->getLogger().warning() << "Entry " << entry_name
295 << "'s event_weight field is not FLOAT32! It will be skipped.\n";
296 m_loadError = true;
297 }
298
299 if (!m_loadError) {
300 file.closeData();
301 }
302 return event_weight;
303}
304
306 // timer for performance
308
309 // These give the limits in each file as to which events we actually load
310 // (when filtering by time).
311 m_loadStart.resize(1, 0);
312 m_loadSize.resize(1, 0);
313
314 m_loadError = false;
316
317 prog->report(entry_name + ": load from disk");
318
319 // arrays to load into
320 std::shared_ptr<std::vector<uint32_t>> event_id;
321 std::shared_ptr<std::vector<float>> event_time_of_flight;
322 std::shared_ptr<std::vector<float>> event_weight;
323 std::shared_ptr<std::vector<uint64_t>> event_index;
324
325 // Open the file
326 Nexus::File file(m_loader.alg->m_filename);
327 try {
328 // Navigate into the file
329 file.openGroup(m_loader.alg->m_top_entry_name, "NXentry");
330 // Open the bankN_event group
331 file.openGroup(entry_name, entry_type);
332
333 const bool needPulseInfo = (!m_loader.alg->compressEvents) || m_loader.alg->compressTolerance == 0 ||
336
337 // Load the event_index field.
338 if (needPulseInfo)
339 event_index = this->loadEventIndex(file);
340 else
341 event_index = nullptr;
342
343 if (!m_loadError) {
344 // Load and validate the pulse times
345 if (needPulseInfo)
346 this->loadPulseTimes(file);
347 else
348 thisBankPulseTimes = nullptr;
349 // The event_index should be the same length as the pulse times from DAS
350 // logs.
351 if (event_index && event_index->size() != thisBankPulseTimes->numberOfPulses())
352 m_loader.alg->getLogger().warning() << "Bank " << entry_name
353 << " has a mismatch between the number of event_index entries "
354 "and the number of pulse times in event_time_zero.\n";
355 // Open and validate event_id field.
356 uint64_t start_event = 0;
357 uint64_t stop_event = 0;
358 if (event_index)
359 this->prepareEventId(file, start_event, stop_event, event_index->operator[](0));
360 else
361 this->prepareEventId(file, start_event, stop_event, 0);
362
363 // These are the arguments to getSlab()
364 m_loadStart[0] = start_event;
365 m_loadSize[0] = stop_event - start_event;
366
367 if ((m_loader.alg->compressEvents) || ((m_loadSize[0] > 0))) {
368 if (m_loader.alg->getCancel()) {
369 m_loader.alg->getLogger().error() << "Loading bank " << entry_name << " is cancelled.\n";
370 m_loadError = true; // To allow cancelling the algorithm
371 }
372
373 // Load pixel IDs
374 if (!m_loadError)
375 event_id = this->loadEventId(file);
376
377 // for compression the number of events needs to come from elsewhere
378 if (!event_index)
379 m_loadSize[0] = event_id->size();
380
381 if (m_loader.alg->getCancel()) {
382 m_loader.alg->getLogger().error() << "Loading bank " << entry_name << " is cancelled.\n";
383 m_loadError = true; // To allow cancelling the algorithm
384 }
385
386 // And TOF.
387 if (!m_loadError) {
388 event_time_of_flight = this->loadTof(file);
389 if (m_have_weight) {
390 event_weight = this->loadEventWeights(file);
391 }
392 }
393 } // Size is at least 1
394 else {
395 // Found a size that was 0 or less; stop processing
397 << "Loading bank " << entry_name << " is stopped due to either zero/negative loading size ("
398 << m_loadStart[0] << ") or negative load start index (" << m_loadStart[0] << ")\n";
399 m_loadError = true;
400 }
401
402 } // no error
403 } // try block
404 catch (std::exception &e) {
405 m_loader.alg->getLogger().error() << "Error while loading bank " << entry_name << ":\n";
406 m_loader.alg->getLogger().error() << e.what() << '\n';
407 m_loadError = true;
408 } catch (...) {
409 m_loader.alg->getLogger().error() << "Unspecified error while loading bank " << entry_name << '\n';
410 m_loadError = true;
411 }
412
413 // Close up the file even if errors occured.
414 file.closeGroup();
415 file.close();
416
417 // Abort if anything failed
418 if (m_loadError) {
419 return;
420 }
421
422 const auto bank_size = m_max_id - m_min_id;
423 const auto minSpectraToLoad = static_cast<uint32_t>(m_loader.alg->m_specMin);
424 const auto maxSpectraToLoad = static_cast<uint32_t>(m_loader.alg->m_specMax);
425 const auto emptyInt = static_cast<uint32_t>(EMPTY_INT());
426 // check that if a range of spectra were requested that these fit within
427 // this bank
428 if (minSpectraToLoad != emptyInt && m_min_id < minSpectraToLoad) {
429 if (minSpectraToLoad > m_max_id) { // the minimum spectra to load is more
430 // than the max of this bank
431 return;
432 }
433 // the min spectra to load is higher than the min for this bank
434 m_min_id = minSpectraToLoad;
435 }
436 if (maxSpectraToLoad != emptyInt && m_max_id > maxSpectraToLoad) {
437 if (maxSpectraToLoad < m_min_id) {
438 // the maximum spectra to load is less than the minimum of this bank
439 return;
440 }
441 // the max spectra to load is lower than the max for this bank
442 m_max_id = maxSpectraToLoad;
443 }
444 if (m_min_id > m_max_id) {
445 // the min is now larger than the max, this means the entire block of
446 // spectra to load is outside this bank
447 return;
448 }
449
450 // schedule the job to generate the event lists
451 auto mid_id = m_max_id;
452 if (m_loader.splitProcessing && m_max_id > (m_min_id + (bank_size / 4)))
453 // only split if told to and the section to load is at least 1/4 the size
454 // of the whole bank
455 mid_id = (m_max_id + m_min_id) / 2;
456
457 // No error? Launch a new task to process that data.
458 const auto numEvents = static_cast<size_t>(m_loadSize[0]);
459 const auto startAt = static_cast<size_t>(m_loadStart[0]);
460
461 if ((m_loader.alg->compressEvents) && (!event_weight) && (m_loader.alg->compressTolerance != 0)) {
462 // this method is for unweighted events that the user wants compressed on load
463
464 // TODO should this be created elsewhere?
465 const auto [tof_min, tof_max] = Mantid::Kernel::parallel_minmax(event_time_of_flight);
466
467 const bool log_compression = (m_loader.alg->compressTolerance < 0);
468
469 // reduce tof range if filtering was requested
470 auto tof_min_fixed = tof_min;
471 auto tof_max_fixed = tof_max;
474 tof_max_fixed = std::min<float>(tof_max_fixed, static_cast<float>(m_loader.alg->filter_tof_max));
476 tof_min_fixed = std::max<float>(tof_min_fixed, static_cast<float>(m_loader.alg->filter_tof_min));
477 }
478
479 // fixup the minimum tof for log binning since it cannot be <= 0
480 if (log_compression && tof_min_fixed <= 0.) {
481 tof_min_fixed = std::abs(static_cast<float>(m_loader.alg->compressTolerance));
482 }
483
484 // Join back up the tof limits to the global ones
485 // This is not thread safe, so only one thread at a time runs this.
486 {
487 std::lock_guard<std::mutex> _lock(m_loader.alg->m_tofMutex);
488 if (tof_min_fixed < m_loader.alg->shortest_tof) {
489 m_loader.alg->shortest_tof = tof_min_fixed;
490 }
491 if (tof_max_fixed > m_loader.alg->longest_tof) {
492 m_loader.alg->longest_tof = tof_max_fixed;
493 }
494 // TODO
495 // m_loader.alg->bad_tofs += badTofs;
496 // m_loader.alg->discarded_events += my_discarded_events;
497 }
498
499 // delta >= 0 is linear, < 0 is log
501
502 // make a vector of logorithmic bins
503 auto histogram_bin_edges = std::make_shared<std::vector<double>>();
504 Mantid::Kernel::VectorHelper::createAxisFromRebinParams({tof_min_fixed, delta, (tof_max_fixed + std::abs(delta))},
505 *histogram_bin_edges);
506
507 // create the tasks
508 std::shared_ptr<Task> newTask1 = std::make_shared<ProcessBankCompressed>(
509 m_loader, entry_name, prog, event_id, event_time_of_flight, startAt, event_index, thisBankPulseTimes, m_min_id,
510 mid_id, histogram_bin_edges, m_loader.alg->compressTolerance);
511 scheduler.push(newTask1);
512 if (m_loader.splitProcessing && (mid_id < m_max_id)) {
513 std::shared_ptr<Task> newTask2 = std::make_shared<ProcessBankCompressed>(
514 m_loader, entry_name, prog, event_id, event_time_of_flight, startAt, event_index, thisBankPulseTimes,
515 (mid_id + 1), m_max_id, histogram_bin_edges, m_loader.alg->compressTolerance);
516 scheduler.push(newTask2);
517 }
518 } else {
519 // create all events using traditional method
520 std::shared_ptr<Task> newTask1 = std::make_shared<ProcessBankData>(
521 m_loader, entry_name, prog, event_id, event_time_of_flight, numEvents, startAt, event_index, thisBankPulseTimes,
522 m_have_weight, event_weight, m_min_id, mid_id);
523 scheduler.push(newTask1);
524 if (m_loader.splitProcessing && (mid_id < m_max_id)) {
525 std::shared_ptr<Task> newTask2 = std::make_shared<ProcessBankData>(
526 m_loader, entry_name, prog, event_id, event_time_of_flight, numEvents, startAt, event_index,
527 thisBankPulseTimes, m_have_weight, event_weight, (mid_id + 1), m_max_id);
528 scheduler.push(newTask2);
529 }
530 }
531
532#ifndef _WIN32
533 if (m_loader.alg->getLogger().isDebug())
534 m_loader.alg->getLogger().debug() << "Time to LoadBankFromDisk " << entry_name << " " << timer << "\n";
535#endif
537}
538
545uint64_t LoadBankFromDiskTask::recalculateDataSize(const int64_t size) {
546 uint64_t ret(size);
547 if (size < 0) {
548 uint64_t const shift = uint64_t(1) << 32;
549 ret += shift;
550 }
551 return ret;
552}
553
554} // namespace Mantid::DataHandling
bool getCancel() const
Returns the cancellation state.
Kernel::Logger & getLogger() const
Returns a reference to the logger.
Helper class for reporting progress from algorithms.
Definition Progress.h:25
Helper class for LoadEventNexus that is specific to the current default loading code for NXevent_data...
int32_t eventid_max
Maximum (inclusive) event ID possible for this instrument.
std::vector< std::shared_ptr< BankPulseTimes > > m_bankPulseTimes
One entry of pulse times for each preprocessor.
detid_t pixelID_to_wi_offset
Offset in the pixelID_to_wi_vector to use.
bool splitProcessing
whether or not to launch multiple ProcessBankData jobs per bank
size_t eventsPerChunk
number of chunks per bank
int firstChunkForBank
for multiple chunks per bank
bool m_haveWeights
Flag for dealing with a simulated file.
void run() override
Main method that performs the work for the task.
void loadPulseTimes(Nexus::File &file)
Load the pulse times, if needed.
std::unique_ptr< std::vector< uint64_t > > loadEventIndex(Nexus::File &file)
Load the event_index field (a list of size of # of pulses giving the index in the event list for that...
Nexus::DimVector m_loadStart
Index to load start at in the file.
std::unique_ptr< std::vector< float > > loadTof(Nexus::File &file)
Open and load the times-of-flight data.
uint32_t m_max_id
Maximum pixel ID in this data.
Kernel::ThreadScheduler & scheduler
ThreadScheduler running this task.
void prepareEventId(Nexus::File &file, uint64_t &start_event, uint64_t &stop_event, const uint64_t &start_event_index)
Open the event_id field and validate the contents.
std::string entry_name
NXS address to bank.
std::unique_ptr< std::vector< float > > loadEventWeights(Nexus::File &file)
Load weight of weigthed events if they exist.
uint32_t m_min_id
Minimum pixel ID in this data.
API::Progress * prog
Progress reporting.
LoadBankFromDiskTask(DefaultEventLoader &loader, std::string entry_name, std::string entry_type, const std::size_t numEvents, const bool oldNeXusFileNames, API::Progress *prog, std::shared_ptr< std::mutex > ioMutex, Kernel::ThreadScheduler &scheduler, std::vector< int > framePeriodNumbers)
Constructor.
Nexus::DimVector m_loadSize
How much to load in the file.
const std::vector< int > m_framePeriodNumbers
Frame period numbers.
std::shared_ptr< BankPulseTimes > thisBankPulseTimes
Object with the pulse times for this bank.
DefaultEventLoader & m_loader
Algorithm being run.
bool m_loadError
Did we get an error in loading.
std::unique_ptr< std::vector< uint32_t > > loadEventId(Nexus::File &file)
Load the event_id field, which has been opened.
uint64_t recalculateDataSize(const int64_t size)
Interpret the value describing the number of events.
bool m_is_time_filtered
if wall-clock filtering was requested
double longest_tof
Limits found to tof.
double filter_tof_max
Filter by a maximum time-of-flight.
int32_t m_specMax
Maximum spectrum to load.
double compressTolerance
Tolerance for CompressEvents; use -1 to mean don't compress.
std::string m_filename
The name and path of the input file.
std::shared_ptr< BankPulseTimes > m_allBanksPulseTimes
Pulse times for ALL banks, taken from proton_charge log.
double shortest_tof
Limits found to tof.
std::mutex m_tofMutex
Mutex protecting tof limits.
bool filter_tof_range
Tof range is being filtered.
int32_t m_specMin
Minimum spectrum to load.
double filter_tof_min
Filter by a minimum time-of-flight.
std::string m_top_entry_name
name of top level NXentry to use
void debug(const std::string &msg)
Logs at debug level.
Definition Logger.cpp:145
void error(const std::string &msg)
Logs at error level.
Definition Logger.cpp:108
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
bool isDebug() const
Returns true if log level is at least debug.
Definition Logger.cpp:189
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
double m_cost
Cached computational cost for the thread.
Definition Task.h:82
void setMutex(const std::shared_ptr< std::mutex > &mutex)
Set the mutex object for this Task.
Definition Task.h:78
The ThreadScheduler object defines how tasks are allocated to threads and in what order.
virtual void push(std::shared_ptr< Task > newTask)=0
Add a Task to the queue.
A simple class that provides a wall-clock (not processor time) timer.
Definition Timer.h:27
void reset()
Explicitly reset the timer.
Definition Timer.cpp:48
Class that provides for a standard Nexus exception.
static unsigned short constexpr FLOAT32
std::size_t numEvents(Nexus::File &file, bool &hasTotalCounts, bool &oldNeXusFileNames, const std::string &prefix, const Nexus::NexusDescriptor &descriptor)
Get the number of events in the currently opened group.
void timeConversionVector(std::vector< T > &vec, const std::string &input_unit, const std::string &output_unit)
Definition Unit.h:661
int MANTID_KERNEL_DLL createAxisFromRebinParams(const std::vector< double > &params, std::vector< double > &xnew, const bool resize_xnew=true, const bool full_bins_only=false, const double xMinHint=std::nan(""), const double xMaxHint=std::nan(""), const bool useReverseLogarithmic=false, const double power=-1)
Creates a new output X array given a 'standard' set of rebinning parameters.
std::pair< T, T > parallel_minmax(std::vector< T > const *const vec, size_t const grainsize=1000)
parallel_minmax
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
Definition EmptyValues.h:24
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition EmptyValues.h:42
STL namespace.
This structure holds the type and dimensions of a primative field/array.
DimVector dims
The dimensions of the file.