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 +
16
17#include <numeric>
18
20
21// ProgressTracker
22ProgressTracker::ProgressTracker(API::Progress &progBar, const char *msg, int64_t target, size_t count)
23 : m_msg(msg), m_count(count), m_step(target / count), m_next(m_step), m_progBar(progBar) {
24
26}
29 while (m_next <= position) {
31
32 switch (m_count) {
33 case 0:
34 return;
35
36 case 1:
37 m_count = 0;
38 m_next = std::numeric_limits<int64_t>::max();
39 return;
40
41 default:
42 m_count--;
43 m_next += m_step;
44 }
45 }
46}
48 if (m_count != 0) {
50 m_count = 0;
51 }
52}
53
54// EventProcessor
55EventProcessor::EventProcessor(const std::vector<bool> &roi, const size_t stride, const double period,
56 const double phase, const int64_t startTime, const double tofMinBoundary,
57 const double tofMaxBoundary, const double timeMinBoundary, const double timeMaxBoundary)
58 : m_roi(roi), m_stride(stride), m_frames(0), m_framesValid(0), m_startTime(startTime), m_period(period),
59 m_phase(phase), m_tofMinBoundary(tofMinBoundary), m_tofMaxBoundary(tofMaxBoundary),
60 m_timeMinBoundary(timeMinBoundary), m_timeMaxBoundary(timeMaxBoundary) {}
62 // frame boundary
63 double frameTime = (static_cast<double>(m_frames) * m_period) * 1e-6; // in seconds
64
65 return (frameTime >= m_timeMinBoundary) && (frameTime <= m_timeMaxBoundary);
66}
68 m_frames++;
69 if (validFrame())
71}
72void EventProcessor::addEvent(size_t x, size_t y, double tof) {
73 // tof correction
74 if (m_period > 0.0) {
75 tof += m_phase;
76 while (tof > m_period)
77 tof -= m_period;
78 while (tof < 0)
79 tof += m_period;
80 }
81
82 // check if event is in valid range
83 if (!validFrame())
84 return;
85
86 // ToF boundary
87 if ((tof < m_tofMinBoundary) && (tof > m_tofMaxBoundary))
88 return;
89
90 // detector id
91 size_t id = m_stride * x + y;
92
93 // image size
94 if ((y >= m_stride) || (id >= m_roi.size()))
95 return;
96
97 // check if neutron is in region of intreset
98 if (m_roi[id]) {
99 // absolute pulse time in nanoseconds
100 auto frames = static_cast<double>(m_frames);
101 auto frameTime = static_cast<int64_t>(m_period * frames * 1.0e3);
102 int64_t pulse = m_startTime + frameTime;
103
104 addEventImpl(id, pulse, tof);
105 }
106}
107
108// EventCounter
109EventCounter::EventCounter(const std::vector<bool> &roi, const size_t stride, const double period, const double phase,
110 const int64_t startTime, const double tofMinBoundary, const double tofMaxBoundary,
111 const double timeMinBoundary, const double timeMaxBoundary, std::vector<size_t> &eventCounts)
112 : EventProcessor(roi, stride, period, phase, startTime, tofMinBoundary, tofMaxBoundary, timeMinBoundary,
113 timeMaxBoundary),
114 m_eventCounts(eventCounts), m_tofMin(std::numeric_limits<double>::max()),
115 m_tofMax(std::numeric_limits<double>::min()) {}
116size_t EventCounter::numFrames() const { return m_framesValid; }
117double EventCounter::tofMin() const { return m_tofMin <= m_tofMax ? m_tofMin : 0.0; }
118double EventCounter::tofMax() const { return m_tofMin <= m_tofMax ? m_tofMax : 0.0; }
119void EventCounter::addEventImpl(size_t id, int64_t pulse, double tof) {
120 UNUSED_ARG(pulse);
121 if (m_tofMin > tof)
122 m_tofMin = tof;
123 if (m_tofMax < tof)
124 m_tofMax = tof;
125
126 m_eventCounts[id]++;
127}
128
129// EventAssigner
130EventAssigner::EventAssigner(const std::vector<bool> &roi, const size_t stride, const double period, const double phase,
131 const int64_t startTime, const double tofMinBoundary, const double tofMaxBoundary,
132 const double timeMinBoundary, const double timeMaxBoundary,
133 std::vector<EventVector_pt> &eventVectors)
134 : EventProcessor(roi, stride, period, phase, startTime, tofMinBoundary, tofMaxBoundary, timeMinBoundary,
135 timeMaxBoundary),
136 m_eventVectors(eventVectors) {}
137void EventAssigner::addEventImpl(size_t id, int64_t pulse, double tof) {
138 m_eventVectors[id]->emplace_back(tof, Types::Core::DateAndTime(pulse));
139}
140
141// EventAssignerFixedWavelength
142EventAssignerFixedWavelength::EventAssignerFixedWavelength(const std::vector<bool> &roi, const size_t stride,
143 const double wavelength, const double period,
144 const double phase, const int64_t startTime,
145 const double tofMinBoundary, const double tofMaxBoundary,
146 const double timeMinBoundary, const double timeMaxBoundary,
147 std::vector<EventVector_pt> &eventVectors)
148 : EventAssigner(roi, stride, period, phase, startTime, tofMinBoundary, tofMaxBoundary, timeMinBoundary,
149 timeMaxBoundary, eventVectors),
150 m_wavelength(wavelength) {}
151void EventAssignerFixedWavelength::addEventImpl(size_t id, int64_t pulse, double tof) {
152 UNUSED_ARG(pulse);
153 UNUSED_ARG(tof);
154 m_eventVectors[id]->emplace_back(m_wavelength);
155}
156
157// ISISRawOnlyFile
158#ifdef _WIN32
159FastReadOnlyFile::FastReadOnlyFile(const char *filename) {
160 m_handle = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
161}
163void *FastReadOnlyFile::handle() const { return m_handle; }
165 CloseHandle(m_handle);
166 m_handle = NULL;
167}
168bool FastReadOnlyFile::read(void *buffer, uint32_t size) {
169 DWORD bytesRead;
170 return (FALSE != ReadFile(m_handle, buffer, size, &bytesRead, NULL)) && (bytesRead == size);
171}
172bool FastReadOnlyFile::seek(int64_t offset, int whence, int64_t *newPosition) {
173 return FALSE != SetFilePointerEx(m_handle, *(LARGE_INTEGER *)&offset, (LARGE_INTEGER *)newPosition, whence);
174}
175#else
176FastReadOnlyFile::FastReadOnlyFile(const char *filename) { m_handle = fopen(filename, "rb"); }
178void *FastReadOnlyFile::handle() const { return m_handle; }
180 fclose(m_handle);
181 m_handle = nullptr;
182}
183bool FastReadOnlyFile::read(void *buffer, uint32_t size) {
184 return 1 == fread(buffer, static_cast<size_t>(size), 1, m_handle);
185}
186bool FastReadOnlyFile::seek(int64_t offset, int whence, int64_t *newPosition) {
187 return (0 == fseek(m_handle, offset, whence)) &&
188 ((newPosition == nullptr) || (0 <= (*newPosition = static_cast<int64_t>(ftell(m_handle)))));
189}
190#endif
191
192namespace Tar {
193
195 memset(Checksum, ' ', sizeof(Checksum));
196 size_t value = std::accumulate((const char *)this, (const char *)this + sizeof(EntryHeader), (size_t)0);
197
198 std::ostringstream buffer;
199
200 buffer << std::oct << std::setfill('0') << std::setw(static_cast<int>(sizeof(Checksum)) - 1) << value;
201 std::string string = buffer.str();
202
203 std::copy(string.cbegin(), string.cend(), Checksum);
204 Checksum[string.size()] = 0;
205}
207 std::ostringstream buffer;
208
209 buffer << std::oct << std::setfill('0') << std::setw(static_cast<int>(sizeof(FileSize)) - 1) << value;
210 std::string string = buffer.str();
211
212 std::copy(string.cbegin(), string.cend(), FileSize);
213 FileSize[string.size()] = 0;
214}
216 int64_t result = 0;
217 const char *p = FileSize;
218 for (size_t n = sizeof(FileSize) - 1; n != 0; --n) { // last character is '\0'
219 char c = *p++;
220 if (('0' <= c) && (c <= '9'))
221 result = result * 8 + (c - '0');
222 }
223 return result;
224}
225
226// construction
227File::File(const std::string &path)
228 : m_good(true), m_file(path.c_str()), m_selected(static_cast<size_t>(-1)), m_position(0), m_size(0),
229 m_bufferPosition(0), m_bufferAvailable(0) {
230
231 m_good = m_file.handle() != nullptr;
232 while (m_good) {
233 EntryHeader header;
234 int64_t position;
235
236 m_good &= m_file.read(&header, sizeof(EntryHeader));
237 m_good &= m_file.seek(512 - sizeof(EntryHeader), SEEK_CUR, &position);
238 if (!m_good)
239 break;
240
241 std::string fileName(header.FileName);
242 if (fileName.length() == 0)
243 return;
244
245 FileInfo fileInfo;
246 fileInfo.Offset = position;
247 fileInfo.Size = header.readFileSize();
248
249 if (header.TypeFlag == TarTypeFlag_NormalFile) {
250 m_fileNames.emplace_back(fileName);
251 m_fileInfos.emplace_back(fileInfo);
252 }
253
254 auto offset = static_cast<size_t>(fileInfo.Size % 512);
255 if (offset != 0)
256 offset = 512 - offset;
257
258 m_good &= m_file.seek(fileInfo.Size + offset, SEEK_CUR);
259 }
260}
262 m_good = false;
263 m_file.close();
264 m_fileNames.clear();
265 m_fileInfos.clear();
266 m_selected = static_cast<size_t>(-1);
267 m_position = 0;
268 m_size = 0;
271}
272
273// properties
274bool File::good() const { return m_good; }
275const std::vector<std::string> &File::files() const { return m_fileNames; }
276const std::string &File::selected_name() const { return m_fileNames[m_selected]; }
277int64_t File::selected_position() const { return m_position; }
278int64_t File::selected_size() const { return m_size; }
279
280// methods
281bool File::select(const char *file) {
282 if (!m_good)
283 return false;
284
285 // reset buffer
288
289 for (size_t i = 0; i != m_fileNames.size(); i++)
290 if (m_fileNames[i] == file) {
291 const FileInfo &info = m_fileInfos[i];
292
293 m_selected = i;
294 m_position = 0;
295 m_size = info.Size;
296
297 return m_good &= m_file.seek(info.Offset, SEEK_SET);
298 }
299
300 m_selected = static_cast<size_t>(-1);
301 m_position = 0;
302 m_size = 0;
303 return false;
304}
305bool File::skip(uint64_t offset) {
306 if (!m_good || (m_selected == static_cast<size_t>(-1)))
307 return false;
308
309 bool overrun = offset > static_cast<uint64_t>(m_size - m_position);
310 if (overrun)
311 offset = m_size - m_position;
312
313 m_position += offset;
314
315 uint64_t bufferPosition = static_cast<uint64_t>(m_bufferPosition) + offset;
316 if (bufferPosition <= m_bufferAvailable)
317 m_bufferPosition = static_cast<size_t>(bufferPosition);
318 else {
319 m_good &= m_file.seek(bufferPosition - m_bufferAvailable, SEEK_CUR);
320
323 }
324
325 return m_good && !overrun;
326}
327size_t File::read(void *dst, size_t size) {
328 if (!m_good || (m_selected == static_cast<size_t>(-1)))
329 return 0;
330
331 if (static_cast<int64_t>(size) > (m_size - m_position))
332 size = static_cast<size_t>(m_size - m_position);
333
334 auto ptr = reinterpret_cast<uint8_t *>(dst);
335 size_t result = 0;
336
339 if (result > size)
340 result = size;
341
342 memcpy(ptr, m_buffer, result);
343 ptr += result;
344
345 size -= result;
346 m_position += result;
347 m_bufferPosition += result;
348 }
349
350 while (size != 0) {
351 auto bytesToRead = static_cast<uint32_t>(std::min<size_t>(size, std::numeric_limits<uint32_t>::max()));
352
353 m_good &= m_file.read(ptr, bytesToRead);
354 if (!m_good)
355 break;
356
357 ptr += bytesToRead;
358
359 size -= bytesToRead;
360 result += bytesToRead;
361 m_position += bytesToRead;
362 }
363
364 return result;
365}
367 if (!m_good || (m_selected == static_cast<size_t>(-1)))
368 return -1;
369
371 if (m_position >= m_size)
372 return -1;
373
376
377 uint32_t size = static_cast<uint32_t>(std::min<int64_t>(sizeof(m_buffer), m_size - m_position));
378 m_good &= m_file.read(m_buffer, size);
379
380 if (m_good)
381 m_bufferAvailable = size;
382 else
383 return -1;
384 }
385
386 m_position++;
387 return m_buffer[m_bufferPosition++];
388}
389bool File::append(const std::string &path, const std::string &name, const void *buffer, size_t size) {
390 std::unique_ptr<FILE, decltype(&fclose)> handle(fopen(path.c_str(), "rb+"), fclose);
391
392 bool good = handle != nullptr;
393 int64_t lastHeaderPosition = 0;
394 int64_t targetPosition = -1;
395
396 while (good) {
397 EntryHeader header;
398 int64_t position;
399
400 lastHeaderPosition = static_cast<int64_t>(ftell(handle.get()));
401
402 good &= 1 == fread(&header, sizeof(EntryHeader), 1, handle.get());
403 good &= 0 == fseek(handle.get(), 512 - sizeof(EntryHeader), SEEK_CUR);
404 good &= 0 <= (position = static_cast<int64_t>(ftell(handle.get())));
405
406 if (!good)
407 return false;
408
409 std::string fileName(header.FileName);
410 if (fileName.length() == 0)
411 break;
412
413 if (fileName == name)
414 targetPosition = lastHeaderPosition;
415 else if (targetPosition != -1)
416 throw std::runtime_error("format exception"); // it has to be the last file in the archive
417
418 FileInfo fileInfo;
419 fileInfo.Offset = position;
420 fileInfo.Size = header.readFileSize();
421
422 auto offset = static_cast<size_t>(fileInfo.Size % 512);
423 if (offset != 0)
424 offset = 512 - offset;
425
426 good &= 0 == fseek(handle.get(), static_cast<long>(fileInfo.Size + offset), SEEK_CUR);
427 }
428
429 if (!good)
430 return false;
431
432 if (targetPosition < 0)
433 targetPosition = lastHeaderPosition;
434
435 // empty buffer
436 char padding[512];
437 memset(padding, 0, 512);
438
439 // prepare new header
440 EntryHeader header;
441 memset(&header, 0, sizeof(EntryHeader));
442 memcpy(header.FileName, name.c_str(), name.size());
443 memset(header.FileMode, '0', sizeof(header.FileMode) - 1);
444 memset(header.OwnerUserID, '0', sizeof(header.OwnerUserID) - 1);
445 memset(header.OwnerGroupID, '0', sizeof(header.OwnerGroupID) - 1);
446 memset(header.LastModification, '0', sizeof(header.LastModification) - 1);
447
448 header.TypeFlag = TarTypeFlag_NormalFile;
449 header.writeFileSize(size);
450 header.writeChecksum();
451
452 // write header
453 good &= 0 == fseek(handle.get(), static_cast<long>(targetPosition), SEEK_SET);
454 good &= 1 == fwrite(&header, sizeof(EntryHeader), 1, handle.get());
455 good &= 1 == fwrite(padding, 512 - sizeof(EntryHeader), 1, handle.get());
456
457 // write content
458 good &= 1 == fwrite(buffer, size, 1, handle.get());
459
460 // write padding
461 auto offset = static_cast<size_t>(size % 512);
462 if (offset != 0) {
463 offset = 512 - offset;
464
465 good &= 1 == fwrite(padding, offset, 1, handle.get());
466 }
467
468 // write final
469 good &= 1 == fwrite(padding, 512, 1, handle.get());
470
471 return good;
472}
473
474} // namespace Tar
475} // namespace Mantid::DataHandling::ANSTO
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
#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:64
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
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)
virtual void addEventImpl(size_t id, int64_t pulse, double tof)=0
void addEvent(size_t x, size_t y, double tof)
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)
bool read(void *buffer, uint32_t size)
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.
Definition: ProgressBase.h:51
STL namespace.