diff --git a/Framework/DataHandling/CMakeLists.txt b/Framework/DataHandling/CMakeLists.txt index 2c388a5b6a0d33d8ac24cfdd7a54acb4e21c3c2b..bb0ec2b4dcf031d3a5b131b3370a6395ae167eea 100644 --- a/Framework/DataHandling/CMakeLists.txt +++ b/Framework/DataHandling/CMakeLists.txt @@ -56,6 +56,7 @@ src/LoadEventPreNexus2.cpp src/LoadFITS.cpp src/LoadFullprofResolution.cpp + src/LoadGeometry.cpp src/LoadGSASInstrumentFile.cpp src/LoadGSS.cpp src/LoadHelper.cpp @@ -64,7 +65,7 @@ src/LoadILLIndirect2.cpp src/LoadILLPolarizationFactors.cpp src/LoadILLReflectometry.cpp - src/LoadILLSANS.cpp + src/LoadILLSANS.cpp src/LoadILLTOF2.cpp src/LoadISISNexus2.cpp src/LoadISISPolarizationEfficiencies.cpp @@ -139,7 +140,7 @@ src/RotateInstrumentComponent.cpp src/RotateSource.cpp src/SNSDataArchive.cpp - src/SaveANSTOAscii.cpp + src/SaveANSTOAscii.cpp src/SaveAscii.cpp src/SaveAscii2.cpp src/SaveBankScatteringAngles.cpp @@ -161,7 +162,7 @@ src/SaveILLCosmosAscii.cpp src/SaveISISNexus.cpp src/SaveIsawDetCal.cpp - src/SaveMask.cpp + src/SaveMask.cpp src/SaveNISTDAT.cpp src/SaveNXSPE.cpp src/SaveNXTomo.cpp @@ -174,7 +175,7 @@ src/SavePHX.cpp src/SaveParameterFile.cpp src/SaveRKH.cpp - src/SaveReflectometryAscii.cpp + src/SaveReflectometryAscii.cpp src/SaveReflCustomAscii.cpp src/SaveReflThreeColumnAscii.cpp src/SaveSESANS.cpp @@ -251,6 +252,7 @@ set ( INC_FILES inc/MantidDataHandling/LoadEventPreNexus2.h inc/MantidDataHandling/LoadFITS.h inc/MantidDataHandling/LoadFullprofResolution.h + inc/MantidDataHandling/LoadGeometry.h inc/MantidDataHandling/LoadGSASInstrumentFile.h inc/MantidDataHandling/LoadGSS.h inc/MantidDataHandling/LoadHelper.h @@ -365,7 +367,7 @@ set ( INC_FILES inc/MantidDataHandling/SavePHX.h inc/MantidDataHandling/SaveParameterFile.h inc/MantidDataHandling/SaveRKH.h - inc/MantidDataHandling/SaveReflectometryAscii.h + inc/MantidDataHandling/SaveReflectometryAscii.h inc/MantidDataHandling/SaveReflCustomAscii.h inc/MantidDataHandling/SaveReflThreeColumnAscii.h inc/MantidDataHandling/SaveSESANS.h @@ -544,7 +546,7 @@ set ( TEST_FILES SavePHXTest.h SaveParameterFileTest.h SaveRKHTest.h - SaveReflectometryAsciiTest.h + SaveReflectometryAsciiTest.h SaveReflCustomAsciiTest.h SaveReflThreeColumnAsciiTest.h SaveSESANSTest.h diff --git a/Framework/DataHandling/inc/MantidDataHandling/LoadGeometry.h b/Framework/DataHandling/inc/MantidDataHandling/LoadGeometry.h new file mode 100644 index 0000000000000000000000000000000000000000..e01e4d07e460c275a3bfe4daad71dfa30347b07f --- /dev/null +++ b/Framework/DataHandling/inc/MantidDataHandling/LoadGeometry.h @@ -0,0 +1,52 @@ +// Mantid Repository : https://github.com/mantidproject/mantid +// +// Copyright © 2007 ISIS Rutherford Appleton Laboratory UKRI, +// NScD Oak Ridge National Laboratory, European Spallation Source +// & Institut Laue - Langevin +// SPDX - License - Identifier: GPL - 3.0 + +#ifndef MANTID_DATAHANDLING_LOADGEOMETRY_H_ +#define MANTID_DATAHANDLING_LOADGEOMETRY_H_ + +#include <string> + +namespace Mantid { +namespace DataHandling { +/** +Loads an instrument definition file into a workspace, with the purpose of being +able to visualise an instrument without requiring to read in a ISIS raw datafile +first. +The name of the algorithm refers to the fact that an instrument +is loaded into a workspace but without any real data - hence the reason for +referring to +it as an 'empty' instrument. + +Required Properties: +<UL> +<LI> Filename - The name of an instrument definition file </LI> +<LI> OutputWorkspace - The name of the workspace in which to store the imported +instrument</LI> +</UL> + +Optional Properties: (note that these options are not available if reading a +multiperiod file) +<UL> +<LI> detector_value - This value affect the colour of the detectorss in the +instrument display window</LI> +<LI> monitor_value - This value affect the colour of the monitors in the +instrument display window</LI> +</UL> + +@author Anders Markvardsen, ISIS, RAL +@date 31/10/2008 +*/ +namespace LoadGeometry { + +bool isIDF(const std::string &filename, const std::string &instrumentname); +bool isNexus(const std::string &filename); + +} // namespace LoadGeometry + +} // namespace DataHandling +} // namespace Mantid + +#endif /*MANTID_DATAHANDLING_LOADGEOMETRY_H_*/ diff --git a/Framework/DataHandling/inc/MantidDataHandling/LoadInstrument.h b/Framework/DataHandling/inc/MantidDataHandling/LoadInstrument.h index d8e24ed3d32046875cc5c140d9900dc623457f2b..3edfe0ab89a420b6b0aa8dc001d1f188ecd9d934 100644 --- a/Framework/DataHandling/inc/MantidDataHandling/LoadInstrument.h +++ b/Framework/DataHandling/inc/MantidDataHandling/LoadInstrument.h @@ -78,6 +78,12 @@ public: const std::string category() const override { return "DataHandling\\Instrument"; } + /// Load instrument from IDF XML file + void IDFInstrumentLoader(); + /// Load instrument from Nexus file + void NexusInstrumentLoader(); + /// Retrieve file name if undefined + void checkAndRetrieveInstrumentFilename(); private: void init() override; diff --git a/Framework/DataHandling/src/LoadEmptyInstrument.cpp b/Framework/DataHandling/src/LoadEmptyInstrument.cpp index a145d5f1362239c08af2b1443c2270b1adcc6eef..bad262ec93ac968d4a82c0d7e0a5f866eb9e5021 100644 --- a/Framework/DataHandling/src/LoadEmptyInstrument.cpp +++ b/Framework/DataHandling/src/LoadEmptyInstrument.cpp @@ -5,6 +5,7 @@ // & Institut Laue - Langevin // SPDX - License - Identifier: GPL - 3.0 + #include "MantidDataHandling/LoadEmptyInstrument.h" +#include "MantidDataHandling/LoadGeometry.h" #include "MantidAPI/FileProperty.h" #include "MantidAPI/RegisterFileLoader.h" #include "MantidAPI/SpectrumInfo.h" @@ -16,8 +17,8 @@ #include "MantidIndexing/IndexInfo.h" #include "MantidKernel/BoundedValidator.h" #include "MantidKernel/ConfigService.h" -#include "MantidKernel/FileDescriptor.h" -#include "MantidKernel/NexusDescriptor.h" +// #include "MantidKernel/FileDescriptor.h" +// #include "MantidKernel/NexusDescriptor.h" #include "MantidKernel/OptionalBool.h" #include "MantidNexusGeometry/NexusGeometryParser.h" @@ -32,25 +33,25 @@ using namespace Geometry; using namespace DataObjects; using namespace HistogramData; -namespace { -bool isIDF(const std::string &filename, const std::string &instrumentname) { - if (!filename.empty()) { - FileDescriptor descriptor(filename); - return ((descriptor.isAscii() && descriptor.extension() == ".xml")); - } - return !instrumentname.empty(); -} - -bool isNexus(const std::string &filename) { - if (!filename.empty() && !FileDescriptor(filename).isAscii(filename)) { - NexusDescriptor descriptor(filename); - return descriptor.isHDF(filename) && - (descriptor.classTypeExists("NXcylindrical_geometry") || - descriptor.classTypeExists("NXoff_geometry")); - } - return false; -} -} // namespace +// namespace { +// bool isIDF(const std::string &filename, const std::string &instrumentname) { +// if (!filename.empty()) { +// FileDescriptor descriptor(filename); +// return ((descriptor.isAscii() && descriptor.extension() == ".xml")); +// } +// return !instrumentname.empty(); +// } +// +// bool isNexus(const std::string &filename) { +// if (!filename.empty() && !FileDescriptor(filename).isAscii(filename)) { +// NexusDescriptor descriptor(filename); +// return descriptor.isHDF(filename) && +// (descriptor.classTypeExists("NXcylindrical_geometry") || +// descriptor.classTypeExists("NXoff_geometry")); +// } +// return false; +// } +// } // namespace /** * Return the confidence with with this algorithm can load the file @@ -132,10 +133,10 @@ void LoadEmptyInstrument::exec() { const std::string instrumentname = getPropertyValue("InstrumentName"); Instrument_const_sptr instrument; Progress prog(this, 0.0, 1.0, 10); - if (isNexus(filename)) { + if (LoadGeometry::isNexus(filename)) { prog.reportIncrement(0, "Loading geometry from file"); instrument = NexusGeometry::NexusGeometryParser::createInstrument(filename); - } else if (isIDF(filename, instrumentname)) { + } else if (LoadGeometry::isIDF(filename, instrumentname)) { MatrixWorkspace_sptr ws = this->runLoadInstrument(filename, instrumentname); instrument = ws->getInstrument(); } else { diff --git a/Framework/DataHandling/src/LoadGeometry.cpp b/Framework/DataHandling/src/LoadGeometry.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d9f18d8bd8a3f725b32812f294d6ad7d1707cdea --- /dev/null +++ b/Framework/DataHandling/src/LoadGeometry.cpp @@ -0,0 +1,33 @@ +// Mantid Repository : https://github.com/mantidproject/mantid +// +// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI, +// NScD Oak Ridge National Laboratory, European Spallation Source +// & Institut Laue - Langevin +// SPDX - License - Identifier: GPL - 3.0 + +#include "MantidDataHandling/LoadGeometry.h" +#include "MantidKernel/FileDescriptor.h" +#include "MantidKernel/NexusDescriptor.h" + +namespace Mantid { +namespace DataHandling { + +bool LoadGeometry::isIDF(const std::string &filename, const std::string &instrumentname) { + if (!filename.empty()) { + Mantid::Kernel::FileDescriptor descriptor(filename); + return ((descriptor.isAscii() && descriptor.extension() == ".xml")); + } + return !instrumentname.empty(); +} + +bool LoadGeometry::isNexus(const std::string &filename) { + if (!filename.empty() && !Mantid::Kernel::FileDescriptor(filename).isAscii(filename)) { + Mantid::Kernel::NexusDescriptor descriptor(filename); + return descriptor.isHDF(filename) && + (descriptor.classTypeExists("NXcylindrical_geometry") || + descriptor.classTypeExists("NXoff_geometry")); + } + return false; +} + +} // namespace DataHandling +} // namespace Mantid diff --git a/Framework/DataHandling/src/LoadInstrument.cpp b/Framework/DataHandling/src/LoadInstrument.cpp index dd956e8c9b381016765f4bb7f792a8cc71ba3de0..b6c5d21167cdd87ae69f89428eccdd15c2a0b0ae 100644 --- a/Framework/DataHandling/src/LoadInstrument.cpp +++ b/Framework/DataHandling/src/LoadInstrument.cpp @@ -4,19 +4,20 @@ // NScD Oak Ridge National Laboratory, European Spallation Source // & Institut Laue - Langevin // SPDX - License - Identifier: GPL - 3.0 + -#include "MantidDataHandling/LoadInstrument.h" #include "MantidAPI/FileProperty.h" #include "MantidAPI/InstrumentDataService.h" #include "MantidAPI/MatrixWorkspace.h" #include "MantidAPI/Progress.h" +#include "MantidDataHandling/LoadGeometry.h" +#include "MantidDataHandling/LoadInstrument.h" #include "MantidGeometry/Instrument.h" +#include "MantidGeometry/Instrument/InstrumentDefinitionParser.h" #include "MantidKernel/ArrayProperty.h" #include "MantidKernel/ConfigService.h" #include "MantidKernel/MandatoryValidator.h" #include "MantidKernel/OptionalBool.h" #include "MantidKernel/Strings.h" - -#include "MantidGeometry/Instrument/InstrumentDefinitionParser.h" +#include "MantidNexusGeometry/NexusGeometryParser.h" #include <Poco/DOM/DOMParser.h> #include <Poco/DOM/Document.h> #include <Poco/DOM/Element.h> @@ -28,6 +29,7 @@ #include <Poco/Path.h> #include <fstream> #include <sstream> +#include <iostream> namespace Mantid { namespace DataHandling { @@ -48,12 +50,14 @@ void LoadInstrument::init() { "Workspace", "Anonymous", Direction::InOut), "The name of the workspace to load the instrument definition " "into. Any existing instrument will be replaced."); + const std::vector<std::string> extensions{".xml", ".nxs", ".hdf5"}; declareProperty( make_unique<FileProperty>("Filename", "", FileProperty::OptionalLoad, - ".xml"), + extensions), "The filename (including its full or relative path) of an instrument " "definition file. The file extension must either be .xml or .XML when " - "specifying an instrument definition file. Note Filename or " + "specifying an instrument definition file. Files can also be .hdf5 or " + ".nxs for usage with NeXus Geometry files. Note Filename or " "InstrumentName must be specified but not both."); declareProperty( make_unique<ArrayProperty<detid_t>>("MonitorList", Direction::Output), @@ -99,6 +103,29 @@ void LoadInstrument::exec() { m_filename = getPropertyValue("Filename"); m_instName = getPropertyValue("InstrumentName"); + // Decide whether to use Nexus or IDF loading + if (LoadGeometry::isIDF(m_filename, m_instName)) + IDFInstrumentLoader(); + else if (LoadGeometry::isNexus(m_filename)) + NexusInstrumentLoader(); + else + throw Kernel::Exception::FileError("Instrument input cannot be read",m_filename); + + // Set the monitors output property + // auto instr = m_workspace->getInstrument(); + setProperty("MonitorList", (m_workspace->getInstrument())->getMonitors()); + + // Rebuild the spectra map for this workspace so that it matches the + // instrument + // if required + const OptionalBool RewriteSpectraMap = getProperty("RewriteSpectraMap"); + if (RewriteSpectraMap == OptionalBool::True) + m_workspace->rebuildSpectraMapping(); +} + +/// Load instrument from IDF XML file +void LoadInstrument::IDFInstrumentLoader() { + // We will parse the XML using the InstrumentDefinitionParser InstrumentDefinitionParser parser; @@ -129,28 +156,7 @@ void LoadInstrument::exec() { } // otherwise we need either Filename or InstrumentName to be set else { - // Retrieve the filename from the properties - if (m_filename.empty()) { - // look to see if an Instrument name provided in which case create - // IDF filename on the fly - if (m_instName.empty()) { - g_log.error("Either the InstrumentName or Filename property of " - "LoadInstrument most be specified"); - throw Kernel::Exception::FileError( - "Either the InstrumentName or Filename property of LoadInstrument " - "most be specified to load an IDF", - m_filename); - } else { - const std::string date = m_workspace->getWorkspaceStartDate(); - m_filename = ExperimentInfo::getInstrumentFilename(m_instName, date); - } - } - - if (m_filename.empty()) { - throw Exception::NotFoundError( - "Unable to find an Instrument Definition File for", m_instName); - } - + checkAndRetrieveInstrumentFilename(); // Remove the path from the filename for use with the InstrumentDataService const std::string::size_type stripPath = m_filename.find_last_of("\\/"); std::string instrumentFile = @@ -201,16 +207,39 @@ void LoadInstrument::exec() { if (!m_filename.empty()) runLoadParameterFile(); } +} - // Set the monitors output property - setProperty("MonitorList", instrument->getMonitors()); +void LoadInstrument::NexusInstrumentLoader() { + checkAndRetrieveInstrumentFilename(); + m_filename = ExperimentInfo::getInstrumentFilename(m_instName, + m_workspace->getWorkspaceStartDate()); + Instrument_const_sptr instrument = NexusGeometry::NexusGeometryParser::createInstrument(m_filename); + m_workspace->setInstrument(instrument); + m_workspace->populateInstrumentParameters(); +} - // Rebuild the spectra map for this workspace so that it matches the - // instrument - // if required - const OptionalBool RewriteSpectraMap = getProperty("RewriteSpectraMap"); - if (RewriteSpectraMap == OptionalBool::True) - m_workspace->rebuildSpectraMapping(); +/// Get the file name from the instrument name if it is not defined +void LoadInstrument::checkAndRetrieveInstrumentFilename() { + // Retrieve the filename from the properties + if (m_filename.empty()) { + // look to see if an Instrument name provided in which case create + // filename on the fly + if (m_instName.empty()) { + g_log.error("Either the InstrumentName or Filename property of " + "LoadInstrument most be specified"); + throw Kernel::Exception::FileError( + "Either the InstrumentName or Filename property of LoadInstrument " + "most be specified to load an IDF", + m_filename); + } else { + m_filename = ExperimentInfo::getInstrumentFilename(m_instName, + m_workspace->getWorkspaceStartDate()); + } + } + if (m_filename.empty()) { + throw Exception::NotFoundError( + "Unable to find an Instrument Definition File for", m_instName); + } } //----------------------------------------------------------------------------------------------------------------------- diff --git a/Framework/NexusGeometry/src/InstrumentBuilder.cpp b/Framework/NexusGeometry/src/InstrumentBuilder.cpp index 8fa6a6dd4ce7687a862e5bfa3bd82bde8d6e8428..734356547c02d68782eca7018146fe234755d50b 100644 --- a/Framework/NexusGeometry/src/InstrumentBuilder.cpp +++ b/Framework/NexusGeometry/src/InstrumentBuilder.cpp @@ -171,6 +171,7 @@ InstrumentBuilder::createInstrument() { m_instrument->getName()); auto *product = m_instrument.release(); m_instrument = std::move(temp); + product->parseTreeAndCacheBeamline(); // Some older compilers (Apple clang 7) don't support copy construction // std::unique_ptr<const T>(const std::ptr<T>&) return std::unique_ptr<const Geometry::Instrument>(product);