Mantid
Loading...
Searching...
No Matches
LoadEventPreNexus2.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
8#include "MantidAPI/Axis.h"
12#include "MantidAPI/Run.h"
27#include "MantidKernel/Glob.h"
34
35#include <algorithm>
36#include <functional>
37#include <set>
38#include <sstream>
39#include <stdexcept>
40#include <vector>
41
42#if BOOST_VERSION < 107100
43#include <boost/timer.hpp>
44#else
45#include <boost/timer/timer.hpp>
46#include <filesystem>
47#endif
48
49namespace Mantid::DataHandling {
50
51DECLARE_FILELOADER_ALGORITHM(LoadEventPreNexus2)
52
53using namespace Kernel;
54using namespace API;
55using namespace Geometry;
56using namespace DataObjects;
57
58using DataObjects::EventList;
59using DataObjects::EventWorkspace;
61using std::ifstream;
62using std::runtime_error;
63using std::string;
64using std::stringstream;
65using std::vector;
66using Types::Core::DateAndTime;
67using Types::Event::TofEvent;
68
69//------------------------------------------------------------------------------------------------
70// constants for locating the parameters to use in execution
71//------------------------------------------------------------------------------------------------
72static const string EVENT_PARAM("EventFilename");
73static const string PULSEID_PARAM("PulseidFilename");
74static const string MAP_PARAM("MappingFilename");
75static const string PID_PARAM("SpectrumList");
76static const string OUT_PARAM("OutputWorkspace");
77
79static const PixelType ERROR_PID = 0x80000000;
81static const uint32_t MAX_TOF_UINT32 = std::numeric_limits<uint32_t>::max();
83static const double TOF_CONVERSION = .1;
85static const double CURRENT_CONVERSION = 1.e-6 / 3600.;
87static const uint64_t VETOFLAG(72057594037927935);
88
89static const string EVENT_EXTS[] = {"_neutron_event.dat", "_neutron0_event.dat", "_neutron1_event.dat",
90 "_neutron2_event.dat", "_neutron3_event.dat", "_neutron4_event.dat",
91 "_live_neutron_event.dat"};
92static const string PULSE_EXTS[] = {"_pulseid.dat", "_pulseid0.dat", "_pulseid1.dat", "_pulseid2.dat",
93 "_pulseid3.dat", "_pulseid4.dat", "_live_pulseid.dat"};
94static const int NUM_EXT = 7;
95
96//-----------------------------------------------------------------------------
97// Statistic Functions
98//-----------------------------------------------------------------------------
99
100//----------------------------------------------------------------------------------------------
103static string getRunnumber(const string &filename) {
104 // start by trimming the filename
105 string runnumber(std::filesystem::path(filename).stem().string());
106
107 if (runnumber.find("neutron") >= string::npos)
108 return "0";
109
110 std::size_t left = runnumber.find('_');
111 std::size_t right = runnumber.find('_', left + 1);
112
113 return runnumber.substr(left + 1, right - left - 1);
114}
115
116//----------------------------------------------------------------------------------------------
119static string generatePulseidName(string eventfile) {
120 // initialize vector of endings and put live at the beginning
121 vector<string> eventExts(EVENT_EXTS, EVENT_EXTS + NUM_EXT);
122 std::reverse(eventExts.begin(), eventExts.end());
123 vector<string> pulseExts(PULSE_EXTS, PULSE_EXTS + NUM_EXT);
124 std::reverse(pulseExts.begin(), pulseExts.end());
125
126 // look for the correct ending
127 for (std::size_t i = 0; i < eventExts.size(); ++i) {
128 size_t start = eventfile.find(eventExts[i]);
129 if (start != string::npos)
130 return eventfile.replace(start, eventExts[i].size(), pulseExts[i]);
131 }
132
133 // give up and return nothing
134 return "";
135}
136
137//----------------------------------------------------------------------------------------------
141 // get the name of the mapping file as set in the parameter files
142 std::vector<string> temp = wksp->getInstrument()->getStringParameter("TS_mapping_file");
143 if (temp.empty())
144 return "";
145 string mapping = temp[0];
146 // Try to get it from the working directory
147 std::filesystem::path localmap(mapping);
148 if (std::filesystem::exists(localmap))
149 return mapping;
150
151 // Try to get it from the data directories
152 string dataversion = Mantid::API::FileFinder::Instance().getFullPath(mapping);
153 if (!dataversion.empty())
154 return dataversion;
155
156 // get a list of all proposal directories
157 string instrument = wksp->getInstrument()->getName();
158 std::filesystem::path base("/SNS/" + instrument + "/");
159 // try short instrument name
160 if (!std::filesystem::exists(base)) {
161 instrument = Kernel::ConfigService::Instance().getInstrument(instrument).shortName();
162 base = std::filesystem::path("/SNS/" + instrument + "/");
163 if (!std::filesystem::exists(base))
164 return "";
165 }
166 vector<string> dirs;
167 for (const auto &entry : std::filesystem::directory_iterator(base)) {
168 if (entry.is_directory()) {
169 dirs.push_back(entry.path().filename().string());
170 }
171 }
172
173 // check all of the proposals for the mapping file in the canonical place
174 const string CAL("_CAL");
175 const size_t CAL_LEN = CAL.length(); // cache to make life easier
176 vector<string> files;
177 for (const auto &dir : dirs) {
178 if ((dir.length() > CAL_LEN) && (dir.compare(dir.length() - CAL.length(), CAL.length(), CAL) == 0)) {
179 std::filesystem::path path = base / dir / "calibrations" / mapping;
180 if (std::filesystem::exists(path))
181 files.emplace_back(path.string());
182 }
183 }
184
185 if (files.empty())
186 return "";
187 else if (files.size() == 1)
188 return files[0];
189 else // just assume that the last one is the right one, this should never be
190 // fired
191 return *(files.rbegin());
192}
193
194//----------------------------------------------------------------------------------------------
202 if (descriptor.extension().rfind("dat") == std::string::npos)
203 return 0;
204
205 // If this looks like a binary file where the exact file length is a
206 // multiple
207 // of the DasEvent struct then we're probably okay.
208 if (descriptor.isAscii())
209 return 0;
210
211 const size_t objSize = sizeof(DasEvent);
212 auto &handle = descriptor.data();
213 // get the size of the file in bytes and reset the handle back to the
214 // beginning
215 handle.seekg(0, std::ios::end);
216 const auto filesize = static_cast<size_t>(handle.tellg());
217 handle.seekg(0, std::ios::beg);
218
219 if (filesize % objSize == 0)
220 return 80;
221 else
222 return 0;
223}
224
225//----------------------------------------------------------------------------------------------
229 : Mantid::API::IFileLoader<Kernel::FileDescriptor>(), prog(nullptr), spectra_list(), pulsetimes(), event_indices(),
230 proton_charge(), proton_charge_tot(0), pixel_to_wkspindex(), pixelmap(), detid_max(), eventfile(nullptr),
231 num_events(0), num_pulses(0), numpixel(0), num_good_events(0), num_error_events(0), num_bad_events(0),
232 num_wrongdetid_events(0), num_ignored_events(0), first_event(0), max_events(0), using_mapping_file(false),
233 loadOnlySomeSpectra(false), spectraLoadMap(), longest_tof(0), shortest_tof(0), parallelProcessing(false),
234 pulsetimesincreasing(false), m_dbOutput(false), m_dbOpBlockNumber(0), m_dbOpNumEvents(0), m_dbOpNumPulses(0) {
235 deprecatedDate("2025-05-06");
236}
237
238//----------------------------------------------------------------------------------------------
242 // which files to use
243 vector<string> eventExts(EVENT_EXTS, EVENT_EXTS + NUM_EXT);
244 declareProperty(std::make_unique<FileProperty>(EVENT_PARAM, "", FileProperty::Load, eventExts),
245 "The name of the neutron event file to read, including its full or "
246 "relative path. In most cases, the file typically ends in "
247 "neutron_event.dat (N.B. case sensitive if running on Linux).");
248 vector<string> pulseExts(PULSE_EXTS, PULSE_EXTS + NUM_EXT);
249 declareProperty(std::make_unique<FileProperty>(PULSEID_PARAM, "", FileProperty::OptionalLoad, pulseExts),
250 "File containing the accelerator pulse information; the "
251 "filename will be found automatically if not specified.");
252 declareProperty(std::make_unique<FileProperty>(MAP_PARAM, "", FileProperty::OptionalLoad, ".dat"),
253 "File containing the pixel mapping (DAS pixels to pixel IDs) file "
254 "(typically INSTRUMENT_TS_YYYY_MM_DD.dat). The filename will be found "
255 "automatically if not specified.");
256
257 // which pixels to load
259 "A list of individual spectra (pixel IDs) to read, specified "
260 "as e.g. 10:20. Only used if set.");
261
262 auto mustBePositive = std::make_shared<BoundedValidator<int>>();
263 mustBePositive->setLower(1);
264 declareProperty("ChunkNumber", EMPTY_INT(), mustBePositive,
265 "If loading the file by sections ('chunks'), this is the "
266 "section number of this execution of the algorithm.");
267 declareProperty("TotalChunks", EMPTY_INT(), mustBePositive,
268 "If loading the file by sections ('chunks'), this is the "
269 "total number of sections.");
270 // TotalChunks is only meaningful if ChunkNumber is set
271 // Would be nice to be able to restrict ChunkNumber to be <= TotalChunks at
272 // validation
273 setPropertySettings("TotalChunks", std::make_unique<VisibleWhenProperty>("ChunkNumber", IS_NOT_DEFAULT));
274
275 std::vector<std::string> propOptions{"Auto", "Serial", "Parallel"};
276 declareProperty("UseParallelProcessing", "Auto", std::make_shared<StringListValidator>(propOptions),
277 "Use multiple cores for loading the data?\n"
278 " Auto: Use serial loading for small data sets, parallel "
279 "for large data sets.\n"
280 " Serial: Use a single core.\n"
281 " Parallel: Use all available cores.");
282
283 // the output workspace name
285 "The name of the workspace that will be created, filled "
286 "with the read-in "
287 "data and stored in the [[Analysis Data Service]].");
288
289 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("EventNumberWorkspace", "", Direction::Output,
291 "Workspace with number of events per pulse");
292
293 // Some debugging options
294 auto mustBeNonNegative = std::make_shared<BoundedValidator<int>>();
295 mustBeNonNegative->setLower(0);
296 declareProperty("DBOutputBlockNumber", EMPTY_INT(), mustBeNonNegative,
297 "Index of the loading block for debugging output. ");
298
299 declareProperty("DBNumberOutputEvents", 40, mustBePositive,
300 "Number of output events for debugging purpose. Must be "
301 "defined with DBOutputBlockNumber.");
302
303 declareProperty("DBNumberOutputPulses", EMPTY_INT(), mustBePositive,
304 "Number of output pulses for debugging purpose. ");
305
306 std::string dbgrp = "Investigation Use";
307 setPropertyGroup("EventNumberWorkspace", dbgrp);
308 setPropertyGroup("DBOutputBlockNumber", dbgrp);
309 setPropertyGroup("DBNumberOutputEvents", dbgrp);
310 setPropertyGroup("DBNumberOutputPulses", dbgrp);
311}
312
313//----------------------------------------------------------------------------------------------
322 g_log.information("Executing LoadEventPreNexus Ver 2.0");
323
324 // Process input properties
325 // a. Check 'chunk' properties are valid, if set
326 const int chunks = getProperty("TotalChunks");
327 if (!isEmpty(chunks) && int(getProperty("ChunkNumber")) > chunks) {
328 throw std::out_of_range("ChunkNumber cannot be larger than TotalChunks");
329 }
330
331 prog = std::make_unique<Progress>(this, 0.0, 1.0, 100);
332
333 // b. what spectra (pixel ID's) to load
334 this->spectra_list = this->getProperty(PID_PARAM);
335
336 // c. the event file is needed in case the pulseid fileanme is empty
337 string event_filename = this->getPropertyValue(EVENT_PARAM);
338 string pulseid_filename = this->getPropertyValue(PULSEID_PARAM);
339 bool throwError = true;
340 if (pulseid_filename.empty()) {
341 pulseid_filename = generatePulseidName(event_filename);
342 if (!pulseid_filename.empty()) {
343 if (std::filesystem::exists(pulseid_filename)) {
344 this->g_log.information() << "Found pulseid file " << pulseid_filename << '\n';
345 throwError = false;
346 } else {
347 pulseid_filename = "";
348 }
349 }
350 }
351
353
354 // Read input files
355 prog->report("Loading Pulse ID file");
356 this->readPulseidFile(pulseid_filename, throwError);
357 prog->report("Loading Event File");
358 this->openEventFile(event_filename);
359
360 // Correct event indexes mased by veto flag
362
363 // Optinally output event number / pulse file
364 std::string diswsname = getPropertyValue("EventNumberWorkspace");
365 if (!diswsname.empty()) {
367 setProperty("EventNumberWorkspace", disws);
368 }
369
370 // Create otuput Workspace
371 prog->report("Creating output workspace");
372 createOutputWorkspace(event_filename);
373
374 // Process the events into pixels
376
377 // Set output
378 this->setProperty<IEventWorkspace_sptr>(OUT_PARAM, localWorkspace);
379
380 // Fast frequency sample environment data
381 this->processImbedLogs();
382
383} // exec()
384
385//------------------------------------------------------------------------------------------------
388void LoadEventPreNexus2::createOutputWorkspace(const std::string &event_filename) {
389 // Create the output workspace
391
392 // Make sure to initialize. We can use dummy numbers for arguments, for
393 // event
394 // workspace it doesn't matter
395 localWorkspace->initialize(1, 1, 1);
396
397 // Set the units
398 localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create("TOF");
399 localWorkspace->setYUnit("Counts");
400
401 // Set title
402 localWorkspace->setTitle("Dummy Title");
403
404 // Property run_start
405 if (this->num_pulses > 0) {
406 // add the start of the run as a ISO8601 date/time string. The start = the
407 // first pulse.
408 // (this is used in LoadInstrument to find the right instrument file to
409 // use).
410 localWorkspace->mutableRun().addProperty("run_start", pulsetimes[0].toISO8601String(), true);
411 }
412
413 // Property run_number
414 localWorkspace->mutableRun().addProperty("run_number", getRunnumber(event_filename));
415
416 // Get the instrument!
417 prog->report("Loading Instrument");
418 this->runLoadInstrument(event_filename, localWorkspace);
419
420 // load the mapping file
421 prog->report("Loading Mapping File");
422 string mapping_filename = this->getPropertyValue(MAP_PARAM);
423 if (mapping_filename.empty()) {
424 mapping_filename = generateMappingfileName(localWorkspace);
425 if (!mapping_filename.empty())
426 this->g_log.information() << "Found mapping file \"" << mapping_filename << "\"\n";
427 }
428 this->loadPixelMap(mapping_filename);
429
430 // Replace workspace by workspace of correct size
431 // Number of non-monitors in instrument
432 size_t nSpec = localWorkspace->getInstrument()->getDetectorIDs(true).size();
433 if (!this->spectra_list.empty())
434 nSpec = this->spectra_list.size();
435 auto tmp = createWorkspace<EventWorkspace>(nSpec, 2, 1);
436 WorkspaceFactory::Instance().initializeFromParent(*localWorkspace, *tmp, true);
437 localWorkspace = std::move(tmp);
438}
439
440//------------------------------------------------------------------------------------------------
444 // Unmask veto bit from vetoed events
445
447 for (int i = 0; i < static_cast<int>(event_indices.size()); ++i) {
449
450 uint64_t eventindex = event_indices[i];
451 if (eventindex > static_cast<uint64_t>(max_events)) {
452 // Is veto, use the unmasked event index
453 uint64_t realeventindex = eventindex & VETOFLAG;
454 event_indices[i] = realeventindex;
455 }
456
457 // Check
458 uint64_t eventindexcheck = event_indices[i];
459 if (eventindexcheck > static_cast<uint64_t>(max_events)) {
460 g_log.information() << "Check: Pulse " << i << ": unphysical event index = " << eventindexcheck << "\n";
461 }
463 }
465}
466
467//------------------------------------------------------------------------------------------------
474 // Generate workspace of 2 spectrum
475 size_t nspec = 2;
476 size_t sizex = event_indices.size();
477 size_t sizey = sizex;
478 MatrixWorkspace_sptr disws = std::dynamic_pointer_cast<MatrixWorkspace>(
479 WorkspaceFactory::Instance().create("Workspace2D", nspec, sizex, sizey));
480
481 g_log.debug() << "Event indexes size = " << event_indices.size() << ", "
482 << "Number of pulses = " << pulsetimes.size() << "\n";
483
484 // Put x-values
485 for (size_t i = 0; i < 2; ++i) {
486 auto &dataX = disws->mutableX(i);
487 dataX[0] = 0;
488 for (size_t j = 0; j < sizex; ++j) {
489 int64_t time = pulsetimes[j].totalNanoseconds() - pulsetimes[0].totalNanoseconds();
490 dataX[j] = static_cast<double>(time) * 1.0E-9;
491 }
492 }
493
494 // Put y-values
495 auto &dataY0 = disws->mutableY(0);
496 auto &dataY1 = disws->mutableY(1);
497
498 dataY0[0] = 0;
499 dataY1[1] = static_cast<double>(event_indices[0]);
500
501 for (size_t i = 1; i < sizey; ++i) {
502 dataY0[i] = static_cast<double>(event_indices[i] - event_indices[i - 1]);
503 dataY1[i] = static_cast<double>(event_indices[i]);
504 }
505
506 return disws;
507}
508
509//----------------------------------------------------------------------------------------------
513 for (const auto pid : this->wrongdetids) {
514 // a. pixel ID -> index
515 const auto mit = this->wrongdetidmap.find(pid);
516 size_t mindex = mit->second;
517 if (mindex > this->wrongdetid_pulsetimes.size()) {
518 g_log.error() << "Wrong Index " << mindex << " for Pixel " << pid << '\n';
519 throw std::invalid_argument("Wrong array index for pixel from map");
520 } else {
521 g_log.information() << "Processing imbed log marked by Pixel " << pid
522 << " with size = " << this->wrongdetid_pulsetimes[mindex].size() << '\n';
523 }
524
525 std::stringstream ssname;
526 ssname << "Pixel" << pid;
527 std::string logname = ssname.str();
528
529 // d. Add this to log
530 this->addToWorkspaceLog(logname, mindex);
531
532 g_log.notice() << "Processed imbedded log " << logname << "\n";
533
534 } // ENDFOR pit
535}
536
537//----------------------------------------------------------------------------------------------
544void LoadEventPreNexus2::addToWorkspaceLog(const std::string &logtitle, size_t mindex) {
545 // Create TimeSeriesProperty
546 auto property = new TimeSeriesProperty<double>(logtitle);
547
548 // Add entries
549 size_t nbins = this->wrongdetid_pulsetimes[mindex].size();
550 for (size_t k = 0; k < nbins; k++) {
551 double tof = this->wrongdetid_tofs[mindex][k];
552 DateAndTime pulsetime = wrongdetid_pulsetimes[mindex][k];
553 int64_t abstime_ns = pulsetime.totalNanoseconds() + static_cast<int64_t>(tof * 1000);
554 DateAndTime abstime(abstime_ns);
555 property->addValue(abstime, tof);
556 } // ENDFOR
557
558 g_log.information() << "Size of Property " << property->name() << " = " << property->size()
559 << " vs Original Log Size = " << nbins << "\n";
560
561 // Add property to workspace
562 localWorkspace->mutableRun().addProperty(std::move(property), false);
563}
564
565//----------------------------------------------------------------------------------------------
571void LoadEventPreNexus2::runLoadInstrument(const std::string &eventfilename,
572 const MatrixWorkspace_sptr &localWorkspace) {
573 // start by getting just the filename
574 string instrument = std::filesystem::path(eventfilename).filename().string();
575
576 // initialize vector of endings and put live at the beginning
577 vector<string> eventExts(EVENT_EXTS, EVENT_EXTS + NUM_EXT);
578 std::reverse(eventExts.begin(), eventExts.end());
579
580 for (const auto &ending : eventExts) {
581 size_t pos = instrument.find(ending);
582 if (pos != string::npos) {
583 instrument.resize(pos);
584 break;
585 }
586 }
587
588 // determine the instrument parameter file
589 size_t pos = instrument.rfind('_'); // get rid of the run number
590 instrument.resize(pos);
591
592 // do the actual work
593 auto loadInst = createChildAlgorithm("LoadInstrument");
594
595 // Now execute the Child Algorithm. Catch and log any error, but don't stop.
596 loadInst->setPropertyValue("InstrumentName", instrument);
597 loadInst->setProperty<MatrixWorkspace_sptr>("Workspace", localWorkspace);
598 loadInst->setProperty("RewriteSpectraMap", Mantid::Kernel::OptionalBool(false));
599 loadInst->executeAsChildAlg();
600
601 // Populate the instrument parameters in this workspace - this works around
602 // a
603 // bug
604 localWorkspace->populateInstrumentParameters();
605}
606
607//----------------------------------------------------------------------------------------------
611inline void LoadEventPreNexus2::fixPixelId(PixelType &pixel, uint32_t &period) const {
612 if (!this->using_mapping_file) { // nothing to do here
613 period = 0;
614 return;
615 }
616
617 PixelType unmapped_pid = pixel % this->numpixel;
618 period = (pixel - unmapped_pid) / this->numpixel;
619 pixel = this->pixelmap[unmapped_pid];
620}
621
622//----------------------------------------------------------------------------------------------
627 //-------------------------------------------------------------------------
628 // Initialize statistic counters
629 //-------------------------------------------------------------------------
630 this->num_error_events = 0;
631 this->num_good_events = 0;
632 this->num_ignored_events = 0;
633 this->num_bad_events = 0;
634 this->num_wrongdetid_events = 0;
635
636 shortest_tof = static_cast<double>(MAX_TOF_UINT32) * TOF_CONVERSION;
637 longest_tof = 0.;
638
639 // Set up loading parameters
640 size_t loadBlockSize = Mantid::Kernel::DEFAULT_BLOCK_SIZE * 2;
641 size_t numBlocks = (max_events + loadBlockSize - 1) / loadBlockSize;
642
643 // We want to pad out empty pixels.
644 const auto &detectorInfo = workspace->detectorInfo();
645 const auto &detIDs = detectorInfo.detectorIDs();
646
647 // Determine processing mode
648 std::string procMode = getProperty("UseParallelProcessing");
649 if (procMode == "Serial")
650 parallelProcessing = false;
651 else if (procMode == "Parallel")
652 parallelProcessing = true;
653 else {
654 // Automatic determination. Loading serially (for me) is about 3 million
655 // events per second,
656 // (which is sped up by ~ x 3 with parallel processing, say 10 million per
657 // second, e.g. 7 million events more per seconds).
658 // compared to a setup time/merging time of about 10 seconds per million
659 // detectors.
660 double setUpTime = double(detectorInfo.size()) * 10e-6;
661 parallelProcessing = ((double(max_events) / 7e6) > setUpTime);
662 g_log.debug() << (parallelProcessing ? "Using" : "Not using") << " parallel processing.\n";
663 }
664
665 // determine maximum pixel id
666 const auto it = std::max_element(detIDs.cbegin(), detIDs.cend());
667 detid_max = it == detIDs.cend() ? 0 : *it;
668
669 // For slight speed up
670 loadOnlySomeSpectra = (!this->spectra_list.empty());
671
672 // Turn the spectra list into a map, for speed of access
673 for (const auto &spectrum : spectra_list)
674 spectraLoadMap[spectrum] = true;
675
676 // Pad all the pixels
677 prog->report("Padding Pixels");
678 this->pixel_to_wkspindex.reserve(detid_max + 1); // starting at zero up to and including detid_max
679 // Set to zero
680 this->pixel_to_wkspindex.assign(detid_max + 1, 0);
681 size_t workspaceIndex = 0;
682 specnum_t spectrumNumber = 1;
683 for (size_t i = 0; i < detectorInfo.size(); ++i) {
684 if (!detectorInfo.isMonitor(i)) {
685 if (!loadOnlySomeSpectra || (spectraLoadMap.find(detIDs[i]) != spectraLoadMap.end())) {
686 this->pixel_to_wkspindex[detIDs[i]] = workspaceIndex;
687 EventList &spec = workspace->getSpectrum(workspaceIndex);
688 spec.setDetectorID(detIDs[i]);
689 spec.setSpectrumNo(spectrumNumber);
690 ++workspaceIndex;
691 } else {
692 this->pixel_to_wkspindex[detIDs[i]] = -1;
693 }
694 ++spectrumNumber;
695 }
696 }
697
698 CPUTimer tim;
699
700 //-------------------------------------------------------------------------
701 // Create the partial workspaces
702 //-------------------------------------------------------------------------
703 // Vector of partial workspaces, for parallel processing.
704 std::vector<EventWorkspace_sptr> partWorkspaces;
705 std::vector<DasEvent *> buffers;
706
708 using EventVector_pt = std::vector<TofEvent> *;
710 EventVector_pt **eventVectors;
711
713 size_t numThreads = 1;
715 numThreads = size_t(PARALLEL_GET_MAX_THREADS);
716
717 partWorkspaces.resize(numThreads);
718 buffers.resize(numThreads);
719 eventVectors = new EventVector_pt *[numThreads];
720
721 PRAGMA_OMP( parallel for if (parallelProcessing) )
722 for (int i = 0; i < int(numThreads); i++) {
723 // This is the partial workspace we are about to create (if in parallel)
724 EventWorkspace_sptr partWS;
725 if (parallelProcessing) {
726 prog->report("Creating Partial Workspace");
727 // Create a partial workspace, copy all the spectra numbers and stuff
728 // (no actual events to copy though).
729 partWS = workspace->clone();
730 // Push it in the array
731 partWorkspaces[i] = partWS;
732 } else
733 partWS = workspace;
734
735 // Allocate the buffers
736 buffers[i] = new DasEvent[loadBlockSize];
737
738 // For each partial workspace, make an array where index = detector ID and
739 // value = pointer to the events vector
740 eventVectors[i] = new EventVector_pt[detid_max + 1];
741 EventVector_pt *theseEventVectors = eventVectors[i];
742 for (detid_t j = 0; j < detid_max + 1; ++j) {
743 size_t wi = pixel_to_wkspindex[j];
744 // Save a POINTER to the vector<tofEvent>
745 if (wi != static_cast<size_t>(-1))
746 theseEventVectors[j] = &partWS->getSpectrum(wi).getEvents();
747 else
748 theseEventVectors[j] = nullptr;
749 }
750 }
751
752 g_log.information() << tim << " to create " << partWorkspaces.size()
753 << " workspaces (same as number of threads) for parallel loading " << numBlocks << " blocks. "
754 << "\n";
755
756 prog->resetNumSteps(numBlocks, 0.1, 0.8);
757
758 //-------------------------------------------------------------------------
759 // LOAD THE DATA
760 //-------------------------------------------------------------------------
761
762 PRAGMA_OMP( parallel for schedule(dynamic, 1) if (parallelProcessing) )
763 for (int blockNum = 0; blockNum < int(numBlocks); blockNum++) {
765
766 // Find the workspace for this particular thread
768 size_t threadNum = 0;
769 if (parallelProcessing) {
770 threadNum = PARALLEL_THREAD_NUMBER;
771 ws = partWorkspaces[threadNum];
772 } else
773 ws = workspace;
774
775 // Get the buffer (for this thread)
776 DasEvent *event_buffer = buffers[threadNum];
777
778 // Get the speeding-up array of vector<tofEvent> where index = detid.
779 EventVector_pt *theseEventVectors = eventVectors[threadNum];
780
781 // Where to start in the file?
782 size_t fileOffset = first_event + (loadBlockSize * blockNum);
783 // May need to reduce size of last (or only) block
784 size_t current_event_buffer_size =
785 (blockNum == int(numBlocks - 1)) ? (max_events - (numBlocks - 1) * loadBlockSize) : loadBlockSize;
786
787 // Load this chunk of event data (critical block)
788 PARALLEL_CRITICAL(LoadEventPreNexus2_fileAccess) {
789 current_event_buffer_size = eventfile->loadBlockAt(event_buffer, fileOffset, current_event_buffer_size);
790 }
791
792 // This processes the events. Can be done in parallel!
793 bool dbprint = m_dbOutput && (blockNum == m_dbOpBlockNumber);
794 procEventsLinear(ws, theseEventVectors, event_buffer, current_event_buffer_size, fileOffset, dbprint);
795
796 // Report progress
797 prog->report("Load Event PreNeXus");
798
800 }
802
803 g_log.debug() << tim << " to load the data.\n";
804
805 //-------------------------------------------------------------------------
806 // MERGE WORKSPACES BACK TOGETHER
807 //-------------------------------------------------------------------------
808 if (parallelProcessing) {
810 prog->resetNumSteps(workspace->getNumberHistograms(), 0.8, 0.95);
811
812 // Merge all workspaces, index by index.
814 for (int iwi = 0; iwi < int(workspace->getNumberHistograms()); iwi++) {
815 auto wi = size_t(iwi);
816
817 // The output event list.
818 EventList &el = workspace->getSpectrum(wi);
819 el.clear(false);
820
821 // How many events will it have?
822 size_t numEvents = 0;
823 for (size_t i = 0; i < numThreads; i++)
824 numEvents += partWorkspaces[i]->getSpectrum(wi).getNumberEvents();
825 // This will avoid too much copying.
826 el.reserve(numEvents);
827
828 // Now merge the event lists
829 for (size_t i = 0; i < numThreads; i++) {
830 EventList &partEl = partWorkspaces[i]->getSpectrum(wi);
831 el += partEl.getEvents();
832 // Free up memory as you go along.
833 partEl.clear(false);
834 }
835 prog->report("Merging Workspaces");
836 }
837 g_log.debug() << tim << " to merge workspaces together.\n";
839 }
841
842 //-------------------------------------------------------------------------
843 // Clean memory
844 //-------------------------------------------------------------------------
845
846 // Delete the buffers for each thread.
847 for (size_t i = 0; i < numThreads; i++) {
848 delete[] buffers[i];
849 delete[] eventVectors[i];
850 }
851 delete[] eventVectors;
852 // delete [] pulsetimes;
853
854 prog->resetNumSteps(3, 0.94, 1.00);
855
856 //-------------------------------------------------------------------------
857 // Finalize loading
858 //-------------------------------------------------------------------------
859 prog->report("Setting proton charge");
860 this->setProtonCharge(workspace);
861 g_log.debug() << tim << " to set the proton charge log."
862 << "\n";
863
864 // Make sure the MRU is cleared
865 workspace->clearMRU();
866
867 // Now, create a default X-vector for histogramming, with just 2 bins.
868 auto axis = HistogramData::BinEdges{shortest_tof - 1, longest_tof + 1};
869 workspace->setAllX(axis);
870 this->pixel_to_wkspindex.clear();
871
872 /* Disabled! Final process on wrong detector id events
873 for (size_t vi = 0; vi < this->wrongdetid_abstimes.size(); vi ++){
874 std::sort(this->wrongdetid_abstimes[vi].begin(),
875 this->wrongdetid_abstimes[vi].end());
876 }
877 */
878
879 //-------------------------------------------------------------------------
880 // Final message output
881 //-------------------------------------------------------------------------
882 g_log.notice() << "Read " << this->num_good_events << " events + " << this->num_error_events << " errors"
883 << ". Shortest TOF: " << shortest_tof << " microsec; longest TOF: " << longest_tof << " microsec."
884 << "\n"
885 << "Bad Events = " << this->num_bad_events
886 << " Events of Wrong Detector = " << this->num_wrongdetid_events << ", "
887 << "Number of Wrong Detector IDs = " << this->wrongdetids.size() << "\n";
888
889 for (auto wit = this->wrongdetids.begin(); wit != this->wrongdetids.end(); ++wit) {
890 g_log.notice() << "Wrong Detector ID : " << *wit << '\n';
891 }
892 for (auto git = this->wrongdetidmap.begin(); git != this->wrongdetidmap.end(); ++git) {
893 PixelType tmpid = git->first;
894 size_t vindex = git->second;
895 g_log.notice() << "Pixel " << tmpid
896 << ": Total number of events = " << this->wrongdetid_pulsetimes[vindex].size() << '\n';
897 }
898} // End of procEvents
899
900//----------------------------------------------------------------------------------------------
913 std::vector<TofEvent> **arrayOfVectors, DasEvent *event_buffer,
914 size_t current_event_buffer_size, size_t fileOffset, bool dbprint) {
915 // Starting pulse time
916 DateAndTime pulsetime;
917 int64_t pulse_i = 0;
918 auto numPulses = static_cast<int64_t>(num_pulses);
919 if (event_indices.size() < num_pulses) {
920 g_log.warning() << "Event_indices vector is smaller than the pulsetimes array.\n";
921 numPulses = static_cast<int64_t>(event_indices.size());
922 }
923
924 // Local stastic parameters
925 size_t local_num_error_events = 0;
926 size_t local_num_bad_events = 0;
927 size_t local_num_wrongdetid_events = 0;
928 size_t local_num_ignored_events = 0;
929 size_t local_num_good_events = 0;
930 double local_shortest_tof = static_cast<double>(MAX_TOF_UINT32) * TOF_CONVERSION;
931 double local_longest_tof = 0.;
932
933 // Storages
934 std::map<PixelType, size_t> local_pidindexmap;
935 std::vector<std::vector<Types::Core::DateAndTime>> local_pulsetimes;
936 std::vector<std::vector<double>> local_tofs;
937 std::set<PixelType> local_wrongdetids;
938
939 // process the individual events
940 std::stringstream dbss;
941 // size_t numwrongpid = 0;
942 for (size_t i = 0; i < current_event_buffer_size; i++) {
943 const DasEvent &temp = *(event_buffer + i);
944 PixelType pid = temp.pid;
945 bool iswrongdetid = false;
946
947 if (dbprint && i < m_dbOpNumEvents)
948 dbss << i << " \t" << temp.tof << " \t" << temp.pid << "\n";
949
950 // Filter out bad event
951 if ((pid & ERROR_PID) == ERROR_PID) {
952 local_num_error_events++;
953 local_num_bad_events++;
954 continue;
955 }
956
957 // Covert the pixel ID from DAS pixel to our pixel ID
958 // downstream monitor pixel for SNAP
959 if (pid == 1073741843)
960 pid = 1179648;
961 else if (this->using_mapping_file) {
962 PixelType unmapped_pid = pid % this->numpixel;
963 pid = this->pixelmap[unmapped_pid];
964 }
965
966 // Wrong pixel IDs
967 if (pid > static_cast<PixelType>(detid_max)) {
968 iswrongdetid = true;
969
970 local_num_error_events++;
971 local_num_wrongdetid_events++;
972 local_wrongdetids.insert(pid);
973 }
974
975 // Now check if this pid we want to load.
976 if (loadOnlySomeSpectra && !iswrongdetid) {
977 std::map<int64_t, bool>::iterator it;
978 it = spectraLoadMap.find(pid);
979 if (it == spectraLoadMap.end()) {
980 // Pixel ID was not found, so the event is being ignored.
981 local_num_ignored_events++;
982 continue;
983 }
984 }
985
986 // Upon this point, only 'good' events are left to work on
987
988 // Pulse: Find the pulse time for this event index
989 if (pulse_i < numPulses - 1) {
990 // This is the total offset into the file
991 size_t total_i = i + fileOffset;
992 // Go through event_index until you find where the index increases to
993 // encompass the current index.
994 // Your pulse = the one before.
995 while (!((total_i >= event_indices[pulse_i]) && (total_i < event_indices[pulse_i + 1]))) {
996 pulse_i++;
997 if (pulse_i >= (numPulses - 1))
998 break;
999 }
1000
1001 // Save the pulse time at this index for creating those events
1002 pulsetime = pulsetimes[pulse_i];
1003 } // Find pulse time
1004
1005 // TOF
1006 double tof = static_cast<double>(temp.tof) * TOF_CONVERSION;
1007
1008 if (!iswrongdetid) {
1009 // Regular event that is belonged to a defined detector
1010 // Find the overall max/min tof
1011 if (tof < local_shortest_tof)
1012 local_shortest_tof = tof;
1013 if (tof > local_longest_tof)
1014 local_longest_tof = tof;
1015
1016 // This is equivalent to
1017 // workspace->getSpectrum(this->pixel_to_wkspindex[pid]).addEventQuickly(event);
1018 // But should be faster as a bunch of these calls were cached.
1019 arrayOfVectors[pid]->emplace_back(tof, pulsetime);
1020 ++local_num_good_events;
1021 } else {
1022 // Special events/Wrong detector id
1023 // i. get/add index of the entry in map
1024 std::map<PixelType, size_t>::iterator it;
1025 it = local_pidindexmap.find(pid);
1026 size_t theindex = 0;
1027 if (it == local_pidindexmap.end()) {
1028 // Initialize it!
1029 size_t newindex = local_pulsetimes.size();
1030 local_pidindexmap[pid] = newindex;
1031
1032 std::vector<Types::Core::DateAndTime> tempvectime;
1033 std::vector<double> temptofs;
1034 local_pulsetimes.emplace_back(tempvectime);
1035 local_tofs.emplace_back(temptofs);
1036
1037 theindex = newindex;
1038
1039 // ++ numwrongpid;
1040
1041 g_log.debug() << "Find New Wrong Pixel ID = " << pid << "\n";
1042 } else {
1043 // existing
1044 theindex = it->second;
1045 }
1046
1047 // ii. calculate and add absolute time
1048 // int64_t abstime = (pulsetime.totalNanoseconds()+int64_t(tof*1000));
1049 local_pulsetimes[theindex].emplace_back(pulsetime);
1050 local_tofs[theindex].emplace_back(tof);
1051
1052 } // END-IF-ELSE: On Event's Pixel's Nature
1053
1054 } // ENDFOR each event
1055
1056 if (dbprint)
1057 g_log.information(dbss.str());
1058
1059 // Update local statistics to their global counterparts
1060 PARALLEL_CRITICAL(LoadEventPreNexus2_global_statistics) {
1061 this->num_good_events += local_num_good_events;
1062 this->num_ignored_events += local_num_ignored_events;
1063 this->num_error_events += local_num_error_events;
1064
1065 this->num_bad_events += local_num_bad_events;
1066 this->num_wrongdetid_events += local_num_wrongdetid_events;
1067
1068 std::set<PixelType>::iterator it;
1069 for (it = local_wrongdetids.begin(); it != local_wrongdetids.end(); ++it) {
1070 PixelType tmpid = *it;
1071 this->wrongdetids.insert(*it);
1072
1073 // Create class map entry if not there
1074 size_t mindex = 0;
1075 auto git = this->wrongdetidmap.find(tmpid);
1076 if (git == this->wrongdetidmap.end()) {
1077 // create entry
1078 size_t newindex = this->wrongdetid_pulsetimes.size();
1079 this->wrongdetidmap[tmpid] = newindex;
1080
1081 std::vector<Types::Core::DateAndTime> temppulsetimes;
1082 std::vector<double> temptofs;
1083 this->wrongdetid_pulsetimes.emplace_back(temppulsetimes);
1084 this->wrongdetid_tofs.emplace_back(temptofs);
1085
1086 mindex = newindex;
1087 } else {
1088 mindex = git->second;
1089 }
1090
1091 // 2. Find local
1092 auto lit = local_pidindexmap.find(tmpid);
1093 size_t localindex = lit->second;
1094
1095 for (size_t iv = 0; iv < local_pulsetimes[localindex].size(); iv++) {
1096 this->wrongdetid_pulsetimes[mindex].emplace_back(local_pulsetimes[localindex][iv]);
1097 this->wrongdetid_tofs[mindex].emplace_back(local_tofs[localindex][iv]);
1098 }
1099 // std::sort(this->wrongdetid_abstimes[mindex].begin(),
1100 // this->wrongdetid_abstimes[mindex].end());
1101 }
1102
1103 if (local_shortest_tof < shortest_tof)
1104 shortest_tof = local_shortest_tof;
1105 if (local_longest_tof > longest_tof)
1106 longest_tof = local_longest_tof;
1107 } // END_CRITICAL
1108}
1109
1110//-----------------------------------------------------------------------------
1120 if (this->proton_charge.empty()) // nothing to do
1121 return;
1122
1123 Run &run = workspace->mutableRun();
1124
1125 // Add the proton charge entries.
1126 TimeSeriesProperty<double> *log = new TimeSeriesProperty<double>("proton_charge");
1127 log->setUnits("picoCoulombs");
1128
1129 // Add the time and associated charge to the log
1130 log->addValues(this->pulsetimes, this->proton_charge);
1131
1133 run.addLogData(std::move(log));
1134
1135 // Force re-integration
1137 double integ = run.getProtonCharge();
1138
1139 g_log.information() << "Total proton charge of " << integ << " microAmp*hours found by integrating.\n";
1140}
1141
1142//-----------------------------------------------------------------------------
1146void LoadEventPreNexus2::loadPixelMap(const std::string &filename) {
1147 this->using_mapping_file = false;
1148
1149 // check that there is a mapping file
1150 if (filename.empty()) {
1151 this->g_log.information("NOT using a mapping file");
1152 return;
1153 }
1154
1155 // actually deal with the file
1156 this->g_log.debug("Using mapping file \"" + filename + "\"");
1157
1158 // Open the file; will throw if there is any problem
1159 BinaryFile<PixelType> pixelmapFile(filename);
1160 auto max_pid = static_cast<PixelType>(pixelmapFile.getNumElements());
1161 // Load all the data
1162 this->pixelmap = pixelmapFile.loadAllIntoVector();
1163
1164 // Check for funky file
1165 using std::placeholders::_1;
1166 if (std::find_if(pixelmap.begin(), pixelmap.end(), std::bind(std::greater<PixelType>(), _1, max_pid)) !=
1167 pixelmap.end()) {
1168 this->g_log.warning("Pixel id in mapping file was out of bounds. Loading "
1169 "without mapping file");
1170 this->numpixel = 0;
1171 this->pixelmap.clear();
1172 this->using_mapping_file = false;
1173 return;
1174 }
1175
1176 // If we got here, the mapping file was loaded correctly and we'll use it
1177 this->using_mapping_file = true;
1178 // Let's assume that the # of pixels in the instrument matches the mapping
1179 // file length.
1180 this->numpixel = static_cast<uint32_t>(pixelmapFile.getNumElements());
1181}
1182
1183//-----------------------------------------------------------------------------
1187void LoadEventPreNexus2::openEventFile(const std::string &filename) {
1188 // Open the file
1189 eventfile = std::make_unique<BinaryFile<DasEvent>>(filename);
1190 num_events = eventfile->getNumElements();
1191 g_log.debug() << "File contains " << num_events << " event records.\n";
1192
1193 // Check if we are only loading part of the event file
1194 const int chunk = getProperty("ChunkNumber");
1195 if (isEmpty(chunk)) // We are loading the whole file
1196 {
1197 first_event = 0;
1199 } else // We are loading part - work out the event number range
1200 {
1201 const int totalChunks = getProperty("TotalChunks");
1202 max_events = num_events / totalChunks;
1203 first_event = (chunk - 1) * max_events;
1204 // Need to add any remainder to the final chunk
1205 if (chunk == totalChunks)
1206 max_events += num_events % totalChunks;
1207 }
1208
1209 g_log.information() << "Reading " << max_events << " event records\n";
1210}
1211
1212//-----------------------------------------------------------------------------
1217void LoadEventPreNexus2::readPulseidFile(const std::string &filename, const bool throwError) {
1218 this->proton_charge_tot = 0.;
1219 this->num_pulses = 0;
1220 this->pulsetimesincreasing = true;
1221
1222 // jump out early if there isn't a filename
1223 if (filename.empty()) {
1224 this->g_log.information("NOT using a pulseid file");
1225 return;
1226 }
1227
1228 std::vector<Pulse> pulses;
1229
1230 // set up for reading
1231 // Open the file; will throw if there is any problem
1232 try {
1233 BinaryFile<Pulse> pulseFile(filename);
1234
1235 // Get the # of pulse
1236 this->num_pulses = pulseFile.getNumElements();
1237 this->g_log.information() << "Using pulseid file \"" << filename << "\", with " << num_pulses << " pulses.\n";
1238
1239 // Load all the data
1240 pulses = pulseFile.loadAll();
1241 } catch (runtime_error &e) {
1242 if (throwError) {
1243 throw;
1244 } else {
1245 this->g_log.information() << "Encountered error in pulseidfile (ignoring file): " << e.what() << "\n";
1246 return;
1247 }
1248 }
1249
1250 if (num_pulses > 0) {
1251 DateAndTime lastPulseDateTime(0, 0);
1252 this->pulsetimes.reserve(num_pulses);
1253 for (const auto &pulse : pulses) {
1254 DateAndTime pulseDateTime(static_cast<int64_t>(pulse.seconds), static_cast<int64_t>(pulse.nanoseconds));
1255 this->pulsetimes.emplace_back(pulseDateTime);
1256 this->event_indices.emplace_back(pulse.event_index);
1257
1258 if (pulseDateTime < lastPulseDateTime)
1259 this->pulsetimesincreasing = false;
1260 else
1261 lastPulseDateTime = pulseDateTime;
1262
1263 double temp = pulse.pCurrent;
1264 this->proton_charge.emplace_back(temp);
1265 if (temp < 0.)
1266 this->g_log.warning("Individual proton charge < 0 being ignored");
1267 else
1268 this->proton_charge_tot += temp;
1269 }
1270 }
1271
1273
1274 if (m_dbOpNumPulses > 0) {
1275 std::stringstream dbss;
1276 for (size_t i = 0; i < m_dbOpNumPulses; ++i)
1277 dbss << "[Pulse] " << i << "\t " << event_indices[i] << "\t " << pulsetimes[i].totalNanoseconds() << '\n';
1278 g_log.information(dbss.str());
1279 }
1280}
1281
1282//----------------------------------------------------------------------------------------------
1286 m_dbOpBlockNumber = getProperty("DBOutputBlockNumber");
1288 m_dbOutput = false;
1290 } else {
1291 m_dbOutput = true;
1292
1293 int numdbevents = getProperty("DBNumberOutputEvents");
1294 m_dbOpNumEvents = static_cast<size_t>(numdbevents);
1295 }
1296
1297 int dbnumpulses = getProperty("DBNumberOutputPulses");
1298 if (!isEmpty(dbnumpulses))
1299 m_dbOpNumPulses = static_cast<size_t>(dbnumpulses);
1300 else
1301 m_dbOpNumPulses = 0;
1302}
1303
1304} // namespace Mantid::DataHandling
gsl_vector * tmp
IPeaksWorkspace_sptr workspace
double left
double right
#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.
Kernel::Logger & g_log
Definition Algorithm.h:422
static bool isEmpty(const NumT toCheck)
checks that the value was not set by users, uses the value in empty double/int.
void deprecatedDate(const std::string &)
The date the algorithm was deprecated on.
@ 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...
Definition IFileLoader.h:19
void setDetectorID(const detid_t detID)
Clear the list of detector IDs, then add one.
Definition ISpectrum.cpp:84
void setSpectrumNo(specnum_t num)
Sets the spectrum number of this spectrum.
void addLogData(Kernel::Property *p)
Add a log entry.
Definition LogManager.h:127
This class stores information regarding an experimental run as a series of log entries.
Definition Run.h:35
void integrateProtonCharge(const std::string &logname="proton_charge") const
Integrate the proton charge over the whole run time - default log proton_charge.
Definition Run.cpp:333
double getProtonCharge() const
Get the proton charge.
Definition Run.cpp:300
A property class for workspaces.
Mantid::detid_t detid_max
The maximum detector ID possible.
std::vector< double > proton_charge
The proton charge on a pulse by pulse basis.
std::size_t num_good_events
The number of good events loaded.
std::map< int64_t, bool > spectraLoadMap
Handle to the loaded spectra map.
std::unique_ptr< Mantid::API::Progress > prog
void procEvents(DataObjects::EventWorkspace_sptr &workspace)
Process the event file properly in parallel.
std::vector< int64_t > spectra_list
the list of Spectra
void processImbedLogs()
Process imbed logs (marked by bad pixel IDs)
void procEventsLinear(DataObjects::EventWorkspace_sptr &workspace, std::vector< Types::Event::TofEvent > **arrayOfVectors, DasEvent *event_buffer, size_t current_event_buffer_size, size_t fileOffset, bool dbprint)
Linear-version of the procedure to process the event file properly.
bool loadOnlySomeSpectra
For loading only some spectra.
std::vector< Types::Core::DateAndTime > pulsetimes
The times for each pulse.
bool using_mapping_file
Set to true if a valid Mapping file was provided.
std::size_t num_error_events
The number of error events encountered.
void init() override
Initialisation code.
std::vector< PixelType > pixelmap
Map between the DAS pixel IDs and our pixel IDs, used while loading.
std::vector< std::vector< Types::Core::DateAndTime > > wrongdetid_pulsetimes
double proton_charge_tot
The total proton charge for the run.
void runLoadInstrument(const std::string &eventfilename, const API::MatrixWorkspace_sptr &localWorkspace)
Load the instrument geometry File.
void unmaskVetoEventIndex()
Some Pulse ID and event indexes might be wrong.
bool pulsetimesincreasing
Whether or not the pulse times are sorted in increasing order.
std::size_t num_events
The number of events in the file.
std::vector< std::vector< double > > wrongdetid_tofs
void processInvestigationInputs()
Processing the input properties for purpose of investigation.
void createOutputWorkspace(const std::string &event_filename)
Create and set up output Event Workspace.
void openEventFile(const std::string &filename)
Open an event file.
bool m_dbOutput
Investigation properties.
std::set< PixelType > wrongdetids
detector IDs. Part of error events.
std::size_t num_bad_events
The number of bad events.
void loadPixelMap(const std::string &filename)
Load a pixel mapping file.
std::vector< uint64_t > event_indices
The index of the first event in each pulse.
void fixPixelId(PixelType &pixel, uint32_t &period) const
Turn a pixel id into a "corrected" pixelid and period.
std::size_t first_event
The first event to load (count from zero)
std::size_t num_pulses
the number of pulses
API::MatrixWorkspace_sptr generateEventDistribtionWorkspace()
Generate a workspace with distribution of events with pulse Workspace has 2 spectrum.
void readPulseidFile(const std::string &filename, const bool throwError)
Read a pulse ID file.
std::size_t num_wrongdetid_events
The number of events with wrong.
std::map< PixelType, size_t > wrongdetidmap
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...
std::size_t num_ignored_events
the number of events that were ignored (not loaded) because, e.g.
void addToWorkspaceLog(const std::string &logtitle, size_t mindex)
Add absolute time series to log.
std::unique_ptr< Mantid::Kernel::BinaryFile< DasEvent > > eventfile
Handles loading from the event file.
bool parallelProcessing
Flag to allow for parallel loading.
DataObjects::EventWorkspace_sptr localWorkspace
std::vector< std::size_t > pixel_to_wkspindex
The value of the vector is the workspace index.
int confidence(Kernel::FileDescriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
std::size_t max_events
Number of events to load.
A class for holding :
Definition EventList.h:57
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.
Definition BinaryFile.h:43
size_t getNumElements() const
Returns the # of elements in the file (cached result of getFileSize)
Definition BinaryFile.h:83
std::vector< T > loadAll()
Loads the entire contents of the file into a pointer to a std::vector.
Definition BinaryFile.h:106
std::vector< T > loadAllIntoVector()
Loads the entire contents of the file into a std::vector.
Definition BinaryFile.h:142
CPUTimer : Timer that uses the CPU time, rather than wall-clock time to measure execution time.
Definition CPUTimer.h:24
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 setPropertyGroup(const std::string &name, const std::string &group)
Set the group for a given property.
void debug(const std::string &msg)
Logs at debug level.
Definition Logger.cpp:145
void notice(const std::string &msg)
Logs at notice level.
Definition Logger.cpp:126
void error(const std::string &msg)
Logs at error level.
Definition Logger.cpp:108
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
OptionalBool : Tri-state bool.
virtual void setUnits(const std::string &unit)
Sets the units of the property, as a string.
Definition Property.cpp:198
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 > &times, const std::vector< TYPE > &values)
Adds vectors of values to the map.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::vector< Types::Event::TofEvent > * EventVector_pt
pointer to the vector of events
static const double CURRENT_CONVERSION
Conversion factor between picoColumbs and microAmp*hours.
static const string PULSEID_PARAM("PulseidFilename")
static string getRunnumber(const string &filename)
Parse preNexus file name to get run number.
static string generatePulseidName(string eventfile)
Generate Pulse ID file name from preNexus event file's name.
int PixelType
DetermineChunking : Workflow algorithm to determine chunking.
static const string PID_PARAM("SpectrumList")
static const uint64_t VETOFLAG(72057594037927935)
Veto flag: 0xFF00000000000.
static const string OUT_PARAM("OutputWorkspace")
static string generateMappingfileName(EventWorkspace_sptr &wksp)
Generate mapping file name from Event workspace's instrument.
static const string MAP_PARAM("MappingFilename")
std::size_t numEvents(Nexus::File &file, bool &hasTotalCounts, bool &oldNeXusFileNames, const std::string &prefix, const Nexus::NexusDescriptor &descriptor)
Get the number of events in the currently opened group.
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< 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 size_t DEFAULT_BLOCK_SIZE
Default number of items to read in from any of the files.
Definition BinaryFile.h:21
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.
Definition EmptyValues.h:24
int32_t detid_t
Typedef for a detector ID.
int32_t specnum_t
Typedef for a spectrum Number.
Definition IDTypes.h:14
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.
Definition Property.h:54