14#include "MantidDataHandling/DllConfig.h"
29#include <boost/lexical_cast.hpp>
30#include <boost/scoped_array.hpp>
33#include <nexus/NeXusFile.hpp>
34#include <nexus/NeXusException.hpp>
47namespace DataHandling {
60bool exists(::NeXus::File &file,
const std::string &name);
62bool 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);
114 template <
typename T>
115 static void loadEntryMetadata(
const std::string &nexusfilename, T WS,
const std::string &entry_name,
128 template <
typename T>
129 static bool loadInstrument(
const std::string &nexusfilename, T localWorkspace,
const std::string &top_entry_name,
133 template <
typename T>
134 static bool runLoadIDFFromNexus(
const std::string &nexusfilename, T localWorkspace,
const std::string &top_entry_name,
146 template <
typename T>
147 static bool runLoadInstrument(
const std::string &nexusfilename, T localWorkspace,
const std::string &top_entry_name,
154 static std::string readInstrumentFromISIS_VMSCompat(::NeXus::File &hFile);
161 std::shared_ptr<EventWorkspaceCollection>
m_ws;
203 Parallel::ExecutionMode
204 getParallelExecutionMode(
const std::map<std::string, Parallel::StorageMode> &storageModes)
const override;
211 void init()
override;
214 void execLoader()
override;
217 const std::string &classType)
const;
221 void loadEvents(
API::Progress *
const prog,
const bool monitors);
222 void createSpectraMapping(
const std::string &nxsfile,
const bool monitorsOnly,
223 const std::vector<std::string> &bankNames = std::vector<std::string>());
225 void runLoadMonitors();
227 void setTimeFilters(
const bool monitors);
228 template <
typename T>
229 T filterEventsByTime(T
workspace, Mantid::Types::Core::DateAndTime &startTime,
230 Mantid::Types::Core::DateAndTime &stopTime);
233 std::unique_ptr<std::pair<std::vector<int32_t>, std::vector<int32_t>>>
234 loadISISVMSSpectraMapping(
const std::string &entry_name);
236 template <
typename T>
void filterDuringPause(T
workspace);
239 void setTopEntryName();
242 void safeOpenFile(
const std::string &fname);
289 const std::string EVENT_TIME_SHIFT_TAG(
"event_time_offset_shift");
291 const auto entries = file.getEntries();
292 if (entries.find(EVENT_TIME_SHIFT_TAG) != entries.end()) {
293 std::string event_shift_type;
294 file.readData(EVENT_TIME_SHIFT_TAG, event_shift_type);
295 if (event_shift_type ==
"random") {
301 file.openData(binsName);
303 std::vector<float> tofsFile;
304 file.getData(tofsFile);
309 if (end_wi <= start_wi) {
310 end_wi = localWorkspace->getNumberHistograms();
317 for (
size_t wi = start_wi; wi < end_wi; ++wi) {
319 if (event_list.
empty())
323 auto tofsEventList = event_list.
getTofs();
325 size_t n = tofsFile.size();
327 auto ev = tofsEventList.begin();
328 auto ev_end = tofsEventList.end();
329 for (
size_t i = 1; i <
n; ++i) {
330 double right = double(tofsFile[i]);
332 if ((ev != ev_end) && (
right < *ev)) {
337 while ((ev != ev_end) && (*ev <
right)) {
343 double left = double(tofsFile[i - 1]);
345 std::uniform_real_distribution<double> flat(
left,
right);
346 std::vector<double> random_numbers(
m);
347 std::generate(random_numbers.begin(), random_numbers.end(), [&flat, &rng]() { return flat(rng); });
348 std::sort(random_numbers.begin(), random_numbers.end());
349 auto it = random_numbers.begin();
350 for (
auto ev1 = ev -
m; ev1 != ev; ++ev1, ++it) {
356 event_list.
setTofs(tofsEventList);
377 const std::string &classType,
382 file.openGroup(entry_name,
"NXentry");
385 if (descriptor !=
nullptr) {
387 if (!descriptor->isEntry(
"/" + entry_name +
"/detector_1_events")) {
392 using string_map_t = std::map<std::string, std::string>;
393 string_map_t entries = file.getEntries();
395 if (entries.find(
"detector_1_events") == entries.end()) {
400 if (classType ==
"NXmonitor") {
401 std::vector<std::string> bankNames;
402 for (string_map_t::const_iterator it = entries.begin(); it != entries.end(); ++it) {
403 std::string entryName(it->first);
404 std::string entry_class(it->second);
405 if (entry_class == classType) {
406 bankNames.emplace_back(entryName);
409 for (
size_t i = 0; i < bankNames.size(); ++i) {
410 const std::string &mon = bankNames[i];
411 file.openGroup(mon, classType);
412 entries = file.getEntries();
413 if (entries.find(
"event_time_bins") == entries.end()) {
431 file.openGroup(
"detector_1_events",
"NXevent_data");
432 entries = file.getEntries();
433 for (string_map_t::const_iterator it = entries.begin(); it != entries.end(); ++it) {
434 if (it->first ==
"time_of_flight" || it->first ==
"event_time_bins") {
443 file.openGroup(
"instrument",
"NXinstrument");
444 file.openGroup(
"dae",
"IXdae");
445 entries = file.getEntries();
446 size_t time_channels_number = 0;
447 for (string_map_t::const_iterator it = entries.begin(); it != entries.end(); ++it) {
450 if (it->first.size() > 14 && it->first.substr(0, 14) ==
"time_channels_") {
451 size_t n = boost::lexical_cast<size_t>(it->first.substr(14));
452 if (
n > time_channels_number) {
453 time_channels_number =
n;
457 if (time_channels_number > 0)
459 file.openGroup(
"time_channels_" +
std::to_string(time_channels_number),
"IXtime_channels");
460 entries = file.getEntries();
461 for (string_map_t::const_iterator it = entries.begin(); it != entries.end(); ++it) {
462 if (it->first ==
"time_of_flight" || it->first ==
"event_time_bins") {
489 const std::string &top_entry_name,
Algorithm *alg,
491 std::string instrument;
492 std::string instFilename;
499 instFilename = nexusfilename;
502 ::NeXus::File nxfile(nexusfilename);
504 nxfile.openGroup(top_entry_name,
"NXentry");
506 nxfile.openGroup(
"instrument",
"NXinstrument");
508 nxfile.openData(
"name");
509 instrument = nxfile.getStrData();
510 alg->
getLogger().
debug() <<
"Instrument name read from NeXus file is " << instrument <<
'\n';
511 }
catch (::NeXus::Exception &) {
515 if (instrument.empty()) {
517 size_t n = nexusfilename.rfind(
'/');
518 if (
n != std::string::npos) {
519 std::string temp = nexusfilename.substr(
n + 1, nexusfilename.size() -
n - 1);
521 if (
n != std::string::npos &&
n > 0) {
522 instrument = temp.substr(0,
n);
527 if (instrument ==
"POWGEN3")
528 instrument =
"POWGEN";
529 if (instrument ==
"NOM")
530 instrument =
"NOMAD";
532 if (instrument.empty())
533 throw std::runtime_error(
"Could not find the instrument name in the NXS "
534 "file or using the filename. Cannot load "
542 if (instFilename.empty()) {
547 if (instFilename.empty()) {
549 Poco::Path file(instrument +
"_Definition.xml");
550 Poco::Path fullPath(directory, file);
551 instFilename = fullPath.toString();
560 bool executionSuccessful(
true);
562 loadInst->setPropertyValue(
"Filename", instFilename);
563 loadInst->setPropertyValue(
"InstrumentName", instrument);
570 localWorkspace->populateInstrumentParameters();
571 }
catch (std::invalid_argument &e) {
572 alg->
getLogger().
information() <<
"Invalid argument to LoadInstrument Child Algorithm : " << e.what() <<
'\n';
573 executionSuccessful =
false;
574 }
catch (std::runtime_error &e) {
577 executionSuccessful =
false;
581 if (!executionSuccessful) {
582 alg->
getLogger().
error() <<
"Error loading Instrument definition file\n";
588 const auto &
pmap = localWorkspace->constInstrumentParameters();
589 if (!
pmap.contains(localWorkspace->getInstrument()->getComponentID(),
"det-pos-source"))
590 return executionSuccessful;
592 std::shared_ptr<Geometry::Parameter> updateDets =
593 pmap.get(localWorkspace->getInstrument()->getComponentID(),
"det-pos-source");
594 std::string
value = updateDets->value<std::string>();
595 if (
value.substr(0, 8) ==
"datafile") {
598 updateInst->setPropertyValue(
"Filename", nexusfilename);
599 if (
value ==
"datafile-ignore-phi") {
600 updateInst->setProperty(
"IgnorePhi",
true);
602 "positions in the data file except for the "
605 alg->
getLogger().
information(
"Detector positions in IDF updated with positions in the data file");
609 updateInst->execute();
612 return executionSuccessful;
621 ::NeXus::File file(nexusfilename);
622 file.openGroup(entry_name,
"NXentry");
625 if (descriptor.
isEntry(
"/" + entry_name +
"/title",
"SDS")) {
626 file.openData(
"title");
627 if (file.getInfo().type == ::NeXus::CHAR) {
628 std::string title = file.getStrData();
636 if (descriptor.
isEntry(
"/" + entry_name +
"/notes",
"SDS")) {
637 file.openData(
"notes");
638 if (file.getInfo().type == ::NeXus::CHAR) {
639 std::string notes = file.getStrData();
641 WS->mutableRun().addProperty(
"file_notes", notes,
true);
647 if (descriptor.
isEntry(
"/" + entry_name +
"/run_number",
"SDS")) {
648 file.openData(
"run_number");
650 if (file.getInfo().type == ::NeXus::CHAR) {
651 run = file.getStrData();
652 }
else if (file.isDataInt()) {
654 std::vector<int>
value;
660 WS->mutableRun().addProperty(
"run_number", run,
true);
666 if (descriptor.
isEntry(
"/" + entry_name +
"/experiment_identifier",
"SDS")) {
667 file.openData(
"experiment_identifier");
669 if (file.getInfo().type == ::NeXus::CHAR) {
670 expId = file.getStrData();
672 if (!expId.empty()) {
673 WS->mutableRun().addProperty(
"experiment_identifier", expId,
true);
680 if (descriptor.
isEntry(
"/" + entry_name +
"/sample",
"NXsample")) {
681 file.openGroup(
"sample",
"NXsample");
683 if (descriptor.
isEntry(
"/" + entry_name +
"/sample/name",
"SDS")) {
684 file.openData(
"name");
685 const auto info = file.getInfo();
687 if (info.type == ::NeXus::CHAR) {
688 if (info.dims.size() == 1) {
689 name = file.getStrData();
691 const int64_t total_length = std::accumulate(info.dims.begin(), info.dims.end(),
static_cast<int64_t
>(1),
692 std::multiplies<int64_t>());
693 boost::scoped_array<char> val_array(
new char[total_length]);
694 file.getData(val_array.get());
695 name = std::string(val_array.get(), total_length);
700 WS->mutableSample().setName(
name);
703 }
catch (::NeXus::Exception &) {
710 if (descriptor.
isEntry(
"/" + entry_name +
"/duration",
"SDS")) {
711 file.openData(
"duration");
712 std::vector<double> duration;
713 file.getDataCoerce(duration);
714 if (duration.size() == 1) {
717 std::vector< ::NeXus::AttrInfo> infos = file.getAttrInfos();
719 for (std::vector< ::NeXus::AttrInfo>::const_iterator it = infos.begin();
720 it != infos.end(); ++it) {
721 if (it->name ==
"units") {
722 units = file.getStrAttr(*it);
729 WS->mutableRun().addProperty(
"duration", duration[0], units,
true);
752 const std::string &top_entry_name,
Algorithm *alg,
755 bool loadNexusInstrumentXML =
true;
757 loadNexusInstrumentXML = alg->
getProperty(
"LoadNexusInstrumentXML");
759 bool foundInstrument =
false;
760 if (loadNexusInstrumentXML)
761 foundInstrument = runLoadIDFFromNexus<T>(nexusfilename, localWorkspace, top_entry_name, alg);
762 if (!foundInstrument)
763 foundInstrument = runLoadInstrument<T>(nexusfilename, localWorkspace, top_entry_name, alg, descriptor);
764 return foundInstrument;
779 const std::string &top_entry_name,
Algorithm *alg) {
782 ::NeXus::File nxsfile(nexusfilename);
783 nxsfile.openPath(top_entry_name +
"/instrument/instrument_xml");
784 }
catch (::NeXus::Exception &) {
785 alg->
getLogger().
information(
"No instrument XML definition found in " + nexusfilename +
" at " + top_entry_name +
794 loadInst->setPropertyValue(
"Filename", nexusfilename);
796 loadInst->setPropertyValue(
"InstrumentParentPath", top_entry_name);
798 }
catch (std::invalid_argument &) {
799 alg->
getLogger().
error(
"Invalid argument to LoadIDFFromNexus Child Algorithm ");
800 }
catch (std::runtime_error &) {
801 alg->
getLogger().
debug(
"No instrument definition found by LoadIDFFromNexus in " + nexusfilename +
" at " +
802 top_entry_name +
"/instrument");
805 if (!loadInst->isExecuted())
807 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.
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)
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.
static bool runLoadInstrument(const std::string &nexusfilename, T localWorkspace, const std::string &top_entry_name, Algorithm *alg, const Kernel::NexusHDF5Descriptor *descriptor=nullptr)
Load instrument from IDF file specified by Nexus file.
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.
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.
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.
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...
std::unique_ptr<::NeXus::File > m_file
static void loadEntryMetadata(const std::string &nexusfilename, T WS, const std::string &entry_name, const Kernel::NexusHDF5Descriptor &descriptor)
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 Kernel::NexusHDF5Descriptor *descriptor=nullptr)
Load instrument from Nexus file if possible, else from IDF spacified by Nexus file.
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::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.
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.
bool isEntry(const std::string &entryName, const std::string &groupClass) const noexcept
Checks if a full-path entry exists for a particular groupClass in a Nexus dataset.
OptionalBool : Tri-state bool.
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.
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.
bool exists(::NeXus::File &file, const std::string &name)
Based on the current group in the file, does the named sub-entry exist?
std::shared_ptr< EventWorkspaceCollection > EventWorkspaceCollection_sptr
void adjustTimeOfFlightISISLegacy(::NeXus::File &file, T localWorkspace, const std::string &entry_name, const std::string &classType, const Kernel::NexusHDF5Descriptor *descriptor=nullptr)
ISIS specific method for dealing with wide events.
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)