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