13#include "MantidDataHandling/DllConfig.h"
30#include "MantidNexus/NexusFile.h"
33#include <boost/lexical_cast.hpp>
34#include <boost/scoped_array.hpp>
45namespace DataHandling {
60bool exists(
const std::map<std::string, std::string> &entries,
const std::string &
name);
81 const std::string
name()
const override {
return "LoadEventNexus"; };
84 const std::string
summary()
const override {
85 return "Loads an Event NeXus file and stores as an "
86 "EventWorkspace. Optionally, you can filter out events falling "
87 "outside a range of times-of-flight and/or a time interval.";
91 int version()
const override {
return 1; };
92 const std::vector<std::string>
seeAlso()
const override {
return {
"LoadISISNexus",
"LoadEventAndCompress"}; }
95 const std::string
category()
const override {
return "DataHandling\\Nexus"; }
100 static std::shared_ptr<BankPulseTimes>
101 runLoadNexusLogs(
const std::string &nexusfilename, T localWorkspace,
Algorithm &alg,
bool returnpulsetimes,
104 template <
typename T>
105 static std::shared_ptr<BankPulseTimes>
106 runLoadNexusLogs(
const std::string &nexusfilename, T localWorkspace,
Algorithm &alg,
bool returnpulsetimes,
108 const std::vector<std::string> &allow_list,
const std::vector<std::string> &block_list);
112 const int &nPeriods,
const std::string &nexusfilename, std::string &status);
114 template <
typename T>
115 static void loadEntryMetadata(
const std::string &nexusfilename, T WS,
const std::string &entry_name);
118 template <
typename T>
119 static bool loadInstrument(
const std::string &nexusfilename, T localWorkspace,
const std::string &top_entry_name,
123 template <
typename T>
124 static bool runLoadIDFFromNexus(
const std::string &nexusfilename, T localWorkspace,
const std::string &top_entry_name,
128 template <
typename T>
129 static bool runLoadInstrument(
const std::string &nexusfilename, T localWorkspace,
const std::string &top_entry_name,
136 static std::string readInstrumentFromISIS_VMSCompat(Nexus::File &hFile);
143 std::shared_ptr<EventWorkspaceCollection>
m_ws;
162 bool m_is_time_filtered{
false};
164 bool filter_bad_pulses{
false};
194 void init()
override;
197 void exec()
override;
199 std::map<std::string, std::string> validateInputs()
override;
204 void createSpectraMapping(
const std::string &nxsfile,
const bool monitorsOnly,
205 const std::vector<std::string> &bankNames = std::vector<std::string>());
207 void runLoadMonitors();
209 void setTimeFilters(
const bool monitors);
210 template <
typename T>
211 T filterEventsByTime(T
workspace, Mantid::Types::Core::DateAndTime &startTime,
212 Mantid::Types::Core::DateAndTime &stopTime);
215 std::unique_ptr<std::pair<std::vector<int32_t>, std::vector<int32_t>>>
216 loadISISVMSSpectraMapping(
const std::string &entry_name);
218 template <
typename T>
void filterDuringPause(T
workspace);
221 void setTopEntryName();
224 void safeOpenFile(
const std::string &fname);
272 file.openData(binsName);
274 std::vector<float> tofsFile;
275 file.getData(tofsFile);
280 if (end_wi <= start_wi) {
281 end_wi = localWorkspace->getNumberHistograms();
288 for (
size_t wi = start_wi; wi < end_wi; ++wi) {
290 if (event_list.
empty())
294 auto tofsEventList = event_list.
getTofs();
296 size_t n = tofsFile.size();
298 auto ev = tofsEventList.begin();
299 auto ev_end = tofsEventList.end();
300 for (
size_t i = 1; i <
n; ++i) {
301 double right = double(tofsFile[i]);
303 if ((ev != ev_end) && (
right < *ev)) {
308 while ((ev != ev_end) && (*ev <
right)) {
314 double left = double(tofsFile[i - 1]);
316 std::uniform_real_distribution<double> flat(
left,
right);
317 std::vector<double> random_numbers(
m);
318 std::generate(random_numbers.begin(), random_numbers.end(), [&flat, &rng]() { return flat(rng); });
319 std::sort(random_numbers.begin(), random_numbers.end());
320 auto it = random_numbers.begin();
321 for (
auto ev1 = ev -
m; ev1 != ev; ++ev1, ++it) {
327 event_list.
setTofs(tofsEventList);
347 const std::string &classType) {
350 file.openAddress(
"/");
351 file.openGroup(entry_name,
"NXentry");
353 using string_map_t = std::map<std::string, std::string>;
354 string_map_t entries = file.getEntries();
356 if (classType ==
"NXmonitor") {
357 std::vector<std::string> bankNames;
358 for (string_map_t::const_iterator it = entries.begin(); it != entries.end(); ++it) {
359 const std::string entry_class(it->second);
360 if (entry_class == classType) {
361 const std::string entryName(it->first);
362 bankNames.emplace_back(entryName);
365 for (
size_t i = 0; i < bankNames.size(); ++i) {
366 const std::string &mon = bankNames[i];
367 file.openGroup(mon, classType);
368 entries = file.getEntries();
369 if (entries.find(
"event_time_bins") == entries.end()) {
387 file.openGroup(
"detector_1_events",
"NXevent_data");
388 entries = file.getEntries();
389 for (string_map_t::const_iterator it = entries.begin(); it != entries.end(); ++it) {
390 if (it->first ==
"time_of_flight" || it->first ==
"event_time_bins") {
399 file.openGroup(
"instrument",
"NXinstrument");
400 file.openGroup(
"dae",
"IXdae");
401 entries = file.getEntries();
402 size_t time_channels_number = 0;
403 for (string_map_t::const_iterator it = entries.begin(); it != entries.end(); ++it) {
406 if (it->first.size() > 14 && it->first.substr(0, 14) ==
"time_channels_") {
407 size_t n = boost::lexical_cast<size_t>(it->first.substr(14));
408 if (
n > time_channels_number) {
409 time_channels_number =
n;
413 if (time_channels_number > 0)
415 file.openGroup(
"time_channels_" +
std::to_string(time_channels_number),
"IXtime_channels");
416 entries = file.getEntries();
417 for (string_map_t::const_iterator it = entries.begin(); it != entries.end(); ++it) {
418 if (it->first ==
"time_of_flight" || it->first ==
"event_time_bins") {
446 const std::string &top_entry_name,
Algorithm *alg,
448 std::string instrument;
449 std::string instFilename;
456 instFilename = nexusfilename;
459 Nexus::File nxfile(nexusfilename);
461 nxfile.openGroup(top_entry_name,
"NXentry");
463 nxfile.openGroup(
"instrument",
"NXinstrument");
465 nxfile.openData(
"name");
466 instrument = nxfile.getStrData();
467 alg->
getLogger().
debug() <<
"Instrument name read from NeXus file is " << instrument <<
'\n';
472 if (instrument.empty()) {
474 size_t n = nexusfilename.rfind(
'/');
475 if (
n != std::string::npos) {
476 std::string temp = nexusfilename.substr(
n + 1, nexusfilename.size() -
n - 1);
478 if (
n != std::string::npos &&
n > 0) {
479 instrument = temp.substr(0,
n);
484 if (instrument ==
"POWGEN3")
485 instrument =
"POWGEN";
486 if (instrument ==
"NOM")
487 instrument =
"NOMAD";
489 if (instrument.empty())
490 throw std::runtime_error(
"Could not find the instrument name in the NXS "
491 "file or using the filename. Cannot load "
499 if (instFilename.empty()) {
504 if (instFilename.empty()) {
505 std::filesystem::path directory(Kernel::ConfigService::Instance().getInstrumentDirectory());
506 std::filesystem::path file(instrument +
"_Definition.xml");
507 std::filesystem::path fullPath = directory / file;
508 instFilename = fullPath.string();
517 bool executionSuccessful(
true);
519 loadInst->setPropertyValue(
"Filename", instFilename);
520 loadInst->setPropertyValue(
"InstrumentName", instrument);
527 localWorkspace->populateInstrumentParameters();
528 }
catch (std::invalid_argument &e) {
529 alg->
getLogger().
information() <<
"Invalid argument to LoadInstrument Child Algorithm : " << e.what() <<
'\n';
530 executionSuccessful =
false;
531 }
catch (std::runtime_error &e) {
534 executionSuccessful =
false;
538 if (!executionSuccessful) {
539 alg->
getLogger().
error() <<
"Error loading Instrument definition file\n";
545 const auto &
pmap = localWorkspace->constInstrumentParameters();
546 if (!
pmap.contains(localWorkspace->getInstrument()->getComponentID(),
"det-pos-source"))
547 return executionSuccessful;
549 std::shared_ptr<Geometry::Parameter> updateDets =
550 pmap.get(localWorkspace->getInstrument()->getComponentID(),
"det-pos-source");
551 std::string
value = updateDets->value<std::string>();
552 if (
value.substr(0, 8) ==
"datafile") {
555 updateInst->setPropertyValue(
"Filename", nexusfilename);
556 if (
value ==
"datafile-ignore-phi") {
557 updateInst->setProperty(
"IgnorePhi",
true);
559 "positions in the data file except for the "
562 alg->
getLogger().
information(
"Detector positions in IDF updated with positions in the data file");
566 updateInst->execute();
569 return executionSuccessful;
577 Nexus::File file(nexusfilename);
578 file.openGroup(entry_name,
"NXentry");
581 if (file.hasData(
"/" + entry_name +
"/title")) {
582 file.openData(
"title");
584 std::string title = file.getStrData();
592 if (file.hasData(
"/" + entry_name +
"/notes")) {
593 file.openData(
"notes");
595 std::string notes = file.getStrData();
597 WS->mutableRun().addProperty(
"file_notes", notes,
true);
603 if (file.hasData(
"/" + entry_name +
"/run_number")) {
604 file.openData(
"run_number");
607 run = file.getStrData();
608 }
else if (file.isDataInt()) {
610 std::vector<int>
value;
616 WS->mutableRun().addProperty(
"run_number", run,
true);
622 if (file.hasData(
"/" + entry_name +
"/experiment_identifier")) {
623 file.openData(
"experiment_identifier");
626 expId = file.getStrData();
628 if (!expId.empty()) {
629 WS->mutableRun().addProperty(
"experiment_identifier", expId,
true);
636 if (file.hasGroup(
"/" + entry_name +
"/sample",
"NXsample")) {
637 file.openGroup(
"sample",
"NXsample");
639 if (file.hasData(
"/" + entry_name +
"/sample/name")) {
640 file.openData(
"name");
641 const auto info = file.getInfo();
642 std::string sampleName;
644 if (info.dims.size() == 1) {
645 sampleName = file.getStrData();
647 const int64_t total_length = std::accumulate(info.dims.begin(), info.dims.end(),
static_cast<int64_t
>(1),
648 std::multiplies<int64_t>());
649 boost::scoped_array<char> val_array(
new char[total_length]);
650 file.getData(val_array.get());
651 sampleName = std::string(val_array.get(), total_length);
655 if (!sampleName.empty()) {
656 WS->mutableSample().setName(sampleName);
666 if (file.hasData(
"/" + entry_name +
"/duration")) {
667 file.openData(
"duration");
668 std::vector<double> duration;
669 file.getDataCoerce(duration);
670 if (duration.size() == 1) {
673 if (file.hasAttr(
"units")) {
674 file.getAttr<std::string>(
"units", units);
678 WS->mutableRun().addProperty(
"duration", duration[0], units,
true);
702 const std::string &top_entry_name,
Algorithm *alg,
705 bool loadNexusInstrumentXML =
true;
707 loadNexusInstrumentXML = alg->
getProperty(
"LoadNexusInstrumentXML");
709 bool foundInstrument =
false;
710 if (loadNexusInstrumentXML)
711 foundInstrument = runLoadIDFFromNexus<T>(nexusfilename, localWorkspace, top_entry_name, alg);
712 if (!foundInstrument)
713 foundInstrument = runLoadInstrument<T>(nexusfilename, std::move(localWorkspace), top_entry_name, alg, descriptor);
714 return foundInstrument;
729 const std::string &top_entry_name,
Algorithm *alg) {
732 Nexus::File nxsfile(nexusfilename);
733 nxsfile.openAddress(top_entry_name +
"/instrument/instrument_xml");
735 alg->
getLogger().
information(
"No instrument XML definition found in " + nexusfilename +
" at " + top_entry_name +
744 loadInst->setPropertyValue(
"Filename", nexusfilename);
746 loadInst->setPropertyValue(
"InstrumentParentPath", top_entry_name);
748 }
catch (std::invalid_argument &) {
749 alg->
getLogger().
error(
"Invalid argument to LoadIDFFromNexus Child Algorithm ");
750 }
catch (std::runtime_error &) {
751 alg->
getLogger().
debug(
"No instrument definition found by LoadIDFFromNexus in " + nexusfilename +
" at " +
752 top_entry_name +
"/instrument");
755 if (!loadInst->isExecuted())
757 return loadInst->isExecuted();
double value
The value of the point.
IPeaksWorkspace_sptr workspace
Base class from which all concrete algorithm classes should be derived.
bool existsProperty(const std::string &name) const override
Checks whether the named property is already in the list of managed property.
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 & getLogger() const
Returns a reference to the logger.
Defines an interface to an algorithm that loads a file so that it can take part in the automatic sele...
static std::string getInstrumentFilename(const std::string &instrumentName, const std::string &date="")
Get the IDF using the instrument name and date.
Helper class for reporting progress from algorithms.
EventWorkspaceCollection : Collection of EventWorspaces to give backward-forward compatibility around...
Custom exception extending std::invalid_argument Thrown when nperiods does not match period_log Custo...
InvalidLogPeriods(const std::string &msg)
std::shared_ptr< Mantid::Kernel::TimeROI > bad_pulses_timeroi
double longest_tof
Limits found to tof.
Mantid::Types::Core::DateAndTime filter_time_start
Filter by start time.
double filter_tof_max
Filter by a maximum time-of-flight.
bool loadlogs
Do we load the sample logs?
bool event_id_is_spec
True if the event_id is spectrum no not pixel ID.
size_t discarded_events
A count of events discarded because they came from a pixel that's not in the IDF.
Mantid::Types::Core::DateAndTime filter_time_stop
Filter by stop time.
static bool runLoadInstrument(const std::string &nexusfilename, T localWorkspace, const std::string &top_entry_name, Algorithm *alg, const Nexus::NexusDescriptor *descriptor=nullptr)
Load instrument from IDF file specified by Nexus file.
const std::string summary() const override
Summary of algorithms purpose.
int32_t m_specMax
Maximum spectrum to load.
double compressTolerance
Tolerance for CompressEvents; use -1 to mean don't compress.
const std::string category() const override
Category.
std::string m_filename
The name and path of the input file.
std::shared_ptr< BankPulseTimes > m_allBanksPulseTimes
Pulse times for ALL banks, taken from proton_charge log.
static void loadEntryMetadata(const std::string &nexusfilename, T WS, const std::string &entry_name)
Load the run number and other meta data from the given bank.
static bool loadInstrument(const std::string &nexusfilename, T localWorkspace, const std::string &top_entry_name, Algorithm *alg, const Nexus::NexusDescriptor *descriptor=nullptr)
Load instrument from Nexus file if possible, else from IDF spacified by Nexus file.
const std::vector< std::string > seeAlso() const override
Function to return all of the seeAlso (these are not validated) algorithms related to this algorithm....
double shortest_tof
Limits found to tof.
std::mutex m_tofMutex
Mutex protecting tof limits.
bool filter_tof_range
Tof range is being filtered.
static std::string readInstrumentFromISIS_VMSCompat(Nexus::File &hFile)
method used to return instrument name for some old ISIS files where it is not written properly within...
DataObjects::EventWorkspace_sptr createEmptyEventWorkspace()
const std::string name() const override
function to return a name of the algorithm, must be overridden in all algorithms
std::unique_ptr< Nexus::File > m_file
std::shared_ptr< EventWorkspaceCollection > m_ws
The workspace being filled out.
static bool runLoadIDFFromNexus(const std::string &nexusfilename, T localWorkspace, const std::string &top_entry_name, Algorithm *alg)
Load instrument for Nexus file.
bool m_instrument_loaded_correctly
Was the instrument loaded?
size_t bad_tofs
Count of all the "bad" tofs found.
int32_t m_specMin
Minimum spectrum to load.
int version() const override
Version.
double filter_tof_min
Filter by a minimum time-of-flight.
std::string m_top_entry_name
name of top level NXentry to use
void setTofs(const MantidVec &tofs) override
Set a list of TOFs to the current event list.
void sortTof() const
Sort events by TOF in one thread.
bool empty() const
Much like stl containers, returns true if there is nothing in the event list.
void getTofs(std::vector< double > &tofs) const override
Fill a vector with the list of TOFs.
Exception for when an item is not found in a collection.
void debug(const std::string &msg)
Logs at debug level.
void error(const std::string &msg)
Logs at error level.
void information(const std::string &msg)
Logs at information level.
OptionalBool : Tri-state bool.
A specialised Property class for holding a series of time-value pairs.
Class that provides for a standard Nexus exception.
const std::map< std::string, std::set< std::string > > & getAllEntries() const noexcept
Returns a const reference of the internal map holding all entries in the Nexus HDF5 file.
static unsigned short constexpr CHAR
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
bool isNexus(const std::string &filename)
Determine if the Geometry file type is Nexus.
void makeTimeOfFlightDataFuzzy(Nexus::File &file, T localWorkspace, const std::string &binsName, size_t start_wi=0, size_t end_wi=0)
Load the time of flight data.
std::shared_ptr< EventWorkspaceCollection > EventWorkspaceCollection_sptr
bool exists(Nexus::File &file, const std::string &name)
void loadEvents(API::Progress &prog, const char *progMsg, EP &eventProcessor, const Nexus::NXEntry &entry, uint64_t start_nsec, uint64_t end_nsec)
void adjustTimeOfFlightISISLegacy(Nexus::File &file, T localWorkspace, const std::string &entry_name, const std::string &classType)
ISIS specific method for dealing with wide events.
MANTID_DATAHANDLING_DLL bool doPerformISISEventShift(Nexus::File &file, std::string &topEntryName)
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
Helper class which provides the Collimation Length for SANS instruments.
Generate a tableworkspace to store the calibration results.
std::string to_string(const wide_integer< Bits, Signed > &n)