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 : m_msg(msg),
m_count(
count), m_step(target /
count), m_next(m_step), m_progBar(progBar) {
55 m_next = std::numeric_limits<int64_t>::max();
83 const double phase,
const int64_t startTime,
const double tofMinBoundary,
84 const double tofMaxBoundary,
const double timeMinBoundary,
const double timeMaxBoundary)
85 : m_roi(roi), m_stride(stride), m_frames(0), m_framesValid(0), m_startTime(startTime), m_period(period),
86 m_phase(phase), m_tofMinBoundary(tofMinBoundary), m_tofMaxBoundary(tofMaxBoundary),
87 m_timeMinBoundary(timeMinBoundary), m_timeMaxBoundary(timeMaxBoundary) {}
127 auto frames =
static_cast<double>(
m_frames);
128 auto frameTime =
static_cast<int64_t
>(
m_period * frames * 1.0e3);
137 const int64_t startTime,
const double tofMinBoundary,
const double tofMaxBoundary,
138 const double timeMinBoundary,
const double timeMaxBoundary, std::vector<size_t> &eventCounts)
139 :
EventProcessor(roi, stride, period, phase, startTime, tofMinBoundary, tofMaxBoundary, timeMinBoundary,
141 m_eventCounts(eventCounts), m_tofMin(
std::numeric_limits<double>::max()),
142 m_tofMax(
std::numeric_limits<double>::min()) {}
158 const int64_t startTime,
const double tofMinBoundary,
const double tofMaxBoundary,
159 const double timeMinBoundary,
const double timeMaxBoundary,
160 std::vector<EventVector_pt> &eventVectors)
161 :
EventProcessor(roi, stride, period, phase, startTime, tofMinBoundary, tofMaxBoundary, timeMinBoundary,
163 m_eventVectors(eventVectors) {}
165 m_eventVectors[id]->emplace_back(tof, Types::Core::DateAndTime(pulse));
170 const double wavelength,
const double period,
171 const double phase,
const int64_t startTime,
172 const double tofMinBoundary,
const double tofMaxBoundary,
173 const double timeMinBoundary,
const double timeMaxBoundary,
174 std::vector<EventVector_pt> &eventVectors)
175 :
EventAssigner(roi, stride, period, phase, startTime, tofMinBoundary, tofMaxBoundary, timeMinBoundary,
176 timeMaxBoundary, eventVectors),
177 m_wavelength(wavelength) {}
185 m_handle = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
195 return (FALSE != ReadFile(
m_handle, buffer, size, &bytesRead, NULL)) && (bytesRead == size);
198 return FALSE != SetFilePointerEx(
m_handle, *(LARGE_INTEGER *)&offset, (LARGE_INTEGER *)newPosition, whence);
209 return 1 == fread(buffer,
static_cast<size_t>(size), 1,
m_handle);
212 return (0 == fseek(
m_handle, offset, whence)) &&
213 ((newPosition ==
nullptr) || (0 <= (*newPosition =
static_cast<int64_t
>(ftell(
m_handle)))));
221 size_t value = std::accumulate(
reinterpret_cast<const char *
>(
this),
222 reinterpret_cast<const char *
>(
this) +
sizeof(
EntryHeader),
static_cast<size_t>(0));
224 std::ostringstream buffer;
226 buffer << std::oct << std::setfill('0') << std::setw(static_cast<int>(
sizeof(
Checksum)) - 1) <<
value;
227 std::string
string = buffer.str();
229 std::copy(
string.cbegin(),
string.cend(),
Checksum);
233 std::ostringstream buffer;
235 buffer << std::oct << std::setfill('0') << std::setw(static_cast<int>(
sizeof(
FileSize)) - 1) <<
value;
236 std::string
string = buffer.str();
238 std::copy(
string.cbegin(),
string.cend(),
FileSize);
244 for (
size_t n =
sizeof(
FileSize) - 1;
n != 0; --
n) {
246 if ((
'0' <= c) && (c <=
'9'))
247 result = result * 8 + (c -
'0');
254 : m_good(true), m_file(path.c_str()), m_selected(static_cast<size_t>(-1)), m_position(0),
m_size(0),
255 m_bufferPosition(0), m_bufferAvailable(0) {
267 std::string fileName(header.FileName);
268 if (fileName.length() == 0)
273 fileInfo.
Size = header.readFileSize();
280 auto offset =
static_cast<size_t>(fileInfo.
Size % 512);
282 offset = 512 - offset;
317 size_t i = std::distance(
m_fileNames.cbegin(), it);
352 return m_good && !overrun;
361 auto ptr =
reinterpret_cast<uint8_t *
>(dst);
378 auto bytesToRead =
static_cast<uint32_t
>(std::min<size_t>(size, std::numeric_limits<uint32_t>::max()));
387 result += bytesToRead;
416bool File::append(
const std::string &path,
const std::string &
name,
const void *buffer,
size_t size) {
417 std::unique_ptr<FILE,
decltype(&fclose)> handle(fopen(path.c_str(),
"rb+"), fclose);
419 if (handle ==
nullptr)
422 int64_t lastHeaderPosition = 0;
423 int64_t targetPosition = -1;
425 bool fileStatus =
true;
430 lastHeaderPosition =
static_cast<int64_t
>(ftell(handle.get()));
432 fileStatus &= 1 == fread(&header,
sizeof(
EntryHeader), 1, handle.get());
433 fileStatus &= 0 == fseek(handle.get(), 512 -
sizeof(
EntryHeader), SEEK_CUR);
434 fileStatus &= 0 <= (
position =
static_cast<int64_t
>(ftell(handle.get())));
439 std::string fileName(header.FileName);
440 if (fileName.length() == 0)
443 if (fileName ==
name)
444 targetPosition = lastHeaderPosition;
445 else if (targetPosition != -1)
446 throw std::runtime_error(
"format exception");
448 auto fileSize = header.readFileSize();
450 auto offset =
static_cast<size_t>(fileSize % 512);
452 offset = 512 - offset;
454 fileStatus &= 0 == fseek(handle.get(),
static_cast<long>(fileSize + offset), SEEK_CUR);
457 if (targetPosition < 0)
458 targetPosition = lastHeaderPosition;
462 memset(padding, 0, 512);
467 memcpy(header.FileName,
name.c_str(),
name.size());
468 memset(header.FileMode,
'0',
sizeof(header.FileMode) - 1);
469 memset(header.OwnerUserID,
'0',
sizeof(header.OwnerUserID) - 1);
470 memset(header.OwnerGroupID,
'0',
sizeof(header.OwnerGroupID) - 1);
471 memset(header.LastModification,
'0',
sizeof(header.LastModification) - 1);
474 header.writeFileSize(size);
475 header.writeChecksum();
478 fileStatus &= 0 == fseek(handle.get(),
static_cast<long>(targetPosition), SEEK_SET);
479 fileStatus &= 1 == fwrite(&header,
sizeof(
EntryHeader), 1, handle.get());
480 fileStatus &= 1 == fwrite(padding, 512 -
sizeof(
EntryHeader), 1, handle.get());
483 fileStatus &= 1 == fwrite(buffer, size, 1, handle.get());
486 auto offset =
static_cast<size_t>(size % 512);
488 offset = 512 - offset;
490 fileStatus &= 1 == fwrite(padding, offset, 1, handle.get());
494 fileStatus &= 1 == fwrite(padding, 512, 1, handle.get());
504 auto retval = epochInNanoSeconds -
static_cast<int64_t
>(Types::Core::DateAndTime::EPOCH_DIFF) * 1'000'000'000;
509 namespace fs = boost::filesystem;
510 fs::path p = nxsFile;
511 for (; !p.extension().empty();)
513 return p.generic_string();
524 auto N = dataSet.
dim0();
530 }
catch (std::runtime_error &) {
540 value = std::string(dataSet(), dataSet.dim0());
542 }
catch (std::runtime_error &) {
549 auto datasets = newEntry.
datasets();
550 auto valid = (datasets.size() == 2 && newEntry.containsDataSet(
"time") && newEntry.containsDataSet(
"value"));
561 auto timestamp = entry.
openNXDataSet<uint64_t>(
"scan_dataset/time");
563 auto offset = entry.
openNXDataSet<int64_t>(
"scan_dataset/value");
566 auto start = timestamp[datasetIx];
567 auto end = start + offset[datasetIx];
569 }
catch (std::runtime_error &) {
581 auto timestamp = entry.
openNXDataSet<uint64_t>(
"hmscan/time");
586 auto start = timestamp[datasetIx];
587 auto end = start + offset[datasetIx];
589 }
catch (std::runtime_error &) {
607 std::vector<uint64_t> ×, std::vector<T> &events, std::string &units) {
609 auto timeStamp = entry.
openNXDataSet<uint64_t>(path +
"/time");
611 size_t maxn = timeStamp.size();
612 uint64_t startIx{0}, endIx{0};
613 auto itt = timeStamp();
614 for (
size_t i = 0; i < maxn; i++) {
621 times.assign(itt + startIx, itt + endIx);
624 units = values.attributes(
"units");
627 events.assign(itv + startIx, itv + endIx);
629 return endIx - startIx;
634 ScanLog valueOption, uint64_t &eventTime, T &eventValue, std::string &units) {
637 std::vector<uint64_t> times;
638 std::vector<T> values;
639 auto n = extractTimedDataSet<T>(entry, path, startTime, endTime, times, values, units);
644 switch (valueOption) {
646 eventValue = std::accumulate(values.cbegin(), values.cend(), T{0}) /
static_cast<T
>(
n);
647 eventTime = std::accumulate(times.cbegin(), times.cend(), uint64_t{0}) /
n;
650 eventValue = values[0];
651 eventTime = times[0];
654 eventValue = values[
n - 1];
655 eventTime = times[
n - 1];
664 uint64_t end_nsec,
const std::string &neutron_path,
int tube_resolution) {
670 auto eventID = entry.
openNXDataSet<uint32_t>(neutron_path +
"/event_id");
671 if (eventID.dim0() == 0)
674 auto eventIndex = entry.
openNXDataSet<uint32_t>(neutron_path +
"/event_time_zero_index");
676 auto zeroOffset = entry.
openNXDataSet<uint64_t>(neutron_path +
"/event_time_zero");
678 auto offsetValues = entry.
openNXDataSet<uint32_t>(neutron_path +
"/event_time_offset");
680 uint32_t numPulses =
static_cast<uint32_t
>(eventIndex.size());
681 uint32_t totalEvents =
static_cast<uint32_t
>(offsetValues.size());
690 uint64_t lastFrameTS{0};
694 for (uint32_t ix = 0; ix < numPulses; ix++) {
695 auto pulseTime = zeroOffset[ix];
696 if (start_nsec <= pulseTime && pulseTime < end_nsec) {
697 if (pulseTime > lastFrameTS) {
699 lastFrameTS = pulseTime;
701 auto baseIndex = eventIndex[ix];
702 auto lastIndex = (ix + 1 < numPulses ? eventIndex[ix + 1] : totalEvents);
703 for (uint32_t j = baseIndex; j < lastIndex; j++) {
706 double tof = offsetValues[j] * 1.0e-3;
707 auto pixel = eventID[j];
708 size_t y = pixel % tube_resolution;
709 size_t x = (pixel -
y) / tube_resolution;
724 uint64_t endTime, std::vector<uint64_t> ×, std::vector<float> &events,
727 uint64_t endTime, std::vector<uint64_t> ×,
728 std::vector<double> &events, std::string &units);
731 uint64_t endTime,
ScanLog valueOption, uint64_t &eventTime,
float &eventValue,
734 uint64_t endTime,
ScanLog valueOption, uint64_t &eventTime,
735 double &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.
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
virtual void addEventImpl(size_t id, int64_t pulse, double tof)=0
void addEvent(size_t x, size_t y, double tof)
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.
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.
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)
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)
void ReadEventData(ProgressTracker &prog, const Nexus::NXEntry &entry, EventProcessor *handler, uint64_t start_nsec, uint64_t end_nsec, const std::string &neutron_path, int tube_resolution=1024)
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)
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)
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 > 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)