16#include <boost/filesystem.hpp>
25 const std::string ®exFilter) {
26 std::vector<std::string> fvalues;
29 for (
auto nxi : datasets) {
30 if (std::regex_match(nxi.nxname, std::regex(regexFilter))) {
31 fvalues.emplace_back(nxi.nxname);
40 const std::string ®exFilter) {
41 std::vector<std::string> fvalues;
44 for (
auto nxi : groups) {
45 if (std::regex_match(nxi.nxname, std::regex(regexFilter))) {
46 fvalues.emplace_back(nxi.nxname);
55 : m_msg(msg),
m_count(
count), m_step(target /
count), m_next(m_step), m_progBar(progBar) {
70 m_next = std::numeric_limits<int64_t>::max();
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) {}
142 auto frames =
static_cast<double>(
m_frames);
143 auto frameTime =
static_cast<int64_t
>(
m_period * frames * 1.0e3);
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,
156 m_eventCounts(eventCounts), m_tofMin(
std::numeric_limits<double>::max()),
157 m_tofMax(
std::numeric_limits<double>::min()) {}
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,
178 m_eventVectors(eventVectors) {}
180 m_eventVectors[id]->emplace_back(tof, Types::Core::DateAndTime(pulse));
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) {}
200 m_handle = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
210 return (FALSE != ReadFile(
m_handle, buffer, size, &bytesRead, NULL)) && (bytesRead == size);
213 return FALSE != SetFilePointerEx(
m_handle, *(LARGE_INTEGER *)&offset, (LARGE_INTEGER *)newPosition, whence);
224 return 1 == fread(buffer,
static_cast<size_t>(size), 1,
m_handle);
227 return (0 == fseek(
m_handle, offset, whence)) &&
228 ((newPosition ==
nullptr) || (0 <= (*newPosition =
static_cast<int64_t
>(ftell(
m_handle)))));
236 size_t value = std::accumulate(
reinterpret_cast<const char *
>(
this),
237 reinterpret_cast<const char *
>(
this) +
sizeof(
EntryHeader),
static_cast<size_t>(0));
239 std::ostringstream buffer;
241 buffer << std::oct << std::setfill('0') << std::setw(static_cast<int>(
sizeof(
Checksum)) - 1) <<
value;
242 std::string
string = buffer.str();
244 std::copy(
string.cbegin(),
string.cend(),
Checksum);
248 std::ostringstream buffer;
250 buffer << std::oct << std::setfill('0') << std::setw(static_cast<int>(
sizeof(
FileSize)) - 1) <<
value;
251 std::string
string = buffer.str();
253 std::copy(
string.cbegin(),
string.cend(),
FileSize);
259 for (
size_t n =
sizeof(
FileSize) - 1;
n != 0; --
n) {
261 if ((
'0' <= c) && (c <=
'9'))
262 result = result * 8 + (c -
'0');
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) {
282 std::string fileName(header.FileName);
283 if (fileName.length() == 0)
288 fileInfo.
Size = header.readFileSize();
295 auto offset =
static_cast<size_t>(fileInfo.
Size % 512);
297 offset = 512 - offset;
332 size_t i = std::distance(
m_fileNames.cbegin(), it);
367 return m_good && !overrun;
376 auto ptr =
reinterpret_cast<uint8_t *
>(dst);
393 auto bytesToRead =
static_cast<uint32_t
>(std::min<size_t>(size, std::numeric_limits<uint32_t>::max()));
402 result += bytesToRead;
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);
434 if (handle ==
nullptr)
437 int64_t lastHeaderPosition = 0;
438 int64_t targetPosition = -1;
440 bool fileStatus =
true;
445 lastHeaderPosition =
static_cast<int64_t
>(ftell(handle.get()));
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())));
454 std::string fileName(header.FileName);
455 if (fileName.length() == 0)
458 if (fileName ==
name)
459 targetPosition = lastHeaderPosition;
460 else if (targetPosition != -1)
461 throw std::runtime_error(
"format exception");
463 auto fileSize = header.readFileSize();
465 auto offset =
static_cast<size_t>(fileSize % 512);
467 offset = 512 - offset;
469 fileStatus &= 0 == fseek(handle.get(),
static_cast<long>(fileSize + offset), SEEK_CUR);
472 if (targetPosition < 0)
473 targetPosition = lastHeaderPosition;
477 memset(padding, 0, 512);
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);
489 header.writeFileSize(size);
490 header.writeChecksum();
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());
498 fileStatus &= 1 == fwrite(buffer, size, 1, handle.get());
501 auto offset =
static_cast<size_t>(size % 512);
503 offset = 512 - offset;
505 fileStatus &= 1 == fwrite(padding, offset, 1, handle.get());
509 fileStatus &= 1 == fwrite(padding, 512, 1, handle.get());
519 auto retval = epochInNanoSeconds -
static_cast<int64_t
>(Types::Core::DateAndTime::EPOCH_DIFF) * 1'000'000'000;
524 namespace fs = boost::filesystem;
525 fs::path p = nxsFile;
526 for (; !p.extension().empty();)
528 return p.generic_string();
538 if (dataSet.
rank() == 0) {
543 auto N = dataSet.
dim0();
550 }
catch (std::runtime_error &) {
560 value = std::string(dataSet(), dataSet.dim0());
562 }
catch (std::runtime_error &) {
569 auto datasets = newEntry.
datasets();
570 auto valid = (datasets.size() == 2 && newEntry.containsDataSet(
"time") && newEntry.containsDataSet(
"value"));
581 auto timestamp = entry.
openNXDataSet<uint64_t>(
"scan_dataset/time");
583 auto offset = entry.
openNXDataSet<int64_t>(
"scan_dataset/value");
586 auto start = timestamp[datasetIx];
587 auto end = start + offset[datasetIx];
589 }
catch (std::runtime_error &) {
601 auto timestamp = entry.
openNXDataSet<uint64_t>(
"hmscan/time");
606 auto start = timestamp[datasetIx];
607 auto end = start + offset[datasetIx];
609 }
catch (std::runtime_error &) {
627 std::vector<uint64_t> ×, std::vector<T> &events, std::string &units) {
632 auto timeStamp = entry.
openNXDataSet<uint64_t>(path +
"/time");
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++) {
644 times.assign(itt + startIx, itt + endIx);
647 units = values.attributes(
"units");
650 events.assign(itv + startIx, itv + endIx);
652 return endIx - startIx;
655 if (loadNXDataSet<T>(entry, path,
value, -1)) {
656 times.push_back(startTime);
657 events.push_back(
value);
666 ScanLog valueOption, uint64_t &eventTime, T &eventValue, std::string &units) {
669 std::vector<uint64_t> times;
670 std::vector<T> values;
671 auto n = extractTimedDataSet<T>(entry, path, startTime, endTime, times, values, units);
676 switch (valueOption) {
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;
682 eventValue = values[0];
683 eventTime = times[0];
686 eventValue = values[
n - 1];
687 eventTime = times[
n - 1];
696 uint64_t end_nsec,
const std::string &neutron_path,
int tube_resolution) {
702 auto eventID = entry.
openNXDataSet<uint32_t>(neutron_path +
"/event_id");
703 if (eventID.dim0() == 0)
706 auto eventIndex = entry.
openNXDataSet<uint32_t>(neutron_path +
"/event_time_zero_index");
708 auto zeroOffset = entry.
openNXDataSet<uint64_t>(neutron_path +
"/event_time_zero");
710 auto offsetValues = entry.
openNXDataSet<uint32_t>(neutron_path +
"/event_time_offset");
712 uint32_t numPulses =
static_cast<uint32_t
>(eventIndex.size());
713 uint32_t totalEvents =
static_cast<uint32_t
>(offsetValues.size());
722 uint64_t lastFrameTS{0};
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) {
731 lastFrameTS = pulseTime;
733 auto baseIndex = eventIndex[ix];
734 auto lastIndex = (ix + 1 < numPulses ? eventIndex[ix + 1] : totalEvents);
735 for (uint32_t j = baseIndex; j < lastIndex; j++) {
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;
756 uint64_t endTime, std::vector<uint64_t> ×, std::vector<float> &events,
759 uint64_t endTime, std::vector<uint64_t> ×,
760 std::vector<double> &events, std::string &units);
762 uint64_t endTime, std::vector<uint64_t> ×, std::vector<int> &events,
766 uint64_t endTime,
ScanLog valueOption, uint64_t &eventTime,
float &eventValue,
769 uint64_t endTime,
ScanLog valueOption, uint64_t &eventTime,
770 double &eventValue, std::string &units);
772 uint64_t endTime,
ScanLog valueOption, uint64_t &eventTime,
int &eventValue,
775 uint64_t endTime,
ScanLog valueOption, uint64_t &eventTime,
776 int64_t &eventValue, std::string &units);
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.
std::map< DeltaEMode::Type, std::string > index
#define TarTypeFlag_NormalFile
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Helper class for reporting progress from algorithms.
void doReport(const std::string &msg="") override
Actually do the reporting, without changing the loop counter.
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
virtual void newFrame()=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)
std::vector< size_t > & m_eventCounts
const double m_timeMinBoundary
const double m_timeMaxBoundary
void addEvent(size_t x, size_t y, double tof) override
virtual void addEventImpl(size_t id, int64_t pulse, double tof)=0
const double m_tofMinBoundary
const double m_tofMaxBoundary
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)
const std::vector< bool > & m_roi
bool seek(int64_t offset, int whence, int64_t *newPosition=nullptr)
bool read(void *buffer, uint32_t size)
FastReadOnlyFile(const char *filename)
helper class to keep track of progress
void setTarget(int64_t target)
void update(int64_t position)
API::Progress & m_progBar
ProgressTracker(API::Progress &progBar, const char *msg, int64_t target, size_t count)
std::vector< FileInfo > m_fileInfos
uint8_t m_buffer[BUFFER_SIZE]
std::vector< std::string > m_fileNames
File(const File &)=delete
const std::string & selected_name() const
int64_t selected_position() const
size_t read(void *dst, size_t size)
bool select(const char *file)
const std::vector< std::string > & files() const
static bool append(const std::string &path, const std::string &name, const void *buffer, size_t size)
bool skip(uint64_t offset)
int64_t selected_size() const
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 > ×, 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 > ×, 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 > ×, 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 > ×, 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 ®exFilter)
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 ®exFilter)
extract datasets from a group that match a regex filter
NXDataSetTyped< char > NXChar
The char dataset type.
void writeFileSize(int64_t value)