14#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);
79 const std::string
name()
const override {
return "LoadEventNexus"; };
82 const std::string
summary()
const override {
83 return "Loads an Event NeXus file and stores as an "
84 "EventWorkspace. Optionally, you can filter out events falling "
85 "outside a range of times-of-flight and/or a time interval.";
89 int version()
const override {
return 1; };
90 const std::vector<std::string>
seeAlso()
const override {
return {
"LoadISISNexus",
"LoadEventAndCompress"}; }
93 const std::string
category()
const override {
return "DataHandling\\Nexus"; }
98 static std::shared_ptr<BankPulseTimes>
99 runLoadNexusLogs(
const std::string &nexusfilename, T localWorkspace,
Algorithm &alg,
bool returnpulsetimes,
102 template <
typename T>
103 static std::shared_ptr<BankPulseTimes>
104 runLoadNexusLogs(
const std::string &nexusfilename, T localWorkspace,
Algorithm &alg,
bool returnpulsetimes,
106 const std::vector<std::string> &allow_list,
const std::vector<std::string> &block_list);
110 const int &nPeriods,
const std::string &nexusfilename, std::string &status);
112 template <
typename T>
113 static void loadEntryMetadata(
const std::string &nexusfilename, T WS,
const std::string &entry_name,
117 template <
typename T>
118 static bool loadInstrument(
const std::string &nexusfilename, T localWorkspace,
const std::string &top_entry_name,
122 template <
typename T>
123 static bool runLoadIDFFromNexus(
const std::string &nexusfilename, T localWorkspace,
const std::string &top_entry_name,
127 template <
typename T>
128 static bool runLoadInstrument(
const std::string &nexusfilename, T localWorkspace,
const std::string &top_entry_name,
135 static std::string readInstrumentFromISIS_VMSCompat(Nexus::File &hFile);
142 std::shared_ptr<EventWorkspaceCollection>
m_ws;
161 bool m_is_time_filtered{
false};
163 bool filter_bad_pulses{
false};
193 void init()
override;
196 void execLoader()
override;
198 std::map<std::string, std::string> validateInputs()
override;
203 void createSpectraMapping(
const std::string &nxsfile,
const bool monitorsOnly,
204 const std::vector<std::string> &bankNames = std::vector<std::string>());
206 void runLoadMonitors();
208 void setTimeFilters(
const bool monitors);
209 template <
typename T>
210 T filterEventsByTime(T
workspace, Mantid::Types::Core::DateAndTime &startTime,
211 Mantid::Types::Core::DateAndTime &stopTime);
214 std::unique_ptr<std::pair<std::vector<int32_t>, std::vector<int32_t>>>
215 loadISISVMSSpectraMapping(
const std::string &entry_name);
217 template <
typename T>
void filterDuringPause(T
workspace);
220 void setTopEntryName();
223 void safeOpenFile(
const std::string &fname);
270 const std::string EVENT_TIME_SHIFT_TAG(
"event_time_offset_shift");
272 const auto entries = file.getEntries();
273 if (entries.find(EVENT_TIME_SHIFT_TAG) != entries.end()) {
274 std::string event_shift_type;
275 file.readData(EVENT_TIME_SHIFT_TAG, event_shift_type);
276 if (event_shift_type ==
"random") {
282 file.openData(binsName);
284 std::vector<float> tofsFile;
285 file.getData(tofsFile);
290 if (end_wi <= start_wi) {
291 end_wi = localWorkspace->getNumberHistograms();
298 for (
size_t wi = start_wi; wi < end_wi; ++wi) {
300 if (event_list.
empty())
304 auto tofsEventList = event_list.
getTofs();
306 size_t n = tofsFile.size();
308 auto ev = tofsEventList.begin();
309 auto ev_end = tofsEventList.end();
310 for (
size_t i = 1; i <
n; ++i) {
311 double right = double(tofsFile[i]);
313 if ((ev != ev_end) && (
right < *ev)) {
318 while ((ev != ev_end) && (*ev <
right)) {
324 double left = double(tofsFile[i - 1]);
326 std::uniform_real_distribution<double> flat(
left,
right);
327 std::vector<double> random_numbers(
m);
328 std::generate(random_numbers.begin(), random_numbers.end(), [&flat, &rng]() { return flat(rng); });
329 std::sort(random_numbers.begin(), random_numbers.end());
330 auto it = random_numbers.begin();
331 for (
auto ev1 = ev -
m; ev1 != ev; ++ev1, ++it) {
337 event_list.
setTofs(tofsEventList);
361 file.openAddress(
"/");
362 file.openGroup(entry_name,
"NXentry");
365 if (descriptor !=
nullptr) {
367 if (!descriptor->isEntry(
"/" + entry_name +
"/detector_1_events")) {
372 using string_map_t = std::map<std::string, std::string>;
373 string_map_t entries = file.getEntries();
375 if (entries.find(
"detector_1_events") == entries.end()) {
380 if (classType ==
"NXmonitor") {
381 std::vector<std::string> bankNames;
382 for (string_map_t::const_iterator it = entries.begin(); it != entries.end(); ++it) {
383 const std::string entry_class(it->second);
384 if (entry_class == classType) {
385 const std::string entryName(it->first);
386 bankNames.emplace_back(entryName);
389 for (
size_t i = 0; i < bankNames.size(); ++i) {
390 const std::string &mon = bankNames[i];
391 file.openGroup(mon, classType);
392 entries = file.getEntries();
393 if (entries.find(
"event_time_bins") == entries.end()) {
411 file.openGroup(
"detector_1_events",
"NXevent_data");
412 entries = file.getEntries();
413 for (string_map_t::const_iterator it = entries.begin(); it != entries.end(); ++it) {
414 if (it->first ==
"time_of_flight" || it->first ==
"event_time_bins") {
423 file.openGroup(
"instrument",
"NXinstrument");
424 file.openGroup(
"dae",
"IXdae");
425 entries = file.getEntries();
426 size_t time_channels_number = 0;
427 for (string_map_t::const_iterator it = entries.begin(); it != entries.end(); ++it) {
430 if (it->first.size() > 14 && it->first.substr(0, 14) ==
"time_channels_") {
431 size_t n = boost::lexical_cast<size_t>(it->first.substr(14));
432 if (
n > time_channels_number) {
433 time_channels_number =
n;
437 if (time_channels_number > 0)
439 file.openGroup(
"time_channels_" +
std::to_string(time_channels_number),
"IXtime_channels");
440 entries = file.getEntries();
441 for (string_map_t::const_iterator it = entries.begin(); it != entries.end(); ++it) {
442 if (it->first ==
"time_of_flight" || it->first ==
"event_time_bins") {
470 const std::string &top_entry_name,
Algorithm *alg,
472 std::string instrument;
473 std::string instFilename;
480 instFilename = nexusfilename;
483 Nexus::File nxfile(nexusfilename);
485 nxfile.openGroup(top_entry_name,
"NXentry");
487 nxfile.openGroup(
"instrument",
"NXinstrument");
489 nxfile.openData(
"name");
490 instrument = nxfile.getStrData();
491 alg->
getLogger().
debug() <<
"Instrument name read from NeXus file is " << instrument <<
'\n';
496 if (instrument.empty()) {
498 size_t n = nexusfilename.rfind(
'/');
499 if (
n != std::string::npos) {
500 std::string temp = nexusfilename.substr(
n + 1, nexusfilename.size() -
n - 1);
502 if (
n != std::string::npos &&
n > 0) {
503 instrument = temp.substr(0,
n);
508 if (instrument ==
"POWGEN3")
509 instrument =
"POWGEN";
510 if (instrument ==
"NOM")
511 instrument =
"NOMAD";
513 if (instrument.empty())
514 throw std::runtime_error(
"Could not find the instrument name in the NXS "
515 "file or using the filename. Cannot load "
523 if (instFilename.empty()) {
528 if (instFilename.empty()) {
529 std::filesystem::path directory(Kernel::ConfigService::Instance().getInstrumentDirectory());
530 std::filesystem::path file(instrument +
"_Definition.xml");
531 std::filesystem::path fullPath = directory / file;
532 instFilename = fullPath.string();
541 bool executionSuccessful(
true);
543 loadInst->setPropertyValue(
"Filename", instFilename);
544 loadInst->setPropertyValue(
"InstrumentName", instrument);
551 localWorkspace->populateInstrumentParameters();
552 }
catch (std::invalid_argument &e) {
553 alg->
getLogger().
information() <<
"Invalid argument to LoadInstrument Child Algorithm : " << e.what() <<
'\n';
554 executionSuccessful =
false;
555 }
catch (std::runtime_error &e) {
558 executionSuccessful =
false;
562 if (!executionSuccessful) {
563 alg->
getLogger().
error() <<
"Error loading Instrument definition file\n";
569 const auto &
pmap = localWorkspace->constInstrumentParameters();
570 if (!
pmap.contains(localWorkspace->getInstrument()->getComponentID(),
"det-pos-source"))
571 return executionSuccessful;
573 std::shared_ptr<Geometry::Parameter> updateDets =
574 pmap.get(localWorkspace->getInstrument()->getComponentID(),
"det-pos-source");
575 std::string
value = updateDets->value<std::string>();
576 if (
value.substr(0, 8) ==
"datafile") {
579 updateInst->setPropertyValue(
"Filename", nexusfilename);
580 if (
value ==
"datafile-ignore-phi") {
581 updateInst->setProperty(
"IgnorePhi",
true);
583 "positions in the data file except for the "
586 alg->
getLogger().
information(
"Detector positions in IDF updated with positions in the data file");
590 updateInst->execute();
593 return executionSuccessful;
602 Nexus::File file(nexusfilename);
603 file.openGroup(entry_name,
"NXentry");
606 if (descriptor.
isEntry(
"/" + entry_name +
"/title",
"SDS")) {
607 file.openData(
"title");
609 std::string title = file.getStrData();
617 if (descriptor.
isEntry(
"/" + entry_name +
"/notes",
"SDS")) {
618 file.openData(
"notes");
620 std::string notes = file.getStrData();
622 WS->mutableRun().addProperty(
"file_notes", notes,
true);
628 if (descriptor.
isEntry(
"/" + entry_name +
"/run_number",
"SDS")) {
629 file.openData(
"run_number");
632 run = file.getStrData();
633 }
else if (file.isDataInt()) {
635 std::vector<int>
value;
641 WS->mutableRun().addProperty(
"run_number", run,
true);
647 if (descriptor.
isEntry(
"/" + entry_name +
"/experiment_identifier",
"SDS")) {
648 file.openData(
"experiment_identifier");
651 expId = file.getStrData();
653 if (!expId.empty()) {
654 WS->mutableRun().addProperty(
"experiment_identifier", expId,
true);
661 if (descriptor.
isEntry(
"/" + entry_name +
"/sample",
"NXsample")) {
662 file.openGroup(
"sample",
"NXsample");
664 if (descriptor.
isEntry(
"/" + entry_name +
"/sample/name",
"SDS")) {
665 file.openData(
"name");
666 const auto info = file.getInfo();
667 std::string sampleName;
669 if (info.dims.size() == 1) {
670 sampleName = file.getStrData();
672 const int64_t total_length = std::accumulate(info.dims.begin(), info.dims.end(),
static_cast<int64_t
>(1),
673 std::multiplies<int64_t>());
674 boost::scoped_array<char> val_array(
new char[total_length]);
675 file.getData(val_array.get());
676 sampleName = std::string(val_array.get(), total_length);
680 if (!sampleName.empty()) {
681 WS->mutableSample().setName(sampleName);
691 if (descriptor.
isEntry(
"/" + entry_name +
"/duration",
"SDS")) {
692 file.openData(
"duration");
693 std::vector<double> duration;
694 file.getDataCoerce(duration);
695 if (duration.size() == 1) {
698 if (file.hasAttr(
"units")) {
699 file.getAttr<std::string>(
"units", units);
703 WS->mutableRun().addProperty(
"duration", duration[0], units,
true);
727 const std::string &top_entry_name,
Algorithm *alg,
730 bool loadNexusInstrumentXML =
true;
732 loadNexusInstrumentXML = alg->
getProperty(
"LoadNexusInstrumentXML");
734 bool foundInstrument =
false;
735 if (loadNexusInstrumentXML)
736 foundInstrument = runLoadIDFFromNexus<T>(nexusfilename, localWorkspace, top_entry_name, alg);
737 if (!foundInstrument)
738 foundInstrument = runLoadInstrument<T>(nexusfilename, std::move(localWorkspace), top_entry_name, alg, descriptor);
739 return foundInstrument;
754 const std::string &top_entry_name,
Algorithm *alg) {
757 Nexus::File nxsfile(nexusfilename);
758 nxsfile.openAddress(top_entry_name +
"/instrument/instrument_xml");
760 alg->
getLogger().
information(
"No instrument XML definition found in " + nexusfilename +
" at " + top_entry_name +
769 loadInst->setPropertyValue(
"Filename", nexusfilename);
771 loadInst->setPropertyValue(
"InstrumentParentPath", top_entry_name);
773 }
catch (std::invalid_argument &) {
774 alg->
getLogger().
error(
"Invalid argument to LoadIDFFromNexus Child Algorithm ");
775 }
catch (std::runtime_error &) {
776 alg->
getLogger().
debug(
"No instrument definition found by LoadIDFFromNexus in " + nexusfilename +
" at " +
777 top_entry_name +
"/instrument");
780 if (!loadInst->isExecuted())
782 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)
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.
static void loadEntryMetadata(const std::string &nexusfilename, T WS, const std::string &entry_name, const Nexus::NexusDescriptor &descriptor)
Load the run number and other meta data from the given bank.
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 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.
bool isEntry(const std::string &entryName, const std::string &groupClass) const noexcept
Checks if a full-address entry exists for a particular groupClass in a Nexus dataset.
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 adjustTimeOfFlightISISLegacy(Nexus::File &file, T localWorkspace, const std::string &entry_name, const std::string &classType, const Nexus::NexusDescriptor *descriptor=nullptr)
ISIS specific method for dealing with wide events.
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)
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)