40template <
typename V1,
typename V2>
bool startsWith(
const V1 &sequence,
const V2 &subSequence) {
41 return std::equal(std::begin(subSequence), std::end(subSequence), std::begin(sequence));
57 const std::string &extn = descriptor.extension();
60 auto &file = descriptor.data();
63 std::getline(file, fileline);
64 if (fileline.find(
"mesytec psd listmode data") != std::string::npos) {
76 const std::vector<std::string> exts{
".mdat"};
78 "A DNS mesydaq listmode event datafile.");
86 declareProperty<bool>(
"DiscardPreChopperEvents",
true,
87 "Discards events before first chopper trigger (turn off for elastic)",
90 declareProperty<bool>(
"SetBinBoundary",
true,
91 "Sets all bin boundaries to include all events (can be turned off to save time).",
96 "The name of the output workspace.");
112 outputWS->getAxis(0)->setUnit(
"TOF");
113 outputWS->setYUnit(
"Counts");
119 auto finalEventAccumulator =
parse_File(file, fileName);
122 outputWS->setAllX({0, outputWS->getEventXMax()});
128 static const unsigned EVENTS_PER_PROGRESS = 100;
134 [](
auto l,
auto r) { return l.timestamp > r.timestamp; });
136 std::atomic<unsigned int> oversizedChanelIndexCounterA(0);
137 std::atomic<unsigned int> oversizedPosCounterA(0);
140 for (
int eventIndex = 0; eventIndex < static_cast<int>(finalEventAccumulator.
neutronEvents.size()); ++eventIndex) {
142 unsigned int oversizedChanelIndexCounter = 0;
143 unsigned int oversizedPosCounter = 0;
144 const auto wsIndex = eventIndex;
145 auto &eventList = finalEventAccumulator.
neutronEvents[eventIndex];
146 if (eventList.size() != 0) {
147 std::sort(eventList.begin(), eventList.end(), [](
auto l,
auto r) { return l.timestamp < r.timestamp; });
150 auto chopperIt = finalEventAccumulator.
triggerEvents.cbegin();
152 auto &spectrum = eventWS->getSpectrum(wsIndex);
155 uint64_t numProcessed = 0;
156 for (
const auto &event : eventList) {
158 if (numProcessed % EVENTS_PER_PROGRESS == 0) {
167 event.timestamp, [](
auto l,
auto r) { return l.timestamp > r; });
168 const uint64_t chopperTimestamp = chopperIt != finalEventAccumulator.
triggerEvents.cend()
169 ? chopperIt->timestamp
175 spectrum.addEventQuickly(Types::Event::TofEvent(
double(event.timestamp - chopperTimestamp) / 10.0));
179 oversizedChanelIndexCounterA += oversizedChanelIndexCounter;
180 oversizedPosCounterA += oversizedPosCounter;
184 if (oversizedChanelIndexCounterA > 0) {
185 g_log.
warning() <<
"Bad chanel indices: " << oversizedChanelIndexCounterA << std::endl;
187 if (oversizedPosCounterA > 0) {
188 g_log.
warning() <<
"Bad position values: " << oversizedPosCounterA << std::endl;
196 std::vector<uint8_t> header;
198 std::array<uint8_t,
header_sep.size()> current_window;
200 while (!file.
eof()) {
204 const auto orig_header_size = header.size();
205 header.resize(header.size() + 1);
206 const auto win_data = current_window.data();
207 std::copy(win_data, win_data + 1, header.data() + orig_header_size);
208 const std::array<uint8_t,
header_sep.size()> orig_window = current_window;
209 file.
readRaw(current_window, 1);
210 std::copy(orig_window.data() + 1, orig_window.data() +
header_sep.size(), win_data);
219 const uint64_t chunckSize = std::max(minChunckSize, file.
fileSize() / maxChunckCount);
221 std::vector<std::vector<uint8_t>> result;
223 while (!file.
eof()) {
224 result.push_back(std::vector<uint8_t>());
226 auto &data = result.back();
227 data.resize(chunckSize);
229 file.
readRaw(*data.begin(), chunckSize);
230 }
catch (std::ifstream::failure &) {
231 data.resize(file.
gcount());
236 static const auto windowSize =
block_sep.size();
237 uint8_t *current_window =
nullptr;
238 std::array<uint8_t, windowSize> *windowAsArray =
239 reinterpret_cast<std::array<uint8_t, windowSize> *
>(current_window);
242 data.resize(data.size() + windowSize);
244 current_window = &*(data.end() - windowSize);
245 windowAsArray =
reinterpret_cast<std::array<uint8_t, windowSize> *
>(current_window);
246 file.
readRaw(current_window[0], windowSize);
248 while ((*windowAsArray !=
block_sep) && (!file.
eof())) {
249 const auto orig_data_size = data.size();
250 data.resize(orig_data_size + 1);
252 current_window = (&data.back() - windowSize + 1);
253 windowAsArray =
reinterpret_cast<std::array<uint8_t, windowSize> *
>(current_window);
254 file.
readRaw(current_window[windowSize - 1], 1);
256 }
catch (std::ifstream::failure &) {
268 if (!
startsWith(header, std::string(
"mesytec psd listmode data"))) {
269 g_log.
error() <<
"This seems not to be a mesytec psd listmode file: " << fileName;
276 std::vector<std::vector<uint8_t>> filechuncks =
split_File(file, threadCount);
277 g_log.
debug() <<
"filechuncks count = " << filechuncks.size() << std::endl;
279 std::vector<EventAccumulator> eventAccumulators(filechuncks.size());
280 for (
auto &evtAcc : eventAccumulators) {
286 for (
int i = 0; i < static_cast<int>(filechuncks.size()); ++i) {
287 auto filechunck = filechuncks[
static_cast<size_t>(i)];
288 g_log.
debug() <<
"filechunck.size() = " << filechunck.size() << std::endl;
299 for (
const auto &v : eventAccumulators) {
301 v.triggerEvents.end());
306 for (
int i = 0; i < static_cast<int>(finalEventAccumulator.
neutronEvents.size()); ++i) {
307 auto &allNeutronEvents = finalEventAccumulator.
neutronEvents[
static_cast<size_t>(i)];
308 for (
const auto &v : eventAccumulators) {
309 allNeutronEvents.insert(allNeutronEvents.end(), v.neutronEvents[
static_cast<size_t>(i)].begin(),
310 v.neutronEvents[
static_cast<size_t>(i)].end());
314 return finalEventAccumulator;
319 while (!file.
eof() && file.
peek() != 0xFF) {
333 throw std::runtime_error(std::string(
"File Integrety LOST. 0x"));
340 const uint16_t dataLength = uint16_t(bufferHeader.bufferLength - 21);
341 const auto event_count = dataLength / 3;
343 for (uint16_t i = 0; i < event_count; i++) {
353 file.
read<2>(header.bufferLength);
354 file.
read<2>(header.bufferVersion);
355 file.
read<2>(header.headerLength);
356 file.
read<2>(header.bufferNumber);
357 file.
read<2>(header.runId);
358 file.
read<1>(header.mcpdId);
359 file.
read<1>(header.deviceStatus);
364 header.timestamp = (uint64_t)ts3 << 32 | (uint64_t)ts2 << 16 | ts1;
374 trigId = (data >> 44) & 0b111;
375 dataId = (data >> 40) & 0b1111;
388 modid = (data >> 44) & 0b111;
389 slotid = (data >> 39) & 0b11111;
408 data = (uint64_t)data3 << 32 | (uint64_t)data2 << 16 | data1;
409 eventId =
static_cast<event_id_e>((data >> 47) & 0b1);
413 if (triggerEvent.isChopperTrigger) {
414 eventAccumulator.
triggerEvents.push_back(triggerEvent.event);
419 eventAccumulator.
neutronEvents[neutronEvent.wsIndex].push_back(neutronEvent.event);
422 g_log.
error() <<
"unknown event id " << eventId <<
"\n";
430 throw std::runtime_error(std::string(
"File Integrety LOST. 0x"));
static constexpr separator_t closing_sig
static constexpr separator_t block_sep
std::array< uint8_t, 8 > separator_t
static constexpr separator_t header_sep
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
#define PARALLEL_FOR_NO_WSP_CHECK()
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#define PARALLEL_GET_MAX_THREADS
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
#define DECLARE_FILELOADER_ALGORITHM(classname)
DECLARE_FILELOADER_ALGORITHM should be used in place of the standard DECLARE_ALGORITHM macro when wri...
FileByteStream & readRaw(T &result, const std::size_t &bytecount)
uint64_t fileSize() const
std::streamsize gcount() const
CancelException is thrown to cancel execution of the algorithm.
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
bool getCancel() const
Returns the cancellation state.
@ Load
allowed here which will be passed to the algorithm
Helper class for reporting progress from algorithms.
A property class for workspaces.
TriggerEvent processTrigger(const uint64_t &data, const LoadDNSEvent::BufferHeader &bufferHeader)
std::vector< uint8_t > parse_Header(FileByteStream &file)
void parse_BlockList(VectorByteStream &file, EventAccumulator &eventAccumulator)
void populate_EventWorkspace(Mantid::DataObjects::EventWorkspace_sptr &eventWS, EventAccumulator &finalEventAccumulator)
void parse_andAddEvent(VectorByteStream &file, const BufferHeader &bufferHeader, EventAccumulator &eventAccumulator)
NeutronEvent processNeutron(const uint64_t &data, const LoadDNSEvent::BufferHeader &bufferHeader)
void exec() override
Run the algorithm.
bool m_discardPreChopperEvents
EventAccumulator parse_File(FileByteStream &file, const std::string &fileName)
void parse_BlockSeparator(VectorByteStream &file)
BufferHeader parse_DataBufferHeader(VectorByteStream &file)
void parse_EndSignature(FileByteStream &file)
void parse_DataBuffer(VectorByteStream &file, EventAccumulator &eventAccumulator)
std::vector< std::vector< uint8_t > > split_File(FileByteStream &file, const unsigned maxChunckCount)
uint32_t m_detectorPixelCount
void init() override
Virtual method - must be overridden by concrete algorithm.
void parse_Block(VectorByteStream &file, EventAccumulator &eventAccumulator)
uint32_t m_chopperChannel
BoundedValidator is a validator that requires the values to be between upper or lower bounds,...
Records the filename and the description of failure.
Defines a wrapper around an open file.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void debug(const std::string &msg)
Logs at debug level.
void error(const std::string &msg)
Logs at error level.
void warning(const std::string &msg)
Logs at warning level.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
VectorByteStream & read(T &result)
VectorByteStream & skip()
VectorByteStream & readRaw(T &result, const std::size_t &bytecount)
bool startsWith(const string &str, const string &prefix)
Returns true if str starts with prefix.
const unsigned int PIXEL_PER_TUBE
const unsigned int MAX_BUFFER_BYTES_SIZE
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
std::unique_ptr< T > create(const P &parent, const IndexArg &indexArg, const HistArg &histArg)
This is the create() method that all the other create() methods call.
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
std::vector< std::vector< CompactEvent > > neutronEvents
std::vector< CompactEvent > triggerEvents
@ Input
An input workspace.
@ Output
An output workspace.