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.");
87 "Discards events before first chopper trigger (turn off for elastic)",
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.