Mantid
Loading...
Searching...
No Matches
LoadANSTOHelper.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 +
15
16#include <boost/filesystem.hpp>
17
18#include <algorithm>
19#include <numeric>
20
22
23// Extract datasets from the group that match a regex filter
24std::vector<std::string> filterDatasets(const Nexus::NXEntry &entry, const std::string &groupAddress,
25 const std::string &regexFilter) {
26 std::vector<std::string> fvalues;
27 auto group = entry.openNXGroup(groupAddress);
28 auto datasets = group.datasets();
29 for (auto nxi : datasets) {
30 if (std::regex_match(nxi.nxname, std::regex(regexFilter))) {
31 fvalues.emplace_back(nxi.nxname);
32 }
33 }
34
35 return fvalues;
36}
37
38// Extract groups from the group that match a regex filter
39std::vector<std::string> filterGroups(const Nexus::NXEntry &entry, const std::string &groupAddress,
40 const std::string &regexFilter) {
41 std::vector<std::string> fvalues;
42 auto group = entry.openNXGroup(groupAddress);
43 auto groups = group.groups();
44 for (auto nxi : groups) {
45 if (std::regex_match(nxi.nxname, std::regex(regexFilter))) {
46 fvalues.emplace_back(nxi.nxname);
47 }
48 }
49
50 return fvalues;
51}
52
53// ProgressTracker
54ProgressTracker::ProgressTracker(API::Progress &progBar, const char *msg, int64_t target, size_t count)
55 : m_msg(msg), m_count(count), m_step(target / count), m_next(m_step), m_progBar(progBar) {
56
58}
61 while (m_next <= position) {
63
64 switch (m_count) {
65 case 0:
66 return;
67
68 case 1:
69 m_count = 0;
70 m_next = std::numeric_limits<int64_t>::max();
71 return;
72
73 default:
74 m_count--;
75 m_next += m_step;
76 }
77 }
78}
80 if (m_count != 0) {
82 m_count = 0;
83 }
84}
85
86void ProgressTracker::setTarget(int64_t target) {
87 if (m_count == 0) {
88 m_step = target;
89 m_next = m_step;
90 return;
91 }
92 m_step = std::max<int64_t>(1, target / m_count);
93 m_next = m_step;
94}
95
96// EventProcessor
97EventProcessor::EventProcessor(const std::vector<bool> &roi, const size_t stride, const double period,
98 const double phase, const int64_t startTime, const double tofMinBoundary,
99 const double tofMaxBoundary, const double timeMinBoundary, const double timeMaxBoundary)
100 : m_roi(roi), m_stride(stride), m_frames(0), m_framesValid(0), m_startTime(startTime), m_period(period),
101 m_phase(phase), m_tofMinBoundary(tofMinBoundary), m_tofMaxBoundary(tofMaxBoundary),
102 m_timeMinBoundary(timeMinBoundary), m_timeMaxBoundary(timeMaxBoundary) {}
104 // frame boundary
105 double frameTime = (static_cast<double>(m_frames) * m_period) * 1e-6; // in seconds
106
107 return (frameTime >= m_timeMinBoundary) && (frameTime <= m_timeMaxBoundary);
108}
110 m_frames++;
111 if (validFrame())
113}
114void EventProcessor::addEvent(size_t x, size_t y, double tof) {
115 // tof correction
116 if (m_period > 0.0) {
117 tof += m_phase;
118 while (tof > m_period)
119 tof -= m_period;
120 while (tof < 0)
121 tof += m_period;
122 }
123
124 // check if event is in valid range
125 if (!validFrame())
126 return;
127
128 // ToF boundary
129 if ((tof < m_tofMinBoundary) || (tof > m_tofMaxBoundary))
130 return;
131
132 // detector id
133 size_t id = m_stride * x + y;
134
135 // image size
136 if ((y >= m_stride) || (id >= m_roi.size()))
137 return;
138
139 // check if neutron is in region of intreset
140 if (m_roi[id]) {
141 // absolute pulse time in nanoseconds
142 auto frames = static_cast<double>(m_frames);
143 auto frameTime = static_cast<int64_t>(m_period * frames * 1.0e3);
144 int64_t pulse = m_startTime + frameTime;
145
146 addEventImpl(id, pulse, tof);
147 }
148}
149
150// EventCounter
151EventCounter::EventCounter(const std::vector<bool> &roi, const size_t stride, const double period, const double phase,
152 const int64_t startTime, const double tofMinBoundary, const double tofMaxBoundary,
153 const double timeMinBoundary, const double timeMaxBoundary, std::vector<size_t> &eventCounts)
154 : EventProcessor(roi, stride, period, phase, startTime, tofMinBoundary, tofMaxBoundary, timeMinBoundary,
155 timeMaxBoundary),
156 m_eventCounts(eventCounts), m_tofMin(std::numeric_limits<double>::max()),
157 m_tofMax(std::numeric_limits<double>::min()) {}
158size_t EventCounter::numFrames() const { return m_framesValid; }
159double EventCounter::tofMin() const { return m_tofMin <= m_tofMax ? m_tofMin : 0.0; }
160double EventCounter::tofMax() const { return m_tofMin <= m_tofMax ? m_tofMax : 0.0; }
161void EventCounter::addEventImpl(size_t id, int64_t pulse, double tof) {
162 UNUSED_ARG(pulse);
163 if (m_tofMin > tof)
164 m_tofMin = tof;
165 if (m_tofMax < tof)
166 m_tofMax = tof;
167
168 m_eventCounts[id]++;
169}
170
171// EventAssigner
172EventAssigner::EventAssigner(const std::vector<bool> &roi, const size_t stride, const double period, const double phase,
173 const int64_t startTime, const double tofMinBoundary, const double tofMaxBoundary,
174 const double timeMinBoundary, const double timeMaxBoundary,
175 std::vector<EventVector_pt> &eventVectors)
176 : EventProcessor(roi, stride, period, phase, startTime, tofMinBoundary, tofMaxBoundary, timeMinBoundary,
177 timeMaxBoundary),
178 m_eventVectors(eventVectors) {}
179void EventAssigner::addEventImpl(size_t id, int64_t pulse, double tof) {
180 m_eventVectors[id]->emplace_back(tof, Types::Core::DateAndTime(pulse));
181}
182
183// EventAssignerFixedWavelength
184EventAssignerFixedWavelength::EventAssignerFixedWavelength(const std::vector<bool> &roi, const size_t stride,
185 const double wavelength, const double period,
186 const double phase, const int64_t startTime,
187 const double tofMinBoundary, const double tofMaxBoundary,
188 const double timeMinBoundary, const double timeMaxBoundary,
189 std::vector<EventVector_pt> &eventVectors)
190 : EventAssigner(roi, stride, period, phase, startTime, tofMinBoundary, tofMaxBoundary, timeMinBoundary,
191 timeMaxBoundary, eventVectors),
192 m_wavelength(wavelength) {}
193void EventAssignerFixedWavelength::addEventImpl(size_t id, int64_t pulse, double /*tof*/) {
194 m_eventVectors[id]->emplace_back(m_wavelength, Types::Core::DateAndTime(pulse));
195}
196
197// ISISRawOnlyFile
198#ifdef _WIN32
199FastReadOnlyFile::FastReadOnlyFile(const char *filename) {
200 m_handle = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
201}
203void *FastReadOnlyFile::handle() const { return m_handle; }
205 CloseHandle(m_handle);
206 m_handle = NULL;
207}
208bool FastReadOnlyFile::read(void *buffer, uint32_t size) {
209 DWORD bytesRead;
210 return (FALSE != ReadFile(m_handle, buffer, size, &bytesRead, NULL)) && (bytesRead == size);
211}
212bool FastReadOnlyFile::seek(int64_t offset, int whence, int64_t *newPosition) {
213 return FALSE != SetFilePointerEx(m_handle, *(LARGE_INTEGER *)&offset, (LARGE_INTEGER *)newPosition, whence);
214}
215#else
216FastReadOnlyFile::FastReadOnlyFile(const char *filename) { m_handle = fopen(filename, "rb"); }
218void *FastReadOnlyFile::handle() const { return m_handle; }
220 fclose(m_handle);
221 m_handle = nullptr;
222}
223bool FastReadOnlyFile::read(void *buffer, uint32_t size) {
224 return 1 == fread(buffer, static_cast<size_t>(size), 1, m_handle);
225}
226bool FastReadOnlyFile::seek(int64_t offset, int whence, int64_t *newPosition) {
227 return (0 == fseek(m_handle, offset, whence)) &&
228 ((newPosition == nullptr) || (0 <= (*newPosition = static_cast<int64_t>(ftell(m_handle)))));
229}
230#endif
231
232namespace Tar {
233
235 memset(Checksum, ' ', sizeof(Checksum));
236 size_t value = std::accumulate(reinterpret_cast<const char *>(this),
237 reinterpret_cast<const char *>(this) + sizeof(EntryHeader), static_cast<size_t>(0));
238
239 std::ostringstream buffer;
240
241 buffer << std::oct << std::setfill('0') << std::setw(static_cast<int>(sizeof(Checksum)) - 1) << value;
242 std::string string = buffer.str();
243
244 std::copy(string.cbegin(), string.cend(), Checksum);
245 Checksum[string.size()] = 0;
246}
248 std::ostringstream buffer;
249
250 buffer << std::oct << std::setfill('0') << std::setw(static_cast<int>(sizeof(FileSize)) - 1) << value;
251 std::string string = buffer.str();
252
253 std::copy(string.cbegin(), string.cend(), FileSize);
254 FileSize[string.size()] = 0;
255}
257 int64_t result = 0;
258 const char *p = FileSize;
259 for (size_t n = sizeof(FileSize) - 1; n != 0; --n) { // last character is '\0'
260 char c = *p++;
261 if (('0' <= c) && (c <= '9'))
262 result = result * 8 + (c - '0');
263 }
264 return result;
265}
266
267// construction
268File::File(const std::string &path)
269 : m_good(true), m_file(path.c_str()), m_selected(static_cast<size_t>(-1)), m_position(0), m_size(0),
270 m_bufferPosition(0), m_bufferAvailable(0) {
271
272 m_good = m_file.handle() != nullptr;
273 while (m_good) {
274 EntryHeader header;
275 int64_t position;
276
277 m_good &= m_file.read(&header, sizeof(EntryHeader));
278 m_good &= m_file.seek(512 - sizeof(EntryHeader), SEEK_CUR, &position);
279 if (!m_good)
280 break;
281
282 std::string fileName(header.FileName);
283 if (fileName.length() == 0)
284 return;
285
286 FileInfo fileInfo;
287 fileInfo.Offset = position;
288 fileInfo.Size = header.readFileSize();
289
290 if (header.TypeFlag == TarTypeFlag_NormalFile) {
291 m_fileNames.emplace_back(fileName);
292 m_fileInfos.emplace_back(fileInfo);
293 }
294
295 auto offset = static_cast<size_t>(fileInfo.Size % 512);
296 if (offset != 0)
297 offset = 512 - offset;
298
299 m_good &= m_file.seek(fileInfo.Size + offset, SEEK_CUR);
300 }
301}
303 m_good = false;
304 m_file.close();
305 m_fileNames.clear();
306 m_fileInfos.clear();
307 m_selected = static_cast<size_t>(-1);
308 m_position = 0;
309 m_size = 0;
312}
313
314// properties
315bool File::good() const { return m_good; }
316const std::vector<std::string> &File::files() const { return m_fileNames; }
317const std::string &File::selected_name() const { return m_fileNames[m_selected]; }
318int64_t File::selected_position() const { return m_position; }
319int64_t File::selected_size() const { return m_size; }
320
321// methods
322bool File::select(const char *file) {
323 if (!m_good)
324 return false;
325
326 // reset buffer
329
330 auto it = std::find(m_fileNames.cbegin(), m_fileNames.cend(), file);
331 if (it != m_fileNames.cend()) {
332 size_t i = std::distance(m_fileNames.cbegin(), it);
333 const FileInfo &info = m_fileInfos[i];
334
335 m_selected = i;
336 m_position = 0;
337 m_size = info.Size;
338
339 return m_good &= m_file.seek(info.Offset, SEEK_SET);
340 }
341
342 m_selected = static_cast<size_t>(-1);
343 m_position = 0;
344 m_size = 0;
345 return false;
346}
347bool File::skip(uint64_t offset) {
348 if (!m_good || (m_selected == static_cast<size_t>(-1)))
349 return false;
350
351 bool overrun = offset > static_cast<uint64_t>(m_size - m_position);
352 if (overrun)
353 offset = m_size - m_position;
354
355 m_position += offset;
356
357 uint64_t bufferPosition = static_cast<uint64_t>(m_bufferPosition) + offset;
358 if (bufferPosition <= m_bufferAvailable)
359 m_bufferPosition = static_cast<size_t>(bufferPosition);
360 else {
361 m_good &= m_file.seek(bufferPosition - m_bufferAvailable, SEEK_CUR);
362
365 }
366
367 return m_good && !overrun;
368}
369size_t File::read(void *dst, size_t size) {
370 if (!m_good || (m_selected == static_cast<size_t>(-1)))
371 return 0;
372
373 if (static_cast<int64_t>(size) > (m_size - m_position))
374 size = static_cast<size_t>(m_size - m_position);
375
376 auto ptr = reinterpret_cast<uint8_t *>(dst);
377 size_t result = 0;
378
381 if (result > size)
382 result = size;
383
384 memcpy(ptr, m_buffer, result);
385 ptr += result;
386
387 size -= result;
388 m_position += result;
389 m_bufferPosition += result;
390 }
391
392 while (size != 0) {
393 auto bytesToRead = static_cast<uint32_t>(std::min<size_t>(size, std::numeric_limits<uint32_t>::max()));
394
395 m_good &= m_file.read(ptr, bytesToRead);
396 if (!m_good)
397 break;
398
399 ptr += bytesToRead;
400
401 size -= bytesToRead;
402 result += bytesToRead;
403 m_position += bytesToRead;
404 }
405
406 return result;
407}
409 if (!m_good || (m_selected == static_cast<size_t>(-1)))
410 return -1;
411
413 if (m_position >= m_size)
414 return -1;
415
418
419 uint32_t size = static_cast<uint32_t>(std::min<int64_t>(sizeof(m_buffer), m_size - m_position));
420 m_good &= m_file.read(m_buffer, size);
421
422 if (m_good)
423 m_bufferAvailable = size;
424 else
425 return -1;
426 }
427
428 m_position++;
429 return m_buffer[m_bufferPosition++];
430}
431bool File::append(const std::string &path, const std::string &name, const void *buffer, size_t size) {
432 std::unique_ptr<FILE, decltype(&fclose)> handle(fopen(path.c_str(), "rb+"), fclose);
433
434 if (handle == nullptr)
435 return false;
436
437 int64_t lastHeaderPosition = 0;
438 int64_t targetPosition = -1;
439
440 bool fileStatus = true;
441 while (fileStatus) {
442 EntryHeader header;
443 int64_t position;
444
445 lastHeaderPosition = static_cast<int64_t>(ftell(handle.get()));
446
447 fileStatus &= 1 == fread(&header, sizeof(EntryHeader), 1, handle.get());
448 fileStatus &= 0 == fseek(handle.get(), 512 - sizeof(EntryHeader), SEEK_CUR);
449 fileStatus &= 0 <= (position = static_cast<int64_t>(ftell(handle.get())));
450
451 if (!fileStatus)
452 return false;
453
454 std::string fileName(header.FileName);
455 if (fileName.length() == 0)
456 break;
457
458 if (fileName == name)
459 targetPosition = lastHeaderPosition;
460 else if (targetPosition != -1)
461 throw std::runtime_error("format exception"); // it has to be the last file in the archive
462
463 auto fileSize = header.readFileSize();
464
465 auto offset = static_cast<size_t>(fileSize % 512);
466 if (offset != 0)
467 offset = 512 - offset;
468
469 fileStatus &= 0 == fseek(handle.get(), static_cast<long>(fileSize + offset), SEEK_CUR);
470 }
471
472 if (targetPosition < 0)
473 targetPosition = lastHeaderPosition;
474
475 // empty buffer
476 char padding[512];
477 memset(padding, 0, 512);
478
479 // prepare new header
480 EntryHeader header;
481 memset(&header, 0, sizeof(EntryHeader));
482 memcpy(header.FileName, name.c_str(), name.size());
483 memset(header.FileMode, '0', sizeof(header.FileMode) - 1);
484 memset(header.OwnerUserID, '0', sizeof(header.OwnerUserID) - 1);
485 memset(header.OwnerGroupID, '0', sizeof(header.OwnerGroupID) - 1);
486 memset(header.LastModification, '0', sizeof(header.LastModification) - 1);
487
488 header.TypeFlag = TarTypeFlag_NormalFile;
489 header.writeFileSize(size);
490 header.writeChecksum();
491
492 // write header
493 fileStatus &= 0 == fseek(handle.get(), static_cast<long>(targetPosition), SEEK_SET);
494 fileStatus &= 1 == fwrite(&header, sizeof(EntryHeader), 1, handle.get());
495 fileStatus &= 1 == fwrite(padding, 512 - sizeof(EntryHeader), 1, handle.get());
496
497 // write content
498 fileStatus &= 1 == fwrite(buffer, size, 1, handle.get());
499
500 // write padding
501 auto offset = static_cast<size_t>(size % 512);
502 if (offset != 0) {
503 offset = 512 - offset;
504
505 fileStatus &= 1 == fwrite(padding, offset, 1, handle.get());
506 }
507
508 // write final
509 fileStatus &= 1 == fwrite(padding, 512, 1, handle.get());
510
511 return fileStatus;
512}
513
514} // namespace Tar
515
516namespace Anxs {
517
518int64_t epochRelDateTimeBase(int64_t epochInNanoSeconds) {
519 auto retval = epochInNanoSeconds - static_cast<int64_t>(Types::Core::DateAndTime::EPOCH_DIFF) * 1'000'000'000;
520 return retval;
521}
522
523std::string extractWorkspaceTitle(const std::string &nxsFile) {
524 namespace fs = boost::filesystem;
525 fs::path p = nxsFile;
526 for (; !p.extension().empty();)
527 p = p.stem();
528 return p.generic_string();
529}
530
531// load nx dataset
532template <class T> bool loadNXDataSet(const Nexus::NXEntry &entry, const std::string &path, T &value, int index) {
533 try {
534 Nexus::NXDataSetTyped<T> dataSet = entry.openNXDataSet<T>(path);
535 dataSet.load();
536
537 // if negative index go from the end
538 if (dataSet.rank() == 0) {
539 value = dataSet[0];
540 return true;
541 } else {
542 if (index < 0) {
543 auto N = dataSet.dim0();
544 value = dataSet[N + index];
545 } else {
546 value = dataSet[index];
547 }
548 return true;
549 }
550 } catch (std::runtime_error &) {
551 return false;
552 }
553}
554
555bool loadNXString(const Nexus::NXEntry &entry, const std::string &path, std::string &value) {
556 try {
557 Nexus::NXChar dataSet = entry.openNXChar(path);
558 dataSet.load();
559
560 value = std::string(dataSet(), dataSet.dim0());
561 return true;
562 } catch (std::runtime_error &) {
563 return false;
564 }
565}
566
567bool isTimedDataSet(const Nexus::NXEntry &entry, const std::string &path) {
568 auto newEntry = entry.openNXGroup(path);
569 auto datasets = newEntry.datasets();
570 auto valid = (datasets.size() == 2 && newEntry.containsDataSet("time") && newEntry.containsDataSet("value"));
571 return valid;
572}
573
574// Extract the start and end time in nsecs from the nexus file
575// based on entry/scan_dataset/[time, value]
576//
577// The time is the start time value is duration in nsec for each dataset
578//
579std::pair<uint64_t, uint64_t> getTimeScanLimits(const Nexus::NXEntry &entry, int datasetIx) {
580
581 auto timestamp = entry.openNXDataSet<uint64_t>("scan_dataset/time");
582 timestamp.load();
583 auto offset = entry.openNXDataSet<int64_t>("scan_dataset/value");
584 offset.load();
585 try {
586 auto start = timestamp[datasetIx];
587 auto end = start + offset[datasetIx];
588 return {start, end};
589 } catch (std::runtime_error &) {
590 return {0, 0};
591 }
592}
593
594// Extract the start and end time in nsecs from the nexus file
595// based on entry/scan_dataset/[time, value]
596//
597// The time is the start time value is duration in nsec for each dataset
598//
599std::pair<uint64_t, uint64_t> getHMScanLimits(const Nexus::NXEntry &entry, int datasetIx) {
600
601 auto timestamp = entry.openNXDataSet<uint64_t>("hmscan/time");
602 timestamp.load();
603 auto offset = entry.openNXDataSet<int64_t>("hmscan/value");
604 offset.load();
605 try {
606 auto start = timestamp[datasetIx];
607 auto end = start + offset[datasetIx];
608 return {start, end};
609 } catch (std::runtime_error &) {
610 return {0, 0};
611 }
612}
613
614// Extract the relevant timestamped data. Get the timestamp first to
615// determine the index limits (it assumed the timestamp is ordered).
616// Then extract the value from that range.
617// The start index is the first entry where the timestamp is less than
618// or equal to to the start time. The start index may occur before the
619// startT time but it is the parameter value at the start time as all
620// subsequenet values occur after the start time. This logic is needed
621// as the recorded value is only captured on the change in value an if
622// the value did not change in the window there would no logged value
623// in the period.
624
625template <typename T>
626uint64_t extractTimedDataSet(const Nexus::NXEntry &entry, const std::string &path, uint64_t startTime, uint64_t endTime,
627 std::vector<uint64_t> &times, std::vector<T> &events, std::string &units) {
628
629 // Check if entry is a group and contains the expected datasets
630 // otherwise extract the dataset value at the start time and return 1
631 if (isTimedDataSet(entry, path)) {
632 auto timeStamp = entry.openNXDataSet<uint64_t>(path + "/time");
633 timeStamp.load();
634 size_t maxn = timeStamp.size();
635 uint64_t startIx{0}, endIx{0};
636 auto itt = timeStamp();
637 for (size_t i = 0; i < maxn; i++) {
638 auto v = itt[i];
639 if (v <= startTime)
640 startIx = i;
641 if (v < endTime)
642 endIx = i + 1;
643 }
644 times.assign(itt + startIx, itt + endIx);
645
646 auto values = entry.openNXDataSet<T>(path + "/value");
647 units = values.attributes("units");
648 values.load();
649 auto itv = values();
650 events.assign(itv + startIx, itv + endIx);
651
652 return endIx - startIx;
653 } else {
654 T value{0};
655 if (loadNXDataSet<T>(entry, path, value, -1)) {
656 times.push_back(startTime);
657 events.push_back(value);
658 return 1;
659 }
660 }
661 return 0;
662}
663
664template <typename T>
665bool extractTimedDataSet(const Nexus::NXEntry &entry, const std::string &path, uint64_t startTime, uint64_t endTime,
666 ScanLog valueOption, uint64_t &eventTime, T &eventValue, std::string &units) {
667 eventTime = 0;
668 eventValue = 0;
669 std::vector<uint64_t> times;
670 std::vector<T> values;
671 auto n = extractTimedDataSet<T>(entry, path, startTime, endTime, times, values, units);
672 if (n == 0)
673 return false;
674
675 bool retn = true;
676 switch (valueOption) {
677 case ScanLog::Mean:
678 eventValue = std::accumulate(values.cbegin(), values.cend(), T{0}) / static_cast<T>(n);
679 eventTime = std::accumulate(times.cbegin(), times.cend(), uint64_t{0}) / n;
680 break;
681 case ScanLog::Start:
682 eventValue = values[0];
683 eventTime = times[0];
684 break;
685 case ScanLog::End:
686 eventValue = values[n - 1];
687 eventTime = times[n - 1];
688 break;
689 default:
690 retn = false;
691 }
692 return retn;
693}
694
695void ReadEventData(ProgressTracker &prog, const Nexus::NXEntry &entry, BaseEventProcessor *handler, uint64_t start_nsec,
696 uint64_t end_nsec, const std::string &neutron_path, int tube_resolution) {
697
698 // the detector event time zero is the actual chopper time and all the events are
699 // relative to this base
700
701 // Get the event index, base values and values but check if there is data available
702 auto eventID = entry.openNXDataSet<uint32_t>(neutron_path + "/event_id");
703 if (eventID.dim0() == 0)
704 return;
705 eventID.load();
706 auto eventIndex = entry.openNXDataSet<uint32_t>(neutron_path + "/event_time_zero_index");
707 eventIndex.load();
708 auto zeroOffset = entry.openNXDataSet<uint64_t>(neutron_path + "/event_time_zero");
709 zeroOffset.load();
710 auto offsetValues = entry.openNXDataSet<uint32_t>(neutron_path + "/event_time_offset");
711 offsetValues.load();
712 uint32_t numPulses = static_cast<uint32_t>(eventIndex.size());
713 uint32_t totalEvents = static_cast<uint32_t>(offsetValues.size());
714
715 prog.setTarget(numPulses);
716
717 // The chopper times are monotonically increasing but there may be duplicate
718 // pulse times when a 'efu' buffer is full mid pulse. In this case the buffer
719 // is sent but the next buffer uses the same pulse time. Only send the frame
720 // event when it changes.
721
722 uint64_t lastFrameTS{0};
723
724 // Run through the data and forward the event data if the pulse time occurs between
725 // start and end time. To be clear the start and end time relates to the pulse times.
726 for (uint32_t ix = 0; ix < numPulses; ix++) {
727 auto pulseTime = zeroOffset[ix];
728 if (start_nsec <= pulseTime && pulseTime < end_nsec) {
729 if (pulseTime > lastFrameTS) {
730 handler->newFrame();
731 lastFrameTS = pulseTime;
732 }
733 auto baseIndex = eventIndex[ix];
734 auto lastIndex = (ix + 1 < numPulses ? eventIndex[ix + 1] : totalEvents);
735 for (uint32_t j = baseIndex; j < lastIndex; j++) {
736 // convert tof to microseconds as double and pixel as (x,y)
737 // and send to handler
738 double tof = offsetValues[j] * 1.0e-3;
739 auto pixel = eventID[j];
740 size_t y = pixel % tube_resolution;
741 size_t x = (pixel - y) / tube_resolution;
742 handler->addEvent(x, y, tof);
743 }
744 }
745 prog.update(ix);
746 }
747}
748
749// template instantiation
750template bool loadNXDataSet<float>(const Nexus::NXEntry &entry, const std::string &path, float &value, int index);
751template bool loadNXDataSet<double>(const Nexus::NXEntry &entry, const std::string &path, double &value, int index);
752template bool loadNXDataSet<int>(const Nexus::NXEntry &entry, const std::string &path, int &value, int index);
753template bool loadNXDataSet<int64_t>(const Nexus::NXEntry &entry, const std::string &path, int64_t &value, int index);
754template bool loadNXDataSet<uint64_t>(const Nexus::NXEntry &entry, const std::string &path, uint64_t &value, int index);
755template uint64_t extractTimedDataSet<float>(const Nexus::NXEntry &entry, const std::string &path, uint64_t startTime,
756 uint64_t endTime, std::vector<uint64_t> &times, std::vector<float> &events,
757 std::string &units);
758template uint64_t extractTimedDataSet<double>(const Nexus::NXEntry &entry, const std::string &path, uint64_t startTime,
759 uint64_t endTime, std::vector<uint64_t> &times,
760 std::vector<double> &events, std::string &units);
761template uint64_t extractTimedDataSet<int>(const Nexus::NXEntry &entry, const std::string &path, uint64_t startTime,
762 uint64_t endTime, std::vector<uint64_t> &times, std::vector<int> &events,
763 std::string &units);
764
765template bool extractTimedDataSet<float>(const Nexus::NXEntry &entry, const std::string &path, uint64_t startTime,
766 uint64_t endTime, ScanLog valueOption, uint64_t &eventTime, float &eventValue,
767 std::string &units);
768template bool extractTimedDataSet<double>(const Nexus::NXEntry &entry, const std::string &path, uint64_t startTime,
769 uint64_t endTime, ScanLog valueOption, uint64_t &eventTime,
770 double &eventValue, std::string &units);
771template bool extractTimedDataSet<int>(const Nexus::NXEntry &entry, const std::string &path, uint64_t startTime,
772 uint64_t endTime, ScanLog valueOption, uint64_t &eventTime, int &eventValue,
773 std::string &units);
774template bool extractTimedDataSet<int64_t>(const Nexus::NXEntry &entry, const std::string &path, uint64_t startTime,
775 uint64_t endTime, ScanLog valueOption, uint64_t &eventTime,
776 int64_t &eventValue, std::string &units);
777
778} // namespace Anxs
779
780} // namespace Mantid::DataHandling::ANSTO
std::string name
Definition Run.cpp:60
std::vector< uint32_t > m_count
sum of all events seen in an individual bin
size_t m_size
Maximum size of the store.
double value
The value of the point.
Definition FitMW.cpp:51
double position
Definition GetAllEi.cpp:154
std::map< DeltaEMode::Type, std::string > index
#define TarTypeFlag_NormalFile
int count
counter
Definition Matrix.cpp:37
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition System.h:44
Helper class for reporting progress from algorithms.
Definition Progress.h:25
void doReport(const std::string &msg="") override
Actually do the reporting, without changing the loop counter.
Definition Progress.cpp:70
abstract base class for processing events as they are read from the file
virtual void addEvent(size_t x, size_t y, double tof)=0
EventAssignerFixedWavelength(const std::vector< bool > &roi, const size_t stride, const double wavelength, const double period, const double phase, const int64_t startTime, const double tofMinBoundary, const double tofMaxBoundary, const double timeMinBoundary, const double timeMaxBoundary, std::vector< EventVector_pt > &eventVectors)
void addEventImpl(size_t id, int64_t pulse, double tof) override
EventAssigner(const std::vector< bool > &roi, const size_t stride, const double period, const double phase, int64_t startTime, const double tofMinBoundary, const double tofMaxBoundary, const double timeMinBoundary, const double timeMaxBoundary, std::vector< EventVector_pt > &eventVectors)
void addEventImpl(size_t id, int64_t pulse, double tof) override
std::vector< EventVector_pt > & m_eventVectors
void addEventImpl(size_t id, int64_t pulse, double tof) override
EventCounter(const std::vector< bool > &roi, const size_t stride, const double period, const double phase, const int64_t startTime, const double tofMinBoundary, const double tofMaxBoundary, const double timeMinBoundary, const double timeMaxBoundary, std::vector< size_t > &eventCounts)
void addEvent(size_t x, size_t y, double tof) override
virtual void addEventImpl(size_t id, int64_t pulse, double tof)=0
EventProcessor(const std::vector< bool > &roi, size_t stride, const double period, const double phase, const int64_t startTime, const double tofMinBoundary, const double tofMaxBoundary, const double timeMinBoundary, const double timeMaxBoundary)
bool seek(int64_t offset, int whence, int64_t *newPosition=nullptr)
helper class to keep track of progress
ProgressTracker(API::Progress &progBar, const char *msg, int64_t target, size_t count)
std::vector< std::string > m_fileNames
const std::string & selected_name() const
size_t read(void *dst, size_t size)
const std::vector< std::string > & files() const
static bool append(const std::string &path, const std::string &name, const void *buffer, size_t size)
void reportIncrement(int inc, const std::string &msg="")
Sends the progress notification and increment the loop counter by more than one.
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
std::vector< NXInfo > & datasets() const
Returns a list of all datasets in this NXClass.
std::vector< NXClassInfo > & groups() const
Returns a list of all classes (or groups) in this NXClass.
NXClass openNXGroup(const std::string &name) const
Creates and opens an arbitrary (non-standard) class (group).
NXChar openNXChar(const std::string &name) const
Creates and opens a char dataset.
NXDataSetTyped< T > openNXDataSet(const std::string &name) const
Templated method for creating datasets.
Templated class implementation of NXDataSet.
void load()
Read all of the datablock in.
dimsize_t dim0() const
Returns the number of elements along the first dimension.
std::size_t rank() const
Returns the rank (number of dimensions) of the data. The maximum is 4.
Implements NXentry Nexus class.
template bool loadNXDataSet< float >(const Nexus::NXEntry &entry, const std::string &path, float &value, int index)
template bool loadNXDataSet< int >(const Nexus::NXEntry &entry, const std::string &path, int &value, int index)
template bool loadNXDataSet< double >(const Nexus::NXEntry &entry, const std::string &path, double &value, int index)
template bool extractTimedDataSet< int64_t >(const Nexus::NXEntry &entry, const std::string &path, uint64_t startTime, uint64_t endTime, ScanLog valueOption, uint64_t &eventTime, int64_t &eventValue, std::string &units)
bool isTimedDataSet(const Nexus::NXEntry &entry, const std::string &path)
template uint64_t extractTimedDataSet< float >(const Nexus::NXEntry &entry, const std::string &path, uint64_t startTime, uint64_t endTime, std::vector< uint64_t > &times, std::vector< float > &events, std::string &units)
std::string extractWorkspaceTitle(const std::string &nxsFile)
bool loadNXString(const Nexus::NXEntry &entry, const std::string &path, std::string &value)
int64_t epochRelDateTimeBase(int64_t epochInNanoSeconds)
template bool loadNXDataSet< uint64_t >(const Nexus::NXEntry &entry, const std::string &path, uint64_t &value, int index)
bool loadNXDataSet(const Nexus::NXEntry &entry, const std::string &path, T &value, int index)
template uint64_t extractTimedDataSet< int >(const Nexus::NXEntry &entry, const std::string &path, uint64_t startTime, uint64_t endTime, std::vector< uint64_t > &times, std::vector< int > &events, std::string &units)
std::pair< uint64_t, uint64_t > getHMScanLimits(const Nexus::NXEntry &entry, int datasetIx)
template uint64_t extractTimedDataSet< double >(const Nexus::NXEntry &entry, const std::string &path, uint64_t startTime, uint64_t endTime, std::vector< uint64_t > &times, std::vector< double > &events, std::string &units)
uint64_t extractTimedDataSet(const Nexus::NXEntry &entry, const std::string &path, uint64_t startTime, uint64_t endTime, std::vector< uint64_t > &times, std::vector< T > &events, std::string &units)
void ReadEventData(ProgressTracker &prog, const Nexus::NXEntry &entry, BaseEventProcessor *handler, uint64_t start_nsec, uint64_t end_nsec, const std::string &neutron_path, int tube_resolution=1024)
std::pair< uint64_t, uint64_t > getTimeScanLimits(const Nexus::NXEntry &entry, int datasetIx)
template bool loadNXDataSet< int64_t >(const Nexus::NXEntry &entry, const std::string &path, int64_t &value, int index)
std::vector< std::string > filterGroups(const Nexus::NXEntry &entry, const std::string &groupAddress, const std::string &regexFilter)
extract groups from a group that match a regex filter
std::vector< std::string > filterDatasets(const Nexus::NXEntry &entry, const std::string &groupAddress, const std::string &regexFilter)
extract datasets from a group that match a regex filter
NXDataSetTyped< char > NXChar
The char dataset type.
STL namespace.