37#if BOOST_VERSION < 107100
38#include <boost/timer.hpp>
40#include <boost/timer/timer.hpp>
59using namespace Kernel;
61using namespace DataObjects;
62using namespace Geometry;
63using DataObjects::EventList;
64using DataObjects::EventWorkspace;
67using std::runtime_error;
69using std::stringstream;
71using Types::Core::DateAndTime;
72using Types::Event::TofEvent;
93static const uint64_t
VETOFLAG(72057594037927935);
95static const string EVENT_EXTS[] = {
"_neutron_event.dat",
"_neutron0_event.dat",
"_neutron1_event.dat",
96 "_neutron2_event.dat",
"_neutron3_event.dat",
"_live_neutron_event.dat"};
97static const string PULSE_EXTS[] = {
"_pulseid.dat",
"_pulseid0.dat",
"_pulseid1.dat",
98 "_pulseid2.dat",
"_pulseid3.dat",
"_live_pulseid.dat"};
110 string runnumber(Poco::Path(filename).getBaseName());
112 if (runnumber.find(
"neutron") >= string::npos)
115 std::size_t
left = runnumber.find(
'_');
116 std::size_t
right = runnumber.find(
'_',
left + 1);
127 std::reverse(eventExts.begin(), eventExts.end());
129 std::reverse(pulseExts.begin(), pulseExts.end());
132 for (std::size_t i = 0; i < eventExts.size(); ++i) {
133 size_t start = eventfile.find(eventExts[i]);
134 if (start != string::npos)
135 return eventfile.replace(start, eventExts[i].size(), pulseExts[i]);
147 std::vector<string> temp = wksp->getInstrument()->getStringParameter(
"TS_mapping_file");
151 string mapping = temp[0];
153 Poco::File localmap(mapping);
154 if (localmap.exists())
159 if (!dataversion.empty())
163 string instrument = wksp->getInstrument()->getName();
164 Poco::File base(
"/SNS/" + instrument +
"/");
166 if (!base.exists()) {
170 base = Poco::File(
"/SNS/" + instrument +
"/");
179 const string CAL(
"_CAL");
180 const size_t CAL_LEN = CAL.length();
181 vector<string> files;
182 for (
auto &dir : dirs) {
183 if ((dir.length() > CAL_LEN) && (dir.compare(dir.length() - CAL.length(), CAL.length(), CAL) == 0)) {
184 std::string path = std::string(base.path()).append(
"/").append(dir).append(
"/calibrations/").append(mapping);
185 if (Poco::File(path).
exists()) {
186 files.emplace_back(path);
192 return std::string();
193 else if (files.size() == 1)
197 return *(files.rbegin());
209 m_numEvents(0), m_numPulses(0), m_numPixel(0), m_numGoodEvents(0), m_numErrorEvents(0), m_numBadEvents(0),
210 m_numWrongdetidEvents(0), m_numIgnoredEvents(0), m_firstEvent(0), m_maxNumEvents(0), m_usingMappingFile(false),
211 m_loadOnlySomeSpectra(false), m_longestTof(0.0), m_shortestTof(0.0), m_parallelProcessing(false),
212 m_pulseTimesIncreasing(false), m_throwError(true), m_examEventLog(false), m_pixelid2exam(0), m_numevents2write(0),
213 m_freqHz(0), m_istep(0), m_dbPixelID(0), m_useDBOutput(false), m_corretctTOF(false) {}
227 if (descriptor.
extension().rfind(
"dat") == std::string::npos)
235 const size_t objSize =
sizeof(
DasEvent);
236 auto &handle = descriptor.
data();
239 handle.seekg(0, std::ios::end);
240 const auto filesize =
static_cast<size_t>(handle.tellg());
241 handle.seekg(0, std::ios::beg);
243 if (filesize % objSize == 0)
256 "The name of the neutron event file to read, including its full or "
257 "relative path. In most cases, the file typically ends in "
258 "neutron_event.dat (N.B. case sensitive if running on Linux).");
261 "File containing the accelerator pulse information; the "
262 "filename will be found automatically if not specified.");
264 "File containing the pixel mapping (DAS pixels to pixel IDs) file "
265 "(typically INSTRUMENT_TS_YYYY_MM_DD.dat). The filename will be found "
266 "automatically if not specified.");
270 "A list of individual spectra (pixel IDs) to read, specified "
271 "as e.g. 10:20. Only used if set.");
273 auto mustBePositive = std::make_shared<BoundedValidator<int>>();
274 mustBePositive->setLower(1);
276 "If loading the file by sections ('chunks'), this is the "
277 "section number of this execution of the algorithm.");
279 "If loading the file by sections ('chunks'), this is the "
280 "total number of sections.");
287 std::vector<std::string> propOptions{
"Auto",
"Serial",
"Parallel"};
288 declareProperty(
"UseParallelProcessing",
"Auto", std::make_shared<StringListValidator>(propOptions),
289 "Use multiple cores for loading the data?\n"
290 " Auto: Use serial loading for small data sets, parallel "
291 "for large data sets.\n"
292 " Serial: Use a single core.\n"
293 " Parallel: Use all available cores.");
297 "The name of the workspace that will be created, filled with the read-in "
298 "data and stored in the [[Analysis Data Service]].");
303 "Optional output table workspace containing the event log "
304 "(pixel) information. ");
307 std::vector<std::string> vecfunmode{
"LoadData",
"Filter",
"ExamineEventLog"};
308 declareProperty(
"FunctionMode",
"LoadData", std::make_shared<StringListValidator>(vecfunmode),
309 "Function mode for different purpose. ");
316 "Pixel IDs for event log. Must have 2 (or more) entries. ");
319 "Pixel ID tags for event log. Must have same items as 'LogPixelIDs'. ");
322 "Freuqency of the accelerator at "
323 "which the experiment runs. It "
324 "can 20, 30 or 60.");
326 declareProperty(
"CorrectTOFtoSample",
false,
"Correct TOF to sample position. ");
340 m_progress = std::make_unique<Progress>(
this, 0.0, 1.0, 100);
359 <<
"It is forced to use input frequency, while all "
360 "events' pulse time will be "
361 <<
"set to " << frame <<
"-th freme. "
364 throw std::runtime_error(
"Operation frequency is not self-consistent");
385 for (int64_t i = 0; i < numberOfSpectra; i++) {
414 throw std::out_of_range(
"ChunkNumber cannot be larger than TotalChunks");
437 g_log.
warning(
"Generated pulse ID file name does not point to an "
459 g_log.
warning() <<
"In functional mode ExamineEventLog, pixel ID must be given!"
461 throw std::runtime_error(
"Incorrect input.");
470 throw std::runtime_error(
"Input log pixel IDs must have more than 2 entries. ");
472 throw std::runtime_error(
"Input log pixel tags must have the same number of items as "
493 throw runtime_error(
"Only 20, 30 and 60Hz are supported. ");
511 m_progress->report(
"Creating output workspace");
518 tempworkspace->initialize(1, 1, 1);
521 tempworkspace->setYUnit(
"Counts");
522 tempworkspace->setTitle(
"Dummy Title");
532 g_log.
notice() <<
"Pulse time 0 = " << pulse0.totalNanoseconds() <<
"\n";
534 tempworkspace->mutableRun().addProperty(
"run_start",
pulsetimes[0].toISO8601String(),
true);
547 if (mapping_filename.empty()) {
550 if (!mapping_filename.empty())
561 size_t nSpec = tempworkspace->getInstrument()->getDetectorIDs(
true).size();
564 auto ws = createWorkspace<EventWorkspace>(nSpec, 2, 1);
577 std::map<PixelType, size_t>::iterator mit;
581 size_t mindex = mit->second;
583 g_log.
error() <<
"Wrong Index " << mindex <<
" for Pixel " << pid <<
'\n';
584 throw std::invalid_argument(
"Wrong array index for pixel from map");
591 std::stringstream ssname;
592 ssname <<
"Pixel" << pid;
593 std::string logname = ssname.str();
601 g_log.
information() <<
"Added Log " << logname <<
" to output workspace. \n";
607 if (!evlog.empty()) {
610 evtablews->addColumn(
"int",
"Pixel-ID");
611 evtablews->addColumn(
"int",
"NumberOfEvents");
614 std::map<PixelType, size_t>::iterator git;
615 for (git = this->
wrongdetidmap.begin(); git != this->wrongdetidmap.end(); ++git) {
617 size_t vindex = git->second;
619 TableRow temprow = evtablews->appendRow();
624 setProperty(
"EventLogTableWorkspace", std::dynamic_pointer_cast<ITableWorkspace>(evtablews));
639 for (
size_t k = 0; k < nbins; k++) {
642 int64_t abstime_ns = pulsetime.totalNanoseconds() +
static_cast<int64_t
>(tof * 1000);
643 DateAndTime abstime(abstime_ns);
647 property->addValue(abstime,
value);
653 g_log.
information() <<
"Size of Property " <<
property->name() <<
" = " <<
property->size()
654 <<
" vs Original Log Size = " << nbins <<
"\n";
665 g_log.
warning() <<
"Event log of map index " << mindex <<
" has " << nbins
666 <<
" entries. There is no need to do statistic on it. "
670 std::vector<int64_t> vec_logtime(nbins);
671 for (
size_t i = 0; i < nbins; ++i) {
673 int64_t templogtime = ptime.totalNanoseconds() +
static_cast<int64_t
>(
wrongdetid_tofs[mindex][i] * 1000.);
675 vec_logtime[i] = templogtime;
679 std::sort(vec_logtime.begin(), vec_logtime.end());
682 int64_t min_dt = vec_logtime[1] - vec_logtime[0];
683 int64_t max_dt = min_dt;
684 int64_t sum_dt = min_dt;
685 int64_t numzeros = 0;
686 for (
size_t i = 2; i < nbins; ++i) {
687 int64_t temp_dt = vec_logtime[i] - vec_logtime[i - 1];
693 if (temp_dt < min_dt)
695 else if (temp_dt > max_dt)
700 double avg_dt =
static_cast<double>(sum_dt) /
static_cast<double>(nbins - 1);
701 g_log.
information() <<
"Event log of map index " << mindex <<
": Avg(dt) = " << avg_dt * 1.0E-9
702 <<
", Min(dt) = " <<
static_cast<double>(min_dt) * 1.0E-9
703 <<
", Max(dt) = " <<
static_cast<double>(max_dt) * 1.0E-9 <<
"\n";
705 g_log.
information() <<
"Event log of map index " << mindex <<
": Avg(dt) = " <<
static_cast<double>(sum_dt) * 1.0E-9
706 <<
", Min(dt) = " <<
static_cast<double>(min_dt) * 1.0E-9
707 <<
", Max(dt) = " <<
static_cast<double>(max_dt) * 1.0E-9 <<
"\n";
710 g_log.
information() <<
"Number of zero-interval eveng log = " << numzeros <<
"\n";
722 string instrument = Poco::Path(eventfilename).getFileName();
726 std::reverse(eventExts.begin(), eventExts.end());
728 for (
auto &eventExt : eventExts) {
729 size_t pos = instrument.find(eventExt);
730 if (pos != string::npos) {
731 instrument = instrument.substr(0, pos);
737 size_t pos = instrument.rfind(
'_');
738 instrument = instrument.substr(0, pos);
744 loadInst->setPropertyValue(
"InstrumentName", instrument);
747 loadInst->executeAsChildAlg();
751 localWorkspace->populateInstrumentParameters();
773 const auto &detectorInfo =
workspace->detectorInfo();
774 const auto &detIDs = detectorInfo.detectorIDs();
777 const auto it = std::max_element(detIDs.cbegin(), detIDs.cend());
785 size_t workspaceIndex = 0;
787 for (
size_t i = 0; i < detectorInfo.size(); ++i) {
788 if (!detectorInfo.isMonitor(i)) {
810 size_t numBlocks = (
m_maxNumEvents + loadBlockSize - 1) / loadBlockSize;
812 std::string procMode =
getProperty(
"UseParallelProcessing");
813 if (procMode ==
"Serial") {
815 }
else if (procMode ==
"Parallel") {
824 double setUpTime = double(detectorInfo.size()) * 10e-6;
832 g_log.
notice(
"In function mode 'ExamineEventLog', processing mode is "
833 "forced to serial. ");
851 std::vector<EventWorkspace_sptr> partWorkspaces;
852 std::vector<DasEvent *> buffers;
855 using EventVector_pt = std::vector<TofEvent> *;
857 EventVector_pt **eventVectors;
860 size_t numThreads = 1;
864 partWorkspaces.resize(numThreads);
865 buffers.resize(numThreads);
866 eventVectors =
new EventVector_pt *[numThreads];
869 g_log.
information() <<
"Processing input event preNexus by " << numThreads <<
" threads"
870 <<
" in " << numBlocks <<
" blocks. "
874 for (
int i = 0; i < int(numThreads); i++) {
879 m_progress->report(
"Creating Partial Workspace");
884 partWorkspaces[i] = partWS;
889 buffers[i] =
new DasEvent[loadBlockSize];
893 eventVectors[i] =
new EventVector_pt[
m_detid_max + 1];
894 EventVector_pt *theseEventVectors = eventVectors[i];
898 theseEventVectors[j] = &partWS->getSpectrum(wi).getEvents();
902 g_log.
information() << tim <<
" to create " << partWorkspaces.size() <<
" workspaces for parallel loading."
905 m_progress->resetNumSteps(numBlocks, 0.1, 0.8);
911 for (
int blockNum = 0; blockNum < int(numBlocks); blockNum++) {
916 size_t threadNum = 0;
919 ws = partWorkspaces[threadNum];
924 DasEvent *event_buffer = buffers[threadNum];
927 EventVector_pt *theseEventVectors = eventVectors[threadNum];
930 size_t fileOffset =
m_firstEvent + (loadBlockSize * blockNum);
932 size_t current_event_buffer_size =
933 (blockNum == int(numBlocks - 1)) ? (
m_maxNumEvents - (numBlocks - 1) * loadBlockSize) : loadBlockSize;
937 current_event_buffer_size =
m_eventFile->loadBlockAt(event_buffer, fileOffset, current_event_buffer_size);
941 procEventsLinear(ws, theseEventVectors, event_buffer, current_event_buffer_size, fileOffset);
961 for (
int iwi = 0; iwi < int(
workspace->getNumberHistograms()); iwi++) {
962 auto wi = size_t(iwi);
970 for (
size_t i = 0; i < numThreads; i++)
971 numEvents += partWorkspaces[i]->getSpectrum(wi).getNumberEvents();
976 for (
size_t i = 0; i < numThreads; i++) {
977 EventList &partEl = partWorkspaces[i]->getSpectrum(wi);
985 g_log.
debug() << tim <<
" to merge workspaces together.\n";
991 for (
size_t i = 0; i < numThreads; i++) {
993 delete[] eventVectors[i];
995 delete[] eventVectors;
1002 g_log.
debug() << tim <<
" to set the proton charge log.\n";
1020 <<
"Number of Wrong Detector IDs = " <<
wrongdetids.size() <<
"\n";
1023 g_log.
notice() <<
"Wrong Detector ID : " << pid <<
'\n';
1027 size_t vindex = detidPair.second;
1045 std::vector<TofEvent> **arrayOfVectors,
DasEvent *event_buffer,
1046 size_t current_event_buffer_size,
size_t fileOffset) {
1051 DateAndTime pulsetime;
1052 auto numPulses =
static_cast<int64_t
>(
m_numPulses);
1054 g_log.
warning() <<
"Event_indices vector is smaller than the pulsetimes array.\n";
1062 int numeventswritten = 0;
1065 size_t local_numErrorEvents = 0;
1066 size_t local_numBadEvents = 0;
1067 size_t local_numIgnoredEvents = 0;
1068 size_t local_numWrongdetidEvents = 0;
1069 size_t local_numGoodEvents = 0;
1071 double local_m_longestTof = 0.;
1074 std::map<PixelType, size_t> local_pidindexmap;
1075 std::vector<std::vector<Types::Core::DateAndTime>> local_pulsetimes;
1076 std::vector<std::vector<double>> local_tofs;
1078 std::set<PixelType> local_wrongdetids;
1079 size_t numwrongpid = 0;
1084 int64_t i_pulse = 0;
1086 for (
size_t ievent = 0; ievent < current_event_buffer_size; ++ievent) {
1088 DasEvent &tempevent = *(event_buffer + ievent);
1096 local_numErrorEvents++;
1097 local_numBadEvents++;
1101 if (pixelid == 1073741843) {
1110 bool iswrongdetid =
false;
1114 iswrongdetid =
true;
1116 ++local_numErrorEvents;
1117 ++local_numWrongdetidEvents;
1118 local_wrongdetids.insert(pixelid);
1123 std::map<int64_t, bool>::iterator it;
1127 local_numIgnoredEvents++;
1134 if (i_pulse < numPulses -
m_istep) {
1136 size_t i_totaloffset = ievent + fileOffset;
1143 while (!((i_totaloffset >= thiseventindex) && (i_totaloffset < nexteventindex))) {
1146 if (i_pulse >= (numPulses -
m_istep))
1158 if (fileOffset == 0 && ievent < 100)
1160 g_log.
notice() << ievent <<
"\t" << i_pulse <<
"\t" << pulsetime <<
"\t"
1161 << tof <<
"\t" << pixelid <<
"\n";
1168 int64_t totaltime = pulsetime.totalNanoseconds() +
static_cast<int64_t
>(tof * 1000);
1170 g_log.
notice() <<
"[EEL] " << numeventswritten <<
"\t\t" << totaltime <<
"\t\t" << pixelid <<
"\t\t" << i_pulse
1171 <<
"\t\t" << fileOffset <<
"\n";
1175 if (!iswrongdetid) {
1178 if (tof < local_m_shortestTof)
1179 local_m_shortestTof = tof;
1180 if (tof > local_m_longestTof)
1181 local_m_longestTof = tof;
1192 arrayOfVectors[pixelid]->emplace_back(tof, pulsetime);
1193 ++local_numGoodEvents;
1195 if (fileOffset == 0 && numeventsprint < 10)
1197 g_log.
notice() <<
"[E10]" <<
"Pulse Time = " << pulsetime <<
", TOF = " << tof
1198 <<
", Pixel ID = " << pixelid
1199 <<
" Pulse index = " << i_pulse <<
", FileOffset =" << fileOffset <<
"\n";
1206 std::map<PixelType, size_t>::iterator it;
1207 it = local_pidindexmap.find(pixelid);
1208 size_t theindex = 0;
1209 if (it == local_pidindexmap.end()) {
1211 size_t newindex = local_pulsetimes.size();
1212 local_pidindexmap[pixelid] = newindex;
1214 std::vector<Types::Core::DateAndTime> tempvectime;
1215 std::vector<double> temptofs;
1216 local_pulsetimes.emplace_back(tempvectime);
1217 local_tofs.emplace_back(temptofs);
1219 theindex = newindex;
1224 theindex = it->second;
1228 local_pulsetimes[theindex].emplace_back(pulsetime);
1229 local_tofs[theindex].emplace_back(tof);
1236 g_log.
debug() <<
"Number of wrong pixel ID = " << numwrongpid <<
" of single block. "
1247 for (
auto tmpid : local_wrongdetids) {
1259 std::vector<Types::Core::DateAndTime> vec_pulsetimes;
1260 std::vector<double> vec_tofs;
1266 mindex = git->second;
1270 auto lit = local_pidindexmap.find(tmpid);
1271 size_t localindex = lit->second;
1275 for (
size_t iv = 0; iv < local_pulsetimes[localindex].size(); iv++) {
1277 this->
wrongdetid_tofs[mindex].emplace_back(local_tofs[localindex][iv]);
1294 size_t numerror = 0;
1296 PRAGMA_OMP(parallel
for schedule(dynamic, 1) )
1302 if (eventindex >
static_cast<uint64_t
>(
m_numEvents)) {
1303 uint64_t realeventindex = eventindex &
VETOFLAG;
1312 bool isveto =
false;
1330 g_log.
debug() <<
"[DB Output]" <<
"Event index " << eventindex
1331 <<
" is corrected to " << realeventindex <<
"\n";
1339 g_log.
error() <<
"EventIndex " << eventindex <<
" of pulse (indexed as " << i <<
") is wrong! "
1340 <<
"Tried to convert them to " << realeventindex <<
" , still exceeding max event index "
1351 PRAGMA_OMP(parallel
for schedule(dynamic, 1) )
1352 for (
int i = 0; i < static_cast<
int>(m_vecEventIndex.size()); ++i) {
1355 uint64_t eventindex = m_vecEventIndex[i];
1356 if (eventindex >
static_cast<uint64_t
>(m_numEvents)) {
1358 g_log.
information() <<
"Check: Pulse " << i <<
": unphysical event index = " << eventindex <<
"\n";
1366 g_log.
notice() <<
"Number of veto pulses = " << numveto <<
", Number of error-event-index pulses = " << numerror
1391 size_t numBlocks = (
m_maxNumEvents + loadBlockSize - 1) / loadBlockSize;
1393 std::string procMode =
getProperty(
"UseParallelProcessing");
1394 if (procMode ==
"Serial") {
1396 }
else if (procMode ==
"Parallel") {
1405 double setUpTime = double(detectorsize) * 10e-6;
1414 g_log.
warning() <<
"Only serial mode is supported at this moment for filtering. "
1421 std::vector<EventWorkspace_sptr> partWorkspaces;
1422 std::vector<DasEvent *> buffers;
1425 using EventVector_pt = std::vector<TofEvent> *;
1427 EventVector_pt **eventVectors;
1430 size_t numThreads = 1;
1434 partWorkspaces.resize(numThreads);
1435 buffers.resize(numThreads);
1436 eventVectors =
new EventVector_pt *[numThreads];
1439 g_log.
information() <<
"Processing input event preNexus by " << numThreads <<
" threads"
1440 <<
" in " << numBlocks <<
" blocks. "
1444 for (
int i = 0; i < int(numThreads); i++) {
1449 m_progress->report(
"Creating Partial Workspace");
1454 partWorkspaces[i] = partWS;
1459 buffers[i] =
new DasEvent[loadBlockSize];
1463 eventVectors[i] =
new EventVector_pt[
m_detid_max + 1];
1464 EventVector_pt *theseEventVectors = eventVectors[i];
1468 if (wi !=
static_cast<size_t>(-1))
1469 theseEventVectors[j] = &partWS->getSpectrum(wi).getEvents();
1471 theseEventVectors[j] =
nullptr;
1475 g_log.
information() << tim <<
" to create " << partWorkspaces.size() <<
" workspaces for parallel loading."
1478 m_progress->resetNumSteps(numBlocks, 0.1, 0.8);
1484 for (
int blockNum = 0; blockNum < int(numBlocks); blockNum++) {
1489 size_t threadNum = 0;
1492 ws = partWorkspaces[threadNum];
1497 DasEvent *event_buffer = buffers[threadNum];
1500 EventVector_pt *theseEventVectors = eventVectors[threadNum];
1503 size_t fileOffset =
m_firstEvent + (loadBlockSize * blockNum);
1505 size_t current_event_buffer_size =
1506 (blockNum == int(numBlocks - 1)) ? (
m_maxNumEvents - (numBlocks - 1) * loadBlockSize) : loadBlockSize;
1510 current_event_buffer_size =
m_eventFile->loadBlockAt(event_buffer, fileOffset, current_event_buffer_size);
1514 filterEventsLinear(ws, theseEventVectors, event_buffer, current_event_buffer_size, fileOffset);
1534 for (
int iwi = 0; iwi < int(
m_localWorkspace->getNumberHistograms()); iwi++) {
1535 auto wi = size_t(iwi);
1543 for (
size_t i = 0; i < numThreads; i++)
1544 numEvents += partWorkspaces[i]->getSpectrum(wi).getNumberEvents();
1549 for (
size_t i = 0; i < numThreads; i++) {
1550 EventList &partEl = partWorkspaces[i]->getSpectrum(wi);
1553 partEl.
clear(
false);
1558 g_log.
debug() << tim <<
" to merge workspaces together.\n";
1564 for (
size_t i = 0; i < numThreads; i++) {
1565 delete[] buffers[i];
1566 delete[] eventVectors[i];
1568 delete[] eventVectors;
1575 g_log.
debug() << tim <<
" to set the proton charge log.\n";
1593 g_log.
notice() <<
"Wrong Detector ID : " << wrongdetid <<
'\n';
1597 size_t vindex = detidPair.second;
1615 std::vector<TofEvent> **arrayOfVectors,
DasEvent *event_buffer,
1616 size_t current_event_buffer_size,
size_t fileOffset) {
1621 DateAndTime pulsetime;
1622 auto numPulses =
static_cast<int64_t
>(
m_numPulses);
1624 g_log.
warning() <<
"Event_indices vector is smaller than the pulsetimes array.\n";
1633 size_t local_numErrorEvents = 0;
1634 size_t local_numBadEvents = 0;
1635 size_t local_numIgnoredEvents = 0;
1636 size_t local_numGoodEvents = 0;
1638 double local_m_longestTof = 0.;
1643 std::map<PixelType, size_t> local_pidindexmap;
1644 std::vector<std::vector<Types::Core::DateAndTime> > local_pulsetimes;
1645 std::vector<std::vector<double> > local_tofs;
1651 int filterstatus = -1;
1652 DateAndTime logpulsetime;
1654 bool definedfilterstatus =
false;
1655 if (fileOffset == 0) {
1658 definedfilterstatus =
false;
1660 size_t firstindex = 1234567890;
1661 for (
size_t i = 0; i <= current_event_buffer_size; ++i) {
1662 DasEvent &tempevent = *(event_buffer + i);
1666 definedfilterstatus =
true;
1671 definedfilterstatus =
true;
1680 if (!definedfilterstatus) {
1681 g_log.
error() <<
"File offset " << fileOffset <<
" unable to find a previoiusly defined log event. "
1684 g_log.
warning() <<
"File offset " << fileOffset <<
" 1-st event log at index = " << firstindex
1685 <<
", status = " << filterstatus <<
"\n";
1691 throw std::runtime_error(
"Instrument is not setup in m_localWorkspace.");
1692 IComponent_const_sptr source = std::dynamic_pointer_cast<const IComponent>(instrument->getSource());
1694 throw std::runtime_error(
"Source is not set up in local workspace.");
1699 bool firstlogevent =
true;
1700 int64_t i_pulse = 0;
1701 int64_t boundtime(0);
1702 int64_t boundindex(0);
1703 int64_t prevbtime(0);
1707 const auto &detIds = detectorInfo.detectorIDs();
1709 double l1 = detectorInfo.l1();
1712 for (
size_t ievent = 0; ievent < current_event_buffer_size; ++ievent) {
1715 DasEvent &tempevent = *(event_buffer + ievent);
1723 local_numErrorEvents++;
1724 local_numBadEvents++;
1727 bool islogevent =
false;
1728 bool iswrongdetid =
false;
1731 if (pixelid == 1073741843) {
1744 if (firstlogevent && definedfilterstatus) {
1745 if (filterstatus != -1)
1746 g_log.
error() <<
"Pre-defined filter status is wrong of fileoffset = " << fileOffset
1747 <<
" at index = " << ievent <<
"\n";
1748 firstlogevent =
false;
1752 boundindex = ievent;
1755 if (firstlogevent && definedfilterstatus) {
1756 if (filterstatus != 1)
1757 g_log.
error() <<
"pre-defined filter status is wrong of fileoffset = " << fileOffset
1758 <<
" at index = " << ievent <<
"\n";
1759 firstlogevent =
false;
1763 boundindex = ievent;
1766 iswrongdetid =
true;
1769 int64_t i_totaloffsetX = ievent + fileOffset;
1770 bool dbprint = (i_totaloffsetX == 23551354 || i_totaloffsetX == -117704);
1772 g_log.
notice() <<
"[Special] ievent = " << i_totaloffsetX <<
", Filter status = " << filterstatus
1773 <<
", Prev-boundary-pixel = " << boundpixel <<
"\n";
1779 std::map<int64_t, bool>::iterator it;
1789 if (i_pulse < numPulses -
m_istep) {
1791 size_t i_totaloffset = ievent + fileOffset;
1798 while (!((i_totaloffset >= thiseventindex) && (i_totaloffset < nexteventindex))) {
1800 if (i_pulse >= (numPulses -
m_istep))
1803 thiseventindex = nexteventindex;
1816 g_log.
notice() <<
"[E] Event " << ievent <<
"\t: Pulse ID = " << i_pulse <<
", Pulse Time = " << pulsetime
1817 <<
", TOF = " << tof <<
", Pixel ID = " << pixelid <<
"\n";
1823 bool reversestatus(
false);
1826 prevbtime = boundtime;
1827 boundtime = pulsetime.totalNanoseconds() +
static_cast<int64_t
>(tof * 1000);
1828 logpulsetime = pulsetime;
1833 if (std::find(detIds.begin(), detIds.end(), pixelid) == detIds.end())
1834 throw std::runtime_error(
"Unable to get access to detector ");
1837 double l2 = detectorInfo.l2(pixelid);
1838 factor = (l1) / (l1 +
l2);
1843 abstime = pulsetime.totalNanoseconds() +
static_cast<int64_t
>(tof * factor * 1000);
1845 abstime = pulsetime.totalNanoseconds() +
static_cast<int64_t
>(tof * 1000);
1846 if (abstime < boundtime) {
1849 reversestatus =
true;
1852 g_log.
warning() <<
"Event " << ievent + fileOffset <<
" is behind an event log though it is earlier. "
1853 <<
"Diff = " << boundtime - abstime <<
" ns \n";
1858 g_log.
notice() <<
"[Special] Event " << ievent + fileOffset <<
" Revert status = " << reversestatus
1859 <<
", Filter-status = " << filterstatus <<
"\n";
1863 int currstatus = filterstatus;
1865 g_log.
notice() <<
"[Special] A Event " << ievent + fileOffset <<
" Revert status = " << reversestatus
1866 <<
", current-status = " << currstatus <<
", Filter-status = " << filterstatus <<
"\n";
1868 currstatus = -filterstatus;
1870 g_log.
notice() <<
"[Special] B Event " << ievent + fileOffset <<
" Revert status = " << reversestatus
1871 <<
", current-status = " << currstatus <<
", Filter-status = " << filterstatus <<
"\n";
1872 if (!iswrongdetid && !islogevent && currstatus > 0) {
1876 g_log.
notice() <<
"[Special] ievent = " << i_totaloffsetX <<
", Filter In "
1881 if (tof < local_m_shortestTof)
1882 local_m_shortestTof = tof;
1883 if (tof > local_m_longestTof)
1884 local_m_longestTof = tof;
1890 arrayOfVectors[pixelid]->emplace_back(tof, pulsetime);
1891 ++local_numGoodEvents;
1894 if (fileOffset == 0 && numeventsprint < 10) {
1895 g_log.
notice() <<
"[E10] Event " << ievent <<
"\t: Pulse ID = " << i_pulse <<
", Pulse Time = " << pulsetime
1896 <<
", TOF = " << tof <<
", Pixel ID = " << pixelid <<
"\n";
1902 g_log.
notice() <<
"[Event_DB11A] Index = " << ievent + fileOffset <<
", AbsTime = " << abstime
1903 <<
", Pulse time = " << pulsetime <<
", TOF = " << tof <<
", Bound Index = " << boundindex
1904 <<
", Boundary time = " << boundtime <<
", Prev Boundary time = " << prevbtime
1905 <<
", Boundary Pixel = " << boundpixel <<
", Pixell ID = " << pixelid <<
"\n";
1910 g_log.
notice() <<
"[Special] ievent = " << i_totaloffsetX <<
", Filter Out "
1915 g_log.
notice() <<
"[Event_DB11B] Index = " << ievent + fileOffset <<
", AbsTime = " << abstime
1916 <<
", Pulse time = " << pulsetime <<
", TOF = " << tof <<
", Bound Index = " << boundindex
1917 <<
", Boundary time = " << boundtime <<
", Prev Boundary Time = " << prevbtime
1918 <<
", Boundary Pixel = " << boundpixel <<
", Pixell ID = " << pixelid <<
"\n";
1923 std::map<PixelType, size_t>::iterator it;
1924 it = local_pidindexmap.find(pixelid);
1925 size_t theindex = 0;
1926 if (it == local_pidindexmap.end()) {
1928 size_t newindex = local_pulsetimes.size();
1929 local_pidindexmap[pixelid] = newindex;
1931 std::vector<Types::Core::DateAndTime> tempvectime;
1932 std::vector<double> temptofs;
1933 local_pulsetimes.emplace_back(tempvectime);
1934 local_tofs.emplace_back(temptofs);
1936 theindex = newindex;
1941 theindex = it->second;
1945 local_pulsetimes[theindex].emplace_back(pulsetime);
1946 local_tofs[theindex].emplace_back(tof);
1979 const auto &detectorInfo = eventws->detectorInfo();
1980 const auto &detIDs = detectorInfo.detectorIDs();
1983 const auto it = std::max_element(detIDs.cbegin(), detIDs.cend());
1987 m_progress->report(
"Padding Pixels of workspace");
1993 size_t workspaceIndex = 0;
1994 for (
size_t i = 0; i < detectorInfo.size(); ++i) {
1995 if (!detectorInfo.isMonitor(i)) {
2005 return detectorInfo.size();
2014 const auto &detectorInfo = eventws->detectorInfo();
2015 const auto &detIDs = detectorInfo.detectorIDs();
2019 for (
size_t i = 0; i < detectorInfo.size(); ++i) {
2020 if (!detectorInfo.isMonitor(i)) {
2024 EventList &spec = eventws->getSpectrum(workspaceIndex);
2040 size_t shortestsame = 100;
2041 size_t checksize = 1200;
2047 for (
size_t i = 1; i < checksize; ++i) {
2051 if (curr_event_index != prev_event_index) {
2052 size_t duration = i - istart;
2053 if (duration < shortestsame) {
2056 shortestsame = duration;
2058 prev_event_index = curr_event_index;
2063 int freq = 60 /
static_cast<int>(shortestsame);
2065 g_log.
notice() <<
"Shortest duration = " << shortestsame <<
" ---> "
2066 <<
"Operation frequency = " << freq <<
"\n";
2098 this->
g_log.
information() <<
"Total proton charge of " << integ <<
" microAmp*hours found by integrating.\n";
2109 if (filename.empty()) {
2111 "loaded and thus empty. ");
2125 using std::placeholders::_1;
2126 if (std::find_if(
m_pixelmap.begin(),
m_pixelmap.end(), std::bind(std::greater<PixelType>(), _1, max_pid)) !=
2128 this->
g_log.
warning(
"Pixel id in mapping file was out of bounds. Loading "
2129 "without mapping file");
2149 m_eventFile = std::make_unique<BinaryFile<DasEvent>>(filename);
2161 const int totalChunks =
getProperty(
"TotalChunks");
2165 if (chunk == totalChunks)
2183 if (filename.empty()) {
2188 std::vector<Pulse> pulses;
2201 }
catch (runtime_error &e) {
2205 this->
g_log.
information() <<
"Encountered error in pulseidfile (ignoring file): " << e.what() <<
"\n";
2211 DateAndTime lastPulseDateTime(0, 0);
2213 for (
const auto &pulse : pulses) {
2214 DateAndTime pulseDateTime(
static_cast<int64_t
>(pulse.seconds),
static_cast<int64_t
>(pulse.nanoseconds));
2215 this->
pulsetimes.emplace_back(pulseDateTime);
2218 if (pulseDateTime < lastPulseDateTime)
2221 lastPulseDateTime = pulseDateTime;
2223 double temp = pulse.pCurrent;
2226 this->
g_log.
warning(
"Individual proton charge < 0 being ignored");
double value
The value of the point.
IPeaksWorkspace_sptr workspace
#define PARALLEL_THREAD_NUMBER
#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_CRITICAL(name)
#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 PRAGMA_OMP(expression)
#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...
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.
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.
static bool isEmpty(const NumT toCheck)
checks that the value was not set by users, uses the value in empty double/int.
@ OptionalLoad
to specify a file to read but the file doesn't have to exist
@ Load
allowed here which will be passed to the algorithm
Defines an interface to an algorithm that loads a file so that it can take part in the automatic sele...
void addDetectorID(const detid_t detID)
Add a detector ID to the set of detector IDs.
void setSpectrumNo(specnum_t num)
Sets the the spectrum number of this spectrum.
void addLogData(Kernel::Property *p)
Add a log entry.
This class stores information regarding an experimental run as a series of log entries.
void integrateProtonCharge(const std::string &logname="proton_charge") const
Integrate the proton charge over the whole run time - default log proton_charge.
double getProtonCharge() const
Get the proton charge.
TableRow represents a row in a TableWorkspace.
A property class for workspaces.
std::unique_ptr< Mantid::API::Progress > m_progress
void procEventsLinear(DataObjects::EventWorkspace_sptr &workspace, std::vector< Types::Event::TofEvent > **arrayOfVectors, DasEvent *event_buffer, size_t current_event_buffer_size, size_t fileOffset)
Linear-version of the procedure to process the event file properly.
int m_freqHz
Accelerator operation frequency.
double m_longestTof
Longest TOF limit.
std::size_t m_numPulses
the number of pulses
void procEvents(DataObjects::EventWorkspace_sptr &workspace)
Process the event file properly.
void runLoadInstrument(const std::string &eventfilename, const API::MatrixWorkspace_sptr &localWorkspace)
Load the instrument geometry File.
std::set< PixelType > wrongdetids
detector IDs. Part of error events.
int findRunFrequency()
Use pulse index/ event index to find out the frequency of instrument running.
Mantid::detid_t m_detid_max
The maximum detector ID possible.
int confidence(Kernel::FileDescriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
std::vector< PixelType > m_pixelmap
Map between the DAS pixel IDs and our pixel IDs, used while loading.
bool m_parallelProcessing
Flag to allow for parallel loading.
std::vector< std::vector< double > > wrongdetid_tofs
uint32_t m_numPixel
the number of pixels
~FilterEventsByLogValuePreNexus() override
Virtual destructor.
std::size_t m_numGoodEvents
The number of good events loaded.
std::unique_ptr< Mantid::Kernel::BinaryFile< DasEvent > > m_eventFile
Handles loading from the event file.
void readPulseidFile(const std::string &filename, const bool throwError)
Read a pulse ID file.
bool m_examEventLog
Flag for examine event (log)
std::size_t m_numBadEvents
The number of bad events.
bool m_usingMappingFile
Set to true if a valid Mapping file was provided.
void processProperties()
Process properties.
std::size_t m_numEvents
The number of events in the file.
void filterEvents()
Process the event file properly.
std::vector< Types::Core::DateAndTime > pulsetimes
The times for each pulse.
std::vector< std::string > m_vecLogPixelTag
Log pixel Tags for filtering.
std::size_t m_numIgnoredEvents
the number of events that were ignored (not loaded) because, e.g.
std::vector< int > m_vecLogPixelID
Log pixel IDs for filtering.
void processEventLogs()
Process imbed logs (marked by bad pixel IDs) (1) Add special event log to workspace log (2) (Optional...
int m_pixelid2exam
Pixel ID to exam.
std::size_t m_firstEvent
The first event to load (count from zero)
int m_numevents2write
Number of events to write out.
std::map< PixelType, size_t > wrongdetidmap
void openEventFile(const std::string &filename)
Open an event file.
bool m_throwError
Throw error with bad pulse ID.
DataObjects::EventWorkspace_sptr m_localWorkspace
size_t padOutEmptyPixels(const DataObjects::EventWorkspace_sptr &eventws)
Pad out empty pixel.
std::vector< std::size_t > m_pixelToWkspindex
The value of the vector is the workspace index.
std::vector< std::vector< Types::Core::DateAndTime > > wrongdetid_pulsetimes
void setProtonCharge(DataObjects::EventWorkspace_sptr &workspace)
Add a sample environment log for the proton chage (charge of the pulse in picoCoulombs) and set the s...
void exec() override
Execution code.
std::string m_pulseIDFileName
Pulse ID file.
void loadPixelMap(const std::string &filename)
Load a pixel mapping file.
void doStatToEventLog(size_t mindex)
Perform statistics to event (wrong pixel ID) logs.
std::vector< uint64_t > m_vecEventIndex
The index of the first event in each pulse.
void filterEventsLinear(DataObjects::EventWorkspace_sptr &workspace, std::vector< Types::Event::TofEvent > **arrayOfVectors, DasEvent *event_buffer, size_t current_event_buffer_size, size_t fileOffset)
Linear-version of the procedure to process the event file properly.
double m_shortestTof
Shortest TOF limit.
void addToWorkspaceLog(const std::string &logtitle, size_t mindex)
Add absolute time series to log.
bool m_pulseTimesIncreasing
Whether or not the pulse times are sorted in increasing order.
bool m_loadOnlySomeSpectra
For loading only some spectra.
std::size_t m_maxNumEvents
Number of events to load.
std::vector< double > m_protonCharge
The proton charge on a pulse by pulse basis.
std::string m_functionMode
Function mode.
void setupPixelSpectrumMap(const DataObjects::EventWorkspace_sptr &eventws)
Set up spectrum/detector ID map inside a workspace.
std::string m_eventFileName
Event file.
FilterEventsByLogValuePreNexus()
Constructor.
void unmaskVetoEventIndexes()
Correct wrong event indexes with pulse.
std::map< int64_t, bool > spectraLoadMap
Handle to the loaded spectra map.
std::size_t m_numWrongdetidEvents
The number of events with wrong.
void init() override
Initialisation code.
DataObjects::EventWorkspace_sptr m_localWorkspaceBA
Output EventWorkspace for filtered event B->A.
double m_protonChargeTot
The total proton charge for the run.
DataObjects::EventWorkspace_sptr setupOutputEventWorkspace()
Create, initialize and set up output EventWrokspace.
std::size_t m_numErrorEvents
The number of error events encountered.
std::vector< int64_t > m_spectraList
the list of Spectra
std::vector< Types::Event::TofEvent > & getEvents()
Return the list of TofEvents contained.
void reserve(size_t num) override
Reserve a certain number of entries in event list of the specified eventType.
void clear(const bool removeDetIDs=true) override
Clear the list of events and any associated detector ID's.
This class is intended to fulfill the design specified in <https://github.com/mantidproject/documents...
Support for a property that holds an array of values.
The BinaryFile template is a helper function for loading simple binary files.
size_t getNumElements() const
Returns the # of elements in the file (cached result of getFileSize)
std::vector< T > loadAll()
Loads the entire contents of the file into a pointer to a std::vector.
std::vector< T > loadAllIntoVector()
Loads the entire contents of the file into a std::vector.
CPUTimer : Timer that uses the CPU time, rather than wall-clock time to measure execution time.
Defines a wrapper around an open file.
static bool isAscii(const std::string &filename, const size_t nbytes=256)
Returns true if the file is considered ascii.
std::istream & data()
Access the open file stream.
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 setPropertySettings(const std::string &name, std::unique_ptr< IPropertySettings > settings)
void debug(const std::string &msg)
Logs at debug level.
void notice(const std::string &msg)
Logs at notice level.
void error(const std::string &msg)
Logs at error level.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
OptionalBool : Tri-state bool.
virtual void setUnits(const std::string &unit)
Sets the units of the property, as a string.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
A specialised Property class for holding a series of time-value pairs.
void addValues(const std::vector< Types::Core::DateAndTime > ×, const std::vector< TYPE > &values)
Adds vectors of values to the map.
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
static const string BLOCK_SIZE_PARAM("LoadingBlockSize")
static const double CURRENT_CONVERSION
Conversion factor between picoColumbs and microAmp*hours.
bool exists(::NeXus::File &file, const std::string &name)
Based on the current group in the file, does the named sub-entry exist?
static const string PULSEID_PARAM("PulseidFilename")
static string getRunnumber(const string &filename)
Get run number.
static string generatePulseidName(string eventfile)
Generate pulse ID.
int PixelType
DetermineChunking : Workflow algorithm to determine chunking.
static const string PID_PARAM("SpectrumList")
static const uint64_t VETOFLAG(72057594037927935)
Veto mask as 0xFF000000000.
static const string OUT_PARAM("OutputWorkspace")
std::size_t numEvents(::NeXus::File &file, bool &hasTotalCounts, bool &oldNeXusFileNames, const std::string &prefix, const NexusHDF5Descriptor &descriptor)
Get the number of events in the currently opened group.
static const string PARALLEL_PARAM("UseParallelProcessing")
static string generateMappingfileName(EventWorkspace_sptr &wksp)
Generate mapping file name.
static const string MAP_PARAM("MappingFilename")
static const double TOF_CONVERSION
Conversion factor between 100 nanoseconds and 1 microsecond.
static const string EVENT_PARAM("EventFilename")
static const PixelType ERROR_PID
All pixel ids with matching this mask are errors.
static const uint32_t MAX_TOF_UINT32
The maximum possible tof as native type.
static const string EVENT_EXTS[]
static const string PULSE_EXTS[]
std::shared_ptr< TableWorkspace > TableWorkspace_sptr
shared pointer to Mantid::DataObjects::TableWorkspace
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
static const size_t DEFAULT_BLOCK_SIZE
Default number of items to read in from any of the files.
Helper class which provides the Collimation Length for SANS instruments.
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
int32_t detid_t
Typedef for a detector ID.
int32_t specnum_t
Typedef for a spectrum Number.
Structure that matches the form in the binary event list.
DasTofType tof
Time of flight.
PixelType pid
Pixel identifier as published by the DAS/DAE/DAQ.
@ Output
An output workspace.