20#include <boost/algorithm/string.hpp>
29constexpr int NUM_OF_SPECTRA = 16384;
39uint64_t swapUint64(uint64_t word) {
40 word = ((word << 8) & 0xFF00FF00FF00FF00ULL) | ((word >> 8) & 0x00FF00FF00FF00FFULL);
41 word = ((word << 16) & 0xFFFF0000FFFF0000ULL) | ((word >> 16) & 0x0000FFFF0000FFFFULL);
42 return (word << 32) | (word >> 32);
52void correctForBigEndian(
const EventUnion &bigEndian, EventUnion &smallEndian) {
53 smallEndian.splitWord.words[0] = swapUint64(bigEndian.splitWord.words[1]);
54 smallEndian.splitWord.words[1] = swapUint64(bigEndian.splitWord.words[0]);
69void addFrameToOutputWorkspace(
int &rawFrames,
int &goodFrames,
const int &eventCountInFrame,
const int &minEventsReq,
70 const int &maxEventsReq,
MantidVec &frameEventCounts,
71 std::vector<DataObjects::EventList> &events,
72 std::vector<DataObjects::EventList> &eventsInFrame) {
74 if (eventCountInFrame >= minEventsReq && eventCountInFrame <= maxEventsReq) {
76 frameEventCounts.emplace_back(eventCountInFrame);
81 for (auto i = 0; i < NUM_OF_SPECTRA; ++i) {
82 if (eventsInFrame[i].getNumberEvents() > 0) {
83 events[i] += eventsInFrame[i];
84 eventsInFrame[i].clear();
99 const std::vector<DataObjects::EventList> &events,
102 std::vector<double> xAxis(
int(std::ceil(maxToF / binWidth)));
103 std::generate(xAxis.begin(), xAxis.end(), [i = 0, &binWidth]()
mutable { return binWidth * i++; });
105 dataWorkspace = DataObjects::create<DataObjects::EventWorkspace>(
106 NUM_OF_SPECTRA, HistogramData::Histogram(HistogramData::BinEdges(xAxis)));
108 for (
int i = 0; i < NUM_OF_SPECTRA; ++i) {
109 dataWorkspace->getSpectrum(i) = events[i];
110 dataWorkspace->getSpectrum(i).setSpectrumNo(i + 1);
111 dataWorkspace->getSpectrum(i).setDetectorID(i + 1);
113 dataWorkspace->setAllX(HistogramData::BinEdges{xAxis});
115 dataWorkspace->setYUnit(
"Counts");
125template <
typename ValueType>
126void addToSampleLog(
const std::string &name,
const ValueType &
value, DataObjects::EventWorkspace &ws) {
127 ws.mutableRun().addProperty(name,
value,
false);
152 const std::vector<std::string> extentions{
".edb"};
153 declareProperty(std::make_unique<API::MultipleFileProperty>(
"Filename", extentions),
154 "The name of the nGEM file to load. Selecting multiple files will "
155 "combine them into one workspace.");
159 "The output workspace");
161 auto mustBePositive = std::make_shared<Kernel::BoundedValidator<int>>();
162 mustBePositive->setLower(0);
164 auto mustBePositiveDbl = std::make_shared<Kernel::BoundedValidator<double>>();
165 mustBePositiveDbl->setLower(0.0);
168 declareProperty(
"BinWidth", 10.0, mustBePositiveDbl,
"The width of the time bins in the output.");
171 "The minimum number of events required in a frame before a "
172 "it is considered 'good'.");
174 "The maximum number of events allowed in a frame to be "
175 "considered 'good'.");
178 "Generate a workspace to show the number of events captured by each "
179 "frame. (optional, default False).");
188 std::vector<std::vector<std::string>> filePaths =
getProperty(
"Filename");
190 const int minEventsReq(
getProperty(
"MinEventsPerFrame"));
191 const int maxEventsReq(
getProperty(
"MaxEventsPerFrame"));
193 double maxToF{-std::numeric_limits<double>::max()}, minToF{std::numeric_limits<double>::max()};
198 std::vector<double> frameEventCounts;
199 int eventCountInFrame = 0;
201 std::vector<DataObjects::EventList> events, eventsInFrame;
202 events.resize(NUM_OF_SPECTRA);
203 eventsInFrame.resize(NUM_OF_SPECTRA);
206 size_t totalFilePaths(filePaths.size());
208 for (
const auto &filePath : filePaths) {
209 loadSingleFile(filePath, eventCountInFrame, maxToF, minToF, rawFrames, goodFrames, minEventsReq, maxEventsReq,
210 frameEventCounts, events, eventsInFrame, totalFilePaths, counter);
213 addFrameToOutputWorkspace(rawFrames, goodFrames, eventCountInFrame, minEventsReq, maxEventsReq, frameEventCounts,
214 events, eventsInFrame);
218 createEventWorkspace(maxToF, binWidth, events, dataWorkspace);
220 addToSampleLog(
"raw_frames", rawFrames, *dataWorkspace);
221 addToSampleLog(
"good_frames", goodFrames, *dataWorkspace);
222 addToSampleLog(
"max_ToF", maxToF, *dataWorkspace);
223 addToSampleLog(
"min_ToF", minToF, *dataWorkspace);
252 double &minToF,
int &rawFrames,
int &goodFrames,
const int &minEventsReq,
253 const int &maxEventsReq,
MantidVec &frameEventCounts,
254 std::vector<DataObjects::EventList> &events,
255 std::vector<DataObjects::EventList> &eventsInFrame,
const size_t &totalFilePaths,
258 if (filePath.size() > 1) {
259 throw std::runtime_error(
"Invalid filename parameter.");
261 std::ifstream file(filePath[0].c_str(), std::ifstream::binary);
262 if (!file.is_open()) {
263 throw std::runtime_error(
"File could not be found.");
267 constexpr size_t SKIP_WORD_SIZE = 4;
268 size_t numProcessedEvents = 0;
269 size_t numWordsSkipped = 0;
278 file.read(
reinterpret_cast<char *
>(&eventBigEndian),
sizeof(eventBigEndian));
280 correctForBigEndian(eventBigEndian, event);
281 }
while (!event.
generic.
check() && !file.seekg(SKIP_WORD_SIZE, std::ios_base::cur).eof() && ++numWordsSkipped);
287 uint64_t pixel =
event.coincidence.getPixel();
289 const double tof =
event.coincidence.timeOfFlight / 1000.0;
293 }
else if (tof < minToF) {
296 eventsInFrame[pixel].addEventQuickly(Types::Event::TofEvent(tof));
299 addFrameToOutputWorkspace(rawFrames, goodFrames, eventCountInFrame, minEventsReq, maxEventsReq, frameEventCounts,
300 events, eventsInFrame);
307 g_log.
warning() <<
"Unexpected event type ID=" <<
event.generic.id <<
" loaded.\n";
312 if (numWordsSkipped > 0) {
314 <<
" bytes of file data were skipped when locating valid events.\n";
329 file.seekg(0, file.end);
330 size_t size = file.tellg();
331 if (size % 16 != 0) {
332 g_log.
warning() <<
"Invalid file size. File is size is " << size
333 <<
" bytes which is not a multiple of 16. There may be some bytes "
334 "missing from the data. \n";
352 const size_t &totalNumEvents,
const size_t &totalFilePaths,
353 const int &fileCount) {
354 numProcessedEvents += eventCountInFrame;
356 progress(
double(numProcessedEvents) /
double(totalNumEvents) / 1.11111, message);
357 eventCountInFrame = 0;
369 std::vector<double> xAxisCounts(frameEventCounts.size() + 1);
370 std::generate(xAxisCounts.begin(), xAxisCounts.end(), [
n = 0.0]()
mutable { return ++n; });
373 DataObjects::create<DataObjects::Workspace2D>(1, HistogramData::Histogram(HistogramData::BinEdges(xAxisCounts)));
375 countsWorkspace->mutableY(0) = frameEventCounts;
376 std::string countsWorkspaceName(this->
getProperty(
"OutputWorkspace"));
377 countsWorkspaceName.append(
"_event_counts");
378 countsWorkspace->setYUnit(
"Counts");
379 std::shared_ptr<Kernel::Units::Label> XLabel =
381 XLabel->setLabel(
"Frame");
382 countsWorkspace->getAxis(0)->unit() = XLabel;
386 "Counts of events per frame.");
388 this->
setProperty(
"CountsWorkspace", countsWorkspace);
412 std::map<std::string, std::string> results;
414 int MinEventsPerFrame =
getProperty(
"MinEventsPerFrame");
415 int MaxEventsPerFrame =
getProperty(
"MaxEventsPerFrame");
417 if (MaxEventsPerFrame < MinEventsPerFrame) {
418 results[
"MaxEventsPerFrame"] =
"MaxEventsPerFrame is less than MinEvents per frame";
double value
The value of the point.
#define PARALLEL_FOR_NO_WSP_CHECK()
#define DECLARE_FILELOADER_ALGORITHM(classname)
DECLARE_FILELOADER_ALGORITHM should be used in place of the standard DECLARE_ALGORITHM macro when wri...
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
bool getCancel() const
Returns the cancellation state.
A property class for workspaces.
int confidence(Kernel::FileDescriptor &descriptor) const override
The confidence that an algorithm is able to load the file.
void loadSingleFile(const std::vector< std::string > &filePath, int &eventCountInFrame, double &maxToF, double &minToF, int &rawFrames, int &goodFrames, const int &minEventsReq, const int &maxEventsReq, MantidVec &frameEventCounts, std::vector< DataObjects::EventList > &events, std::vector< DataObjects::EventList > &eventsInFrame, const size_t &totalFilePaths, int &fileCount)
Load a file into the event lists.
void createCountWorkspace(const std::vector< double > &frameEventCounts)
Create a workspace to store the number of counts per frame.
void exec() override
Execute the algorithm.
void loadInstrument(DataObjects::EventWorkspace_sptr &dataWorkspace)
Load the instrument and attach to the data workspace.
bool reportProgressAndCheckCancel(size_t &numProcessedEvents, int &eventCountInFrame, const size_t &totalNumEvents, const size_t &totalFilePaths, const int &fileCount)
Reports progress and checks cancel flag.
std::map< std::string, std::string > validateInputs() override
Validate the imputs into the algorithm, overrides.
size_t verifyFileSize(std::ifstream &file)
Check that a file to be loaded is in 128 bit words.
void init() override
Initialise the algorithm.
Defines a wrapper around an open file.
const std::string & extension() const
Access the file extension.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
OptionalBool : Tri-state bool.
The concrete, templated class for properties.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< Workspace2D > Workspace2D_sptr
shared pointer to Mantid::DataObjects::Workspace2D
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.
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
std::vector< double > MantidVec
typedef for the data storage used in Mantid matrix workspaces
Mantid::DataObjects::EventWorkspace_sptr createEventWorkspace()
Create event workspace with: 500 pixels 1000 histogrammed bins.
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Input
An input workspace.
@ Output
An output workspace.
Is able to hold all versions of the data words in the same memory location.
CoincidenceEvent coincidence