diff --git a/Code/Mantid/Framework/Algorithms/test/AlphaCalcTest.h b/Code/Mantid/Framework/Algorithms/test/AlphaCalcTest.h index 80b2f9d2ac0df5ee12e89af966af60fd5e3241d0..dbaede7f8ca7c271d8a24bf3dffc13f0bbb68578 100644 --- a/Code/Mantid/Framework/Algorithms/test/AlphaCalcTest.h +++ b/Code/Mantid/Framework/Algorithms/test/AlphaCalcTest.h @@ -3,7 +3,7 @@ #include <cxxtest/TestSuite.h> -#include "MantidDataHandling/LoadMuonNexus.h" +#include "MantidDataHandling/LoadMuonNexus2.h" #include "MantidDataHandling/LoadInstrument.h" #include "MantidDataHandling/GroupDetectors.h" #include "MantidAPI/IAlgorithm.h" @@ -38,6 +38,7 @@ public: void testCalAlphaManySpectra() { + //system("pause"); //Load the muon nexus file loader.initialize(); loader.setPropertyValue("Filename", "emu00006473.nxs"); @@ -93,7 +94,7 @@ public: private: AlphaCalc alphaCalc; - Mantid::DataHandling::LoadMuonNexus loader; + Mantid::DataHandling::LoadMuonNexus2 loader; }; diff --git a/Code/Mantid/Framework/Algorithms/test/ApplyDeadTimeCorrTest.h b/Code/Mantid/Framework/Algorithms/test/ApplyDeadTimeCorrTest.h index 230fd5576ff164d03765542b507972bc8f6fbab8..d729719b217414ebbdee1c32cc820ab7dc81bc7e 100644 --- a/Code/Mantid/Framework/Algorithms/test/ApplyDeadTimeCorrTest.h +++ b/Code/Mantid/Framework/Algorithms/test/ApplyDeadTimeCorrTest.h @@ -3,7 +3,7 @@ #include <cxxtest/TestSuite.h> -#include "MantidDataHandling/LoadMuonNexus.h" +#include "MantidDataHandling/LoadMuonNexus2.h" #include "MantidDataHandling/LoadInstrument.h" #include "MantidDataHandling/GroupDetectors.h" #include "MantidAPI/IAlgorithm.h" @@ -199,7 +199,7 @@ public: private: ApplyDeadTimeCorr applyDeadTime; - Mantid::DataHandling::LoadMuonNexus loader; + Mantid::DataHandling::LoadMuonNexus2 loader; }; diff --git a/Code/Mantid/Framework/Algorithms/test/MuonAsymmetryCalcTest.h b/Code/Mantid/Framework/Algorithms/test/MuonAsymmetryCalcTest.h index b6a9857ba819d8fdf4cd9f30dca836b3adff194d..883b9f5256f687d0e8699fdcb9df834bb26ffd76 100644 --- a/Code/Mantid/Framework/Algorithms/test/MuonAsymmetryCalcTest.h +++ b/Code/Mantid/Framework/Algorithms/test/MuonAsymmetryCalcTest.h @@ -3,7 +3,7 @@ #include <cxxtest/TestSuite.h> -#include "MantidDataHandling/LoadMuonNexus.h" +#include "MantidDataHandling/LoadMuonNexus2.h" #include "MantidDataHandling/LoadInstrument.h" #include "MantidDataHandling/GroupDetectors.h" #include "MantidAPI/IAlgorithm.h" @@ -91,7 +91,7 @@ public: private: MuonAsymmetryCalc asymCalc; - Mantid::DataHandling::LoadMuonNexus loader; + Mantid::DataHandling::LoadMuonNexus2 loader; Mantid::DataHandling::GroupDetectors group1; Mantid::DataHandling::GroupDetectors group2; diff --git a/Code/Mantid/Framework/Algorithms/test/MuonRemoveExpDecayTest.h b/Code/Mantid/Framework/Algorithms/test/MuonRemoveExpDecayTest.h index a7b6d068e7de20bf383c0a3955658d53b0b28dff..6ad22942904b3e2b686e3a7ce2106b161b5bf2d2 100644 --- a/Code/Mantid/Framework/Algorithms/test/MuonRemoveExpDecayTest.h +++ b/Code/Mantid/Framework/Algorithms/test/MuonRemoveExpDecayTest.h @@ -4,7 +4,7 @@ #include <cxxtest/TestSuite.h> #include "MantidDataHandling/LoadInstrument.h" -#include "MantidDataHandling/LoadMuonNexus.h" +#include "MantidDataHandling/LoadMuonNexus2.h" #include "MantidAlgorithms/MuonRemoveExpDecay.h" #include "MantidAPI/Workspace.h" #include "MantidDataObjects/Workspace2D.h" @@ -93,7 +93,7 @@ public: private: MuonRemoveExpDecay alg; - Mantid::DataHandling::LoadMuonNexus loader; + Mantid::DataHandling::LoadMuonNexus2 loader; }; diff --git a/Code/Mantid/Framework/Algorithms/test/RemoveBinsTest.h b/Code/Mantid/Framework/Algorithms/test/RemoveBinsTest.h index 545b4331dd9a752f1bebd11cde498d64a4a55552..6e4886bdbccf646c68eff3eded0f146884a89782 100644 --- a/Code/Mantid/Framework/Algorithms/test/RemoveBinsTest.h +++ b/Code/Mantid/Framework/Algorithms/test/RemoveBinsTest.h @@ -9,7 +9,7 @@ #include <stdexcept> #include "MantidAlgorithms/RemoveBins.h" -#include "MantidDataHandling/LoadMuonNexus.h" +#include "MantidDataHandling/LoadMuonNexus2.h" #include "MantidDataHandling/LoadInstrument.h" #include "MantidDataObjects/Workspace2D.h" #include "MantidKernel/UnitFactory.h" @@ -177,7 +177,7 @@ public: void xtestRealData() { - Mantid::DataHandling::LoadMuonNexus loader; + Mantid::DataHandling::LoadMuonNexus2 loader; loader.initialize(); loader.setPropertyValue("Filename", "emu00006473.nxs"); loader.setPropertyValue("OutputWorkspace", "EMU6473"); diff --git a/Code/Mantid/Framework/DataHandling/CMakeLists.txt b/Code/Mantid/Framework/DataHandling/CMakeLists.txt index 9f7787a4cdefb8f59ef7cd2ba8bac0e4d1649c1d..74e4d8e267aec5db46bad42eab402cc82b0b4d92 100644 --- a/Code/Mantid/Framework/DataHandling/CMakeLists.txt +++ b/Code/Mantid/Framework/DataHandling/CMakeLists.txt @@ -58,6 +58,7 @@ set ( SRC_FILES src/LoadMaskingFile.cpp src/LoadMuonLog.cpp src/LoadMuonNexus.cpp + src/LoadMuonNexus1.cpp src/LoadMuonNexus2.cpp src/LoadNXSPE.cpp src/LoadNexus.cpp @@ -196,6 +197,7 @@ set ( INC_FILES inc/MantidDataHandling/LoadMaskingFile.h inc/MantidDataHandling/LoadMuonLog.h inc/MantidDataHandling/LoadMuonNexus.h + inc/MantidDataHandling/LoadMuonNexus1.h inc/MantidDataHandling/LoadMuonNexus2.h inc/MantidDataHandling/LoadNXSPE.h inc/MantidDataHandling/LoadNexus.h @@ -322,8 +324,8 @@ set ( TEST_FILES LoadMappingTableTest.h LoadMaskTest.h LoadMuonLogTest.h + LoadMuonNexus1Test.h LoadMuonNexus2Test.h - LoadMuonNexusTest.h LoadNXSPETest.h LoadNexusLogsTest.h LoadNexusMonitorsTest.h diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMuonNexus.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMuonNexus.h index 579b210cb9f465b3647a555f1e16c1eb716e4679..74ba34c15d32abd74a50a3849639e1f0fc267061 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMuonNexus.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMuonNexus.h @@ -22,10 +22,8 @@ namespace Mantid { /** @class LoadMuonNexus LoadMuonNexus.h DataHandling/LoadMuonNexus.h - Loads an file in Nexus Muon format and stores it in a 2D workspace - (Workspace2D class). LoadMuonNexus is an algorithm and as such inherits - from the Algorithm class, via DataHandlingCommand, and overrides - the init() & exec() methods. + It is a base class for loadres for versions 1 and 2 of the muon nexus file format. + It implements property initialization and some common for both versions methods. Required Properties: <UL> @@ -77,19 +75,20 @@ namespace Mantid /// Algorithm's category for identification overriding a virtual method virtual const std::string category() const { return "DataHandling\\Nexus;Muon"; } - /// do a quick check that this file can be loaded + /// do a quick check that this file can be loaded virtual bool quickFileCheck(const std::string& filePath,size_t nread,const file_header& header); /// check the structure of the file and return a value between 0 and 100 of how much this file can be loaded virtual int fileCheck(const std::string& filePath); protected: - /// Overwrites Algorithm method - void exec(); + virtual void runLoadInstrumentFromNexus(DataObjects::Workspace2D_sptr) {} void checkOptionalProperties(); void runLoadInstrument(DataObjects::Workspace2D_sptr); /// The name and path of the input file std::string m_filename; + /// The first top-level entry name in the file + std::string m_entry_name; /// The instrument name from Nexus std::string m_instrument_name; /// The sample name read from Nexus @@ -120,13 +119,6 @@ namespace Mantid virtual void initDocs(); /// Overwrites Algorithm method. void init(); - - void loadData(const MantidVecPtr::ptr_type& tcbs,size_t hist, specid_t& i, - MuonNexusReader& nxload, const int64_t lengthIn, DataObjects::Workspace2D_sptr localWorkspace); - void runLoadInstrumentFromNexus(DataObjects::Workspace2D_sptr); - void runLoadMappingTable(DataObjects::Workspace2D_sptr); - void runLoadLog(DataObjects::Workspace2D_sptr); - void loadRunDetails(DataObjects::Workspace2D_sptr localWorkspace); }; } // namespace DataHandling diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMuonNexus1.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMuonNexus1.h new file mode 100644 index 0000000000000000000000000000000000000000..671b0315371d525c33852436651e0a438998b48c --- /dev/null +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMuonNexus1.h @@ -0,0 +1,101 @@ +#ifndef MANTID_DATAHANDLING_LOADMUONNEXUS1_H_ +#define MANTID_DATAHANDLING_LOADMUONNEXUS1_H_ + +//---------------------------------------------------------------------- +// Includes +//---------------------------------------------------------------------- +#include "MantidDataHandling/LoadMuonNexus.h" +#include "MantidDataObjects/Workspace2D.h" +#include "MantidKernel/System.h" +#include "MantidAPI/SpectraDetectorMap.h" + +#include <napi.h> +//---------------------------------------------------------------------- +// Forward declaration +//---------------------------------------------------------------------- +class MuonNexusReader; + +namespace Mantid +{ + namespace DataHandling + { + /** @class LoadMuonNexus LoadMuonNexus.h DataHandling/LoadMuonNexus.h + + Loads an file in Nexus Muon format version 1 and stores it in a 2D workspace + (Workspace2D class). LoadMuonNexus is an algorithm and as such inherits + from the Algorithm class, via DataHandlingCommand, and overrides + the init() & exec() methods. + + Required Properties: + <UL> + <LI> Filename - The name of and path to the input NeXus file </LI> + <LI> OutputWorkspace - The name of the workspace in which to store the imported data + (a multiperiod file will store higher periods in workspaces called OutputWorkspace_PeriodNo) + [ not yet implemented for Nexus ]</LI> + </UL> + + Optional Properties: (note that these options are not available if reading a multiperiod file) + <UL> + <LI> spectrum_min - The spectrum to start loading from</LI> + <LI> spectrum_max - The spectrum to load to</LI> + <LI> spectrum_list - An ArrayProperty of spectra to load</LI> + <LI> auto_group - Determines whether the spectra are automatically grouped together based on the groupings in the NeXus file. </LI> + </UL> + + Copyright © 2007-2010 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + File change history is stored at: <https://github.com/mantidproject/mantid>. + Code Documentation is available at: <http://doxygen.mantidproject.org> + */ + class DLLExport LoadMuonNexus1 : public LoadMuonNexus + { + public: + /// Default constructor + LoadMuonNexus1(); + /// Destructor + virtual ~LoadMuonNexus1() {} + /// Algorithm's name for identification overriding a virtual method + virtual const std::string name() const { return "LoadMuonNexus"; } + /// Algorithm's version for identification overriding a virtual method + virtual int version() const { return 1; } + /// Algorithm's category for identification overriding a virtual method + virtual const std::string category() const { return "DataHandling\\Nexus;Muon"; } + + /// check the structure of the file and return a value between 0 and 100 of how much this file can be loaded + virtual int fileCheck(const std::string& filePath); + protected: + /// Overwrites Algorithm method + void exec(); + /// Implement the base class method + void runLoadInstrumentFromNexus(DataObjects::Workspace2D_sptr); + + private: + /// Sets documentation strings for this algorithm + virtual void initDocs(); + + void loadData(const MantidVecPtr::ptr_type& tcbs,size_t hist, specid_t& i, + MuonNexusReader& nxload, const int64_t lengthIn, DataObjects::Workspace2D_sptr localWorkspace); + void runLoadMappingTable(DataObjects::Workspace2D_sptr); + void runLoadLog(DataObjects::Workspace2D_sptr); + void loadRunDetails(DataObjects::Workspace2D_sptr localWorkspace); + }; + + } // namespace DataHandling +} // namespace Mantid + +#endif /*MANTID_DATAHANDLING_LOADMUONNEXUS1_H_*/ diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMuonNexus2.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMuonNexus2.h index edd5b5ed44c58ff1a9f508caaf90197cb17f32f2..1094ac22d002d8cbe60548ee63b77a2779f1f56d 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMuonNexus2.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMuonNexus2.h @@ -10,24 +10,12 @@ namespace Mantid { -namespace NeXus -{ - // Forward declarations - template<class T> - class NXDataSetTyped; - typedef NXDataSetTyped<int> NXInt; -} - namespace DataHandling { - // Forward declarations - template<class T> - class NXDataSetTyped; - typedef NXDataSetTyped<int> NXInt; /** - Loads an file in NeXus Muon format and stores it in a 2D workspace + Loads an file in NeXus Muon format version 1 and 2 and stores it in a 2D workspace (Workspace2D class). LoadMuonNexus is an algorithm and as such inherits from the Algorithm class, via DataHandlingCommand, and overrides the init() & exec() methods. @@ -82,8 +70,6 @@ namespace NeXus /// Algorithm's category for identification overriding a virtual method virtual const std::string category() const { return "DataHandling\\Nexus;Muon"; } - /// do a quick check that this file can be loaded - virtual bool quickFileCheck(const std::string& filePath,size_t nread,const file_header& header); /// check the structure of the file and return a value between 0 and 100 of how much this file can be loaded virtual int fileCheck(const std::string& filePath); private: @@ -91,6 +77,8 @@ namespace NeXus virtual void initDocs(); /// Overwrites Algorithm method void exec(); + /// Execute this version of the algorithm + void doExec(); void loadData(const Mantid::NeXus::NXInt& counts,const std::vector<double>& timeBins,int wsIndex, int period,int spec,API::MatrixWorkspace_sptr localWorkspace); diff --git a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus.cpp b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus.cpp index 53ea3c2f104aa9333b89aa5cdded0674a7598bb7..e043b3f973e636eae51e28645ab3253c043631ae 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus.cpp @@ -1,45 +1,3 @@ -/*WIKI* - - -The algorithm LoadMuonNexus will read a Muon Nexus data file (original format) and place the data -into the named workspace. -The file name can be an absolute or relative path and should have the extension -.nxs or .NXS. -If the file contains data for more than one period, a separate workspace will be generated for each. -After the first period the workspace names will have "_2", "_3", and so on, appended to the given workspace name. -For single period data, the optional parameters can be used to control which spectra are loaded into the workspace. -If spectrum_min and spectrum_max are given, then only that range to data will be loaded. -If a spectrum_list is given than those values will be loaded. -* TODO get XML descriptions of Muon instruments. This data is not in existing Muon Nexus files. -* TODO load the spectra detector mapping. This may be very simple for Muon instruments. - -===Time series data=== -The log data in the Nexus file (NX_LOG sections) will be loaded as TimeSeriesProperty data within the workspace. -Time is stored as seconds from the Unix epoch. - -===Errors=== - -The error for each histogram count is set as the square root of the number of counts. - -===Time bin data=== - -The ''corrected_times'' field of the Nexus file is used to provide time bin data and the bin edge values are calculated from these -bin centre times. - -===Multiperiod data=== - -To determine if a file contains data from more than one period the field ''switching_states'' is read from the Nexus file. -If this value is greater than one it is taken to be the number of periods, <math>N_p</math> of the data. -In this case the <math>N_s</math> spectra in the ''histogram_data'' field are split with <math>N_s/N_p</math> assigned to each period. - -===ChildAlgorithms used=== - -The ChildAlgorithms used by LoadMuonNexus are: -* LoadMuonLog - this reads log information from the Nexus file and uses it to create TimeSeriesProperty entries in the workspace. -* LoadInstrument - this algorithm looks for an XML description of the instrument and if found reads it. -* LoadIntstrumentFromNexus - this is called if the normal LoadInstrument fails. As the Nexus file has limited instrument data, this only populates a few fields. - -*WIKI*/ //---------------------------------------------------------------------- // Includes //---------------------------------------------------------------------- @@ -70,8 +28,6 @@ namespace Mantid { namespace DataHandling { - // Register the algorithm into the algorithm factory - DECLARE_ALGORITHM(LoadMuonNexus) /// Sets documentation strings for this algorithm void LoadMuonNexus::initDocs() @@ -139,396 +95,6 @@ namespace Mantid "The name of the vector in which to store the list of deadtimes for each spectrum", Direction::Output); } - /** Executes the algorithm. Reading in the file and creating and populating - * the output workspace - * - * @throw Exception::FileError If the Nexus file cannot be found/opened - * @throw std::invalid_argument If the optional properties are set to invalid values - */ - void LoadMuonNexus::exec() - { - // Retrieve the filename from the properties - m_filename = getPropertyValue("Filename"); - // Retrieve the entry number - m_entrynumber = getProperty("EntryNumber"); - - - - NXRoot root(m_filename); - NXEntry entry = root.openEntry("run/histogram_data_1"); - try - { - NXInfo info = entry.getDataSetInfo("time_zero"); - if (info.stat != NX_ERROR) - { - double dum = root.getFloat("run/histogram_data_1/time_zero"); - setProperty("TimeZero", dum); - } - } - catch (::NeXus::Exception&) - {} - - try - { - NXInfo infoResolution = entry.getDataSetInfo("resolution"); - NXInt counts = root.openNXInt("run/histogram_data_1/counts"); - std::string firstGoodBin = counts.attributes("first_good_bin"); - if ( !firstGoodBin.empty() && infoResolution.stat != NX_ERROR ) - { - double bin = static_cast<double>(boost::lexical_cast<int>(firstGoodBin)); - double bin_size = static_cast<double>(root.getInt("run/histogram_data_1/resolution"))/1000000.0; - setProperty("FirstGoodData", bin*bin_size); - } - } - catch (::NeXus::Exception&) - {} - - try - { - std::vector<double>defaultDeadTimes; - NXFloat deadTimes = root.openNXFloat("run/instrument/detector/deadtimes"); - deadTimes.load(); - - int length = deadTimes.dim0(); - for (int i = 0; i < length; i++) - { - defaultDeadTimes.push_back(static_cast<double>(*(deadTimes() + i) ) ); - } - setProperty("DeadTimes", defaultDeadTimes); - } - catch (::NeXus::Exception&) - {} - - NXEntry nxRun = root.openEntry("run"); - std::string title; - std::string notes; - try - { - title = nxRun.getString("title"); - notes = nxRun.getString("notes"); - } - catch (::NeXus::Exception&) - {} - std::string run_num; - try - { - run_num = boost::lexical_cast<std::string>(nxRun.getInt("number")); - } - catch (::NeXus::Exception&) - {} - - MuonNexusReader nxload; - if (nxload.readFromFile(m_filename) != 0) - { - g_log.error("Unable to open file " + m_filename); - throw Exception::FileError("Unable to open File:" , m_filename); - } - - // Read in the instrument name from the Nexus file - m_instrument_name = nxload.getInstrumentName(); - // Read in the number of spectra in the Nexus file - m_numberOfSpectra = nxload.t_nsp1; - if(m_entrynumber!=0) - { - m_numberOfPeriods=1; - if(m_entrynumber>nxload.t_nper) - { - throw std::invalid_argument("Invalid Entry Number:Enter a valid number"); - } - } - else - { - // Read the number of periods in this file - m_numberOfPeriods = nxload.t_nper; - } - // Need to extract the user-defined output workspace name - Property *ws = getProperty("OutputWorkspace"); - std::string localWSName = ws->value(); - // If multiperiod, will need to hold the Instrument, Sample & SpectraDetectorMap for copying - boost::shared_ptr<Instrument> instrument; - boost::shared_ptr<Sample> sample; - - // Call private method to validate the optional parameters, if set - checkOptionalProperties(); - - // Read the number of time channels (i.e. bins) from the Nexus file - const int channelsPerSpectrum = nxload.t_ntc1; - // Read in the time bin boundaries - const int lengthIn = channelsPerSpectrum + 1; - float* timeChannels = new float[lengthIn]; - nxload.getTimeChannels(timeChannels, lengthIn); - // Put the read in array into a vector (inside a shared pointer) - boost::shared_ptr<MantidVec> timeChannelsVec - (new MantidVec(timeChannels, timeChannels + lengthIn)); - - // Calculate the size of a workspace, given its number of periods & spectra to read - int64_t total_specs; - if( m_interval || m_list) - { - total_specs = m_spec_list.size(); - if (m_interval) - { - total_specs += (m_spec_max-m_spec_min+1); - m_spec_max += 1; - } - } - else - { - total_specs = m_numberOfSpectra; - // for nexus return all spectra - m_spec_min = 0; // changed to 0 for NeXus, was 1 for Raw - m_spec_max = m_numberOfSpectra; // was +1? - } - - // Create the 2D workspace for the output - DataObjects::Workspace2D_sptr localWorkspace = boost::dynamic_pointer_cast<DataObjects::Workspace2D> - (WorkspaceFactory::Instance().create("Workspace2D",total_specs,lengthIn,lengthIn-1)); - localWorkspace->setTitle(title); - localWorkspace->setComment(notes); - localWorkspace->mutableRun().addLogData(new PropertyWithValue<std::string>("run_number", run_num)); - // Set the unit on the workspace to muon time, for now in the form of a Label Unit - boost::shared_ptr<Kernel::Units::Label> lblUnit = - boost::dynamic_pointer_cast<Kernel::Units::Label>(UnitFactory::Instance().create("Label")); - lblUnit->setLabel("Time","microsecond"); - localWorkspace->getAxis(0)->unit() = lblUnit; - // Set y axis unit - localWorkspace->setYUnit("Counts"); - - WorkspaceGroup_sptr wsGrpSptr=WorkspaceGroup_sptr(new WorkspaceGroup); - if(m_numberOfPeriods>1) - { - setProperty("OutputWorkspace",boost::dynamic_pointer_cast<Workspace>(wsGrpSptr)); - } - - API::Progress progress(this,0.,1.,m_numberOfPeriods * total_specs); - // Loop over the number of periods in the Nexus file, putting each period in a separate workspace - for (int64_t period = 0; period < m_numberOfPeriods; ++period) { - if(m_entrynumber!=0) - { - period=m_entrynumber-1; - if(period!=0) - { - loadRunDetails(localWorkspace); - runLoadInstrument(localWorkspace ); - runLoadMappingTable(localWorkspace ); - } - } - - if (period == 0) - { - // Only run the Child Algorithms once - loadRunDetails(localWorkspace); - runLoadInstrument(localWorkspace ); - runLoadMappingTable(localWorkspace ); - runLoadLog(localWorkspace ); - localWorkspace->populateInstrumentParameters(); - } - else // We are working on a higher period of a multiperiod raw file - { - localWorkspace = boost::dynamic_pointer_cast<DataObjects::Workspace2D> - (WorkspaceFactory::Instance().create(localWorkspace)); - localWorkspace->setTitle(title); - localWorkspace->setComment(notes); - //localWorkspace->newInstrumentParameters(); ??? - - } - - - std::string outws(""); - if(m_numberOfPeriods>1) - { - std::string outputWorkspace = "OutputWorkspace"; - std::stringstream suffix; - suffix << (period+1); - outws =outputWorkspace+"_"+suffix.str(); - std::string WSName = localWSName + "_" + suffix.str(); - declareProperty(new WorkspaceProperty<Workspace>(outws,WSName,Direction::Output)); - if (wsGrpSptr) - { - wsGrpSptr->addWorkspace( localWorkspace ); - } - } - - size_t counter = 0; - for (int64_t i = m_spec_min; i < m_spec_max; ++i) - { - // Shift the histogram to read if we're not in the first period - specid_t histToRead = static_cast<specid_t>(i + period*total_specs); - loadData(timeChannelsVec,counter,histToRead,nxload,lengthIn-1,localWorkspace ); // added -1 for NeXus - counter++; - progress.report(); - } - // Read in the spectra in the optional list parameter, if set - if (m_list) - { - for(size_t i=0; i < m_spec_list.size(); ++i) - { - loadData(timeChannelsVec,counter,m_spec_list[i],nxload,lengthIn-1, localWorkspace ); - counter++; - progress.report(); - } - } - // Just a sanity check - assert(counter == size_t(total_specs) ); - - bool autogroup = getProperty("AutoGroup"); - - if (autogroup) - { - - //Get the groupings - int64_t max_group = 0; - // use a map for mapping group number and output workspace index in case - // there are group numbers > number of groups - std::map<int64_t,int64_t> groups; - m_groupings.resize(nxload.numDetectors); - bool thereAreZeroes = false; - for (int64_t i =0; i < static_cast<int64_t>(nxload.numDetectors); ++i) - { - int64_t ig = static_cast<int64_t>(nxload.detectorGroupings[i]); - if (ig == 0) - { - thereAreZeroes = true; - continue; - } - m_groupings[i] = static_cast<specid_t>(ig); - if (groups.find(ig) == groups.end()) - groups[ig] = static_cast<int64_t>(groups.size()); - if (ig > max_group) max_group = ig; - } - - if (thereAreZeroes) - for (int64_t i =0; i < static_cast<int64_t>(nxload.numDetectors); ++i) - { - int64_t ig = static_cast<int64_t>(nxload.detectorGroupings[i]); - if (ig == 0) - { - ig = ++max_group; - m_groupings[i] = static_cast<specid_t>(ig); - groups[ig] = groups.size(); - } - } - - int numHists = static_cast<int>(localWorkspace->getNumberHistograms()); - size_t ngroups = groups.size(); // number of groups - - // to output groups in ascending order - { - int64_t i=0; - for(std::map<int64_t,int64_t>::iterator it=groups.begin();it!=groups.end();++it,++i) - { - it->second = i; - g_log.information()<<"group "<<it->first<<": "; - bool first = true; - int64_t first_i = -1 * std::numeric_limits<int64_t>::max(); - int64_t last_i = -1 * std::numeric_limits<int64_t>::max(); - for(int64_t i=0;i<static_cast<int64_t>(numHists);i++) - if (m_groupings[i] == it->first) - { - if (first) - { - first = false; - g_log.information()<<i; - first_i = i; - } - else - { - if (first_i >= 0) - { - if (i > last_i + 1) - { - g_log.information()<<'-'<<i; - first_i = -1; - } - } - else - { - g_log.information()<<','<<i; - first_i = i; - } - } - last_i = i; - } - else - { - if (!first && first_i >= 0) - { - if (last_i > first_i) - g_log.information()<<'-'<<last_i; - first_i = -1; - } - } - if (first_i >= 0 && last_i > first_i) - g_log.information()<<'-'<<last_i; - g_log.information()<<'\n'; - } - } - - //Create a workspace with only two spectra for forward and back - DataObjects::Workspace2D_sptr groupedWS = boost::dynamic_pointer_cast<DataObjects::Workspace2D> - (API::WorkspaceFactory::Instance().create(localWorkspace, ngroups, localWorkspace->dataX(0).size(), localWorkspace->blocksize())); - - boost::shared_array<specid_t> spec(new specid_t[numHists]); - boost::shared_array<detid_t> dets(new detid_t[numHists]); - - //Compile the groups - for (int i = 0; i < numHists; ++i) - { - specid_t k = static_cast<specid_t>(groups[ m_groupings[numHists*period + i] ]); - - for (detid_t j = 0; j < static_cast<detid_t>(localWorkspace->blocksize()); ++j) - { - groupedWS->dataY(k)[j] = groupedWS->dataY(k)[j] + localWorkspace->dataY(i)[j]; - - //Add the errors in quadrature - groupedWS->dataE(k)[j] - = sqrt(pow(groupedWS->dataE(k)[j], 2) + pow(localWorkspace->dataE(i)[j], 2)); - } - - //Copy all the X data - groupedWS->dataX(k) = localWorkspace->dataX(i); - spec[i] = k + 1; - dets[i] = i + 1; - } - - m_groupings.clear(); - - // All two spectra - for(detid_t k=0; k<static_cast<detid_t>(ngroups); k++) - { - groupedWS->getAxis(1)->spectraNo(k)= k + 1; - } - - groupedWS->replaceSpectraMap(new API::SpectraDetectorMap(spec.get(),dets.get(),numHists)); - - // Assign the result to the output workspace property - if(m_numberOfPeriods>1) - setProperty(outws, boost::dynamic_pointer_cast<Workspace>(groupedWS)); - else - { - setProperty("OutputWorkspace",boost::dynamic_pointer_cast<Workspace>(groupedWS)); - - } - - } - else - { - // Assign the result to the output workspace property - if(m_numberOfPeriods>1) - setProperty(outws,boost::dynamic_pointer_cast<Workspace>(localWorkspace)); - else - { - setProperty("OutputWorkspace",boost::dynamic_pointer_cast<Workspace>(localWorkspace)); - } - - } - - } // loop over periods - - // Clean up - delete[] timeChannels; - } - /// Validates the optional 'spectra to read' properties, if they have been set void LoadMuonNexus::checkOptionalProperties() { @@ -564,91 +130,6 @@ namespace Mantid } } - /** Load in a single spectrum taken from a NeXus file - * @param tcbs :: The vector containing the time bin boundaries - * @param hist :: The workspace index - * @param i :: The spectrum number - * @param nxload :: A reference to the MuonNeXusReader object - * @param lengthIn :: The number of elements in a spectrum - * @param localWorkspace :: A pointer to the workspace in which the data will be stored - */ - void LoadMuonNexus::loadData(const MantidVecPtr::ptr_type& tcbs,size_t hist, specid_t& i, - MuonNexusReader& nxload, const int64_t lengthIn, DataObjects::Workspace2D_sptr localWorkspace) - { - // Read in a spectrum - // Put it into a vector, discarding the 1st entry, which is rubbish - // But note that the last (overflow) bin is kept - // For Nexus, not sure if above is the case, hence give all data for now - MantidVec& Y = localWorkspace->dataY(hist); - Y.assign(nxload.counts + i * lengthIn, nxload.counts + i * lengthIn + lengthIn); - // Create and fill another vector for the errors, containing sqrt(count) - MantidVec& E = localWorkspace->dataE(hist); - typedef double (*uf)(double); - uf dblSqrt = std::sqrt; - std::transform(Y.begin(), Y.end(), E.begin(), dblSqrt); - // Populate the workspace. Loop starts from 1, hence i-1 - localWorkspace->setX(hist, tcbs); - localWorkspace->getAxis(1)->spectraNo(hist)= static_cast<int>(hist) + 1; - } - - - /** Log the run details from the file - * @param localWorkspace :: The workspace details to use - */ - void LoadMuonNexus::loadRunDetails(DataObjects::Workspace2D_sptr localWorkspace) - { - API::Run & runDetails = localWorkspace->mutableRun(); - - runDetails.addProperty("run_title", localWorkspace->getTitle(), true); - - int numSpectra = static_cast<int>(localWorkspace->getNumberHistograms()); - runDetails.addProperty("nspectra", numSpectra); - - NXRoot root(m_filename); - try - { - std::string start_time = root.getString("run/start_time"); - runDetails.addProperty("run_start", start_time); - } - catch (std::runtime_error &) - { - g_log.warning("run/start_time is not available, run_start log not added."); - } - - - try - { - std::string stop_time = root.getString("run/stop_time"); - runDetails.addProperty("run_end", stop_time); - } - catch (std::runtime_error &) - { - g_log.warning("run/stop_time is not available, run_end log not added."); - } - - try - { - std::string dur = root.getString("run/duration"); - runDetails.addProperty("dur", dur); - runDetails.addProperty("durunits", 1); // 1 means second here - runDetails.addProperty("dur_secs", dur); - } - catch (std::runtime_error &) - { - g_log.warning("run/duration is not available, dur log not added."); - } - - // Get number of good frames - NXEntry runInstrumentBeam = root.openEntry("run/instrument/beam"); - NXInfo infoGoodTotalFrames = runInstrumentBeam.getDataSetInfo("frames_good"); - if (infoGoodTotalFrames.stat != NX_ERROR) - { - int dum = root.getInt("run/instrument/beam/frames_good"); - runDetails.addProperty("goodfrm", dum); - } - - } - /// Run the Child Algorithm LoadInstrument (or LoadInstrumentFromNexus) void LoadMuonNexus::runLoadInstrument(DataObjects::Workspace2D_sptr localWorkspace) { @@ -682,104 +163,6 @@ namespace Mantid } } - /// Run LoadInstrumentFromNexus as a Child Algorithm (only if loading from instrument definition file fails) - void LoadMuonNexus::runLoadInstrumentFromNexus(DataObjects::Workspace2D_sptr localWorkspace) - { - g_log.information() << "Instrument definition file not found. Attempt to load information about \n" - << "the instrument from nexus data file.\n"; - - IAlgorithm_sptr loadInst = createChildAlgorithm("LoadInstrumentFromNexus"); - - // Now execute the Child Algorithm. Catch and log any error, but don't stop. - bool executionSuccessful(true); - try - { - loadInst->setPropertyValue("Filename", m_filename); - loadInst->setProperty<MatrixWorkspace_sptr> ("Workspace", localWorkspace); - loadInst->execute(); - } - catch( std::invalid_argument&) - { - g_log.information("Invalid argument to LoadInstrument Child Algorithm"); - executionSuccessful = false; - } - catch (std::runtime_error&) - { - g_log.information("Unable to successfully run LoadInstrument Child Algorithm"); - executionSuccessful = false; - } - - if ( !executionSuccessful ) g_log.error("No instrument definition loaded"); - } - - /// Run the LoadMappingTable Child Algorithm to fill the SpectraToDetectorMap - void LoadMuonNexus::runLoadMappingTable(DataObjects::Workspace2D_sptr localWorkspace) - { - NXRoot root(m_filename); - NXInt number = root.openNXInt("run/instrument/detector/number"); - number.load(); - detid_t ndet = static_cast<detid_t>(number[0]/m_numberOfPeriods); - boost::shared_array<detid_t> det(new detid_t[ndet]); - for(detid_t i=0;i<ndet;i++) - { - det[i] = i + 1; - } - localWorkspace->replaceSpectraMap(new API::SpectraDetectorMap(det.get(),det.get(),ndet)); - } - - /// Run the LoadLog Child Algorithm - void LoadMuonNexus::runLoadLog(DataObjects::Workspace2D_sptr localWorkspace) - { - IAlgorithm_sptr loadLog = createChildAlgorithm("LoadMuonLog"); - // Pass through the same input filename - loadLog->setPropertyValue("Filename",m_filename); - // Set the workspace property to be the same one filled above - loadLog->setProperty<MatrixWorkspace_sptr>("Workspace",localWorkspace); - - // Now execute the Child Algorithm. Catch and log any error, but don't stop. - try - { - loadLog->execute(); - } - catch (std::runtime_error&) - { - g_log.error("Unable to successfully run LoadLog Child Algorithm"); - } - catch (std::logic_error&) - { - g_log.error("Unable to successfully run LoadLog Child Algorithm"); - } - - if ( ! loadLog->isExecuted() ) g_log.error("Unable to successfully run LoadLog Child Algorithm"); - - - NXRoot root(m_filename); - - try - { - NXChar orientation = root.openNXChar("run/instrument/detector/orientation"); - // some files have no data there - orientation.load(); - - if (orientation[0] == 't') - { - Kernel::TimeSeriesProperty<double>* p = new Kernel::TimeSeriesProperty<double>("fromNexus"); - std::string start_time = root.getString("run/start_time"); - p->addValue(start_time,-90.0); - localWorkspace->mutableRun().addLogData(p); - setProperty("MainFieldDirection", "Transverse"); - } - else - { - setProperty("MainFieldDirection", "Longitudinal"); - } - } - catch(...) - { - setProperty("MainFieldDirection", "Longitudinal"); - } - - } /**This method does a quick file type check by looking at the first 100 bytes of the file * @param filePath- path of the file including name. @@ -807,7 +190,6 @@ namespace Mantid return true; } return false; - } /**checks the file by opening it and reading few lines * @param filePath :: name of the file inluding its path @@ -815,26 +197,8 @@ namespace Mantid */ int LoadMuonNexus::fileCheck(const std::string& filePath) { - using namespace ::NeXus; - int confidence(0); - try - { - ::NeXus::File file = ::NeXus::File(filePath); - file.openPath("/run/analysis"); - std::string analysisType = file.getStrData(); - std::string compareString = "muon"; - if( analysisType.compare(0,compareString.length(),compareString) == 0 ) - { - // If all this succeeded then we'll assume this is an ISIS Muon NeXus file - confidence = 80; - } - file.close(); - } - catch(::NeXus::Exception&) - { - } - return confidence; - + UNUSED_ARG( filePath ); + throw Kernel::Exception::NotImplementedError("LoadMuonNexus cannot be used as a file checker."); } } // namespace DataHandling diff --git a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ce959c6405d7debe2386cca117ffdec2f1ccb7cf --- /dev/null +++ b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp @@ -0,0 +1,696 @@ +/*WIKI* + + +The algorithm LoadMuonNexus will read a Muon Nexus data file (original format) and place the data +into the named workspace. +The file name can be an absolute or relative path and should have the extension +.nxs or .NXS. +If the file contains data for more than one period, a separate workspace will be generated for each. +After the first period the workspace names will have "_2", "_3", and so on, appended to the given workspace name. +For single period data, the optional parameters can be used to control which spectra are loaded into the workspace. +If spectrum_min and spectrum_max are given, then only that range to data will be loaded. +If a spectrum_list is given than those values will be loaded. +* TODO get XML descriptions of Muon instruments. This data is not in existing Muon Nexus files. +* TODO load the spectra detector mapping. This may be very simple for Muon instruments. + +===Time series data=== +The log data in the Nexus file (NX_LOG sections) will be loaded as TimeSeriesProperty data within the workspace. +Time is stored as seconds from the Unix epoch. + +===Errors=== + +The error for each histogram count is set as the square root of the number of counts. + +===Time bin data=== + +The ''corrected_times'' field of the Nexus file is used to provide time bin data and the bin edge values are calculated from these +bin centre times. + +===Multiperiod data=== + +To determine if a file contains data from more than one period the field ''switching_states'' is read from the Nexus file. +If this value is greater than one it is taken to be the number of periods, <math>N_p</math> of the data. +In this case the <math>N_s</math> spectra in the ''histogram_data'' field are split with <math>N_s/N_p</math> assigned to each period. + +===ChildAlgorithms used=== + +The ChildAlgorithms used by LoadMuonNexus are: +* LoadMuonLog - this reads log information from the Nexus file and uses it to create TimeSeriesProperty entries in the workspace. +* LoadInstrument - this algorithm looks for an XML description of the instrument and if found reads it. +* LoadIntstrumentFromNexus - this is called if the normal LoadInstrument fails. As the Nexus file has limited instrument data, this only populates a few fields. + +*WIKI*/ +//---------------------------------------------------------------------- +// Includes +//---------------------------------------------------------------------- +#include "MantidDataHandling/LoadMuonNexus1.h" +#include "MantidDataObjects/Workspace2D.h" +#include "MantidAPI/LoadAlgorithmFactory.h" +#include "MantidAPI/FileProperty.h" +#include "MantidAPI/Progress.h" +#include "MantidAPI/SpectraDetectorMap.h" +#include "MantidAPI/TableRow.h" +#include "MantidGeometry/Instrument/Detector.h" +#include "MantidKernel/UnitFactory.h" +#include "MantidKernel/ConfigService.h" +#include "MantidKernel/ArrayProperty.h" +#include "MantidKernel/TimeSeriesProperty.h" +#include "MantidKernel/BoundedValidator.h" +#include "MantidKernel/ListValidator.h" +#include "MantidNexus/MuonNexusReader.h" +#include "MantidNexus/NexusClasses.h" + +#include <Poco/Path.h> +#include <limits> +#include <cmath> +#include <boost/shared_ptr.hpp> + +namespace Mantid +{ + namespace DataHandling + { + // Register the algorithm into the algorithm factory + DECLARE_ALGORITHM(LoadMuonNexus1) + DECLARE_LOADALGORITHM(LoadMuonNexus1) + + /// Sets documentation strings for this algorithm + void LoadMuonNexus1::initDocs() + { + this->setWikiSummary("The LoadMuonNexus algorithm will read the given NeXus Muon data file Version 1 and use the results to populate the named workspace. LoadMuonNexus may be invoked by [[LoadNexus]] if it is given a NeXus file of this type. "); + this->setOptionalMessage("The LoadMuonNexus algorithm will read the given NeXus Muon data file Version 1 and use the results to populate the named workspace. LoadMuonNexus may be invoked by LoadNexus if it is given a NeXus file of this type."); + } + + + using namespace Kernel; + using namespace API; + using Geometry::Instrument; + using namespace Mantid::NeXus; + + /// Empty default constructor + LoadMuonNexus1::LoadMuonNexus1() : LoadMuonNexus() {} + + /** Executes the algorithm. Reading in the file and creating and populating + * the output workspace + * + * @throw Exception::FileError If the Nexus file cannot be found/opened + * @throw std::invalid_argument If the optional properties are set to invalid values + */ + void LoadMuonNexus1::exec() + { + // Retrieve the filename from the properties + m_filename = getPropertyValue("Filename"); + // Retrieve the entry number + m_entrynumber = getProperty("EntryNumber"); + + NXRoot root(m_filename); + NXEntry entry = root.openEntry("run/histogram_data_1"); + try + { + NXInfo info = entry.getDataSetInfo("time_zero"); + if (info.stat != NX_ERROR) + { + double dum = root.getFloat("run/histogram_data_1/time_zero"); + setProperty("TimeZero", dum); + } + } + catch (::NeXus::Exception&) + {} + + try + { + NXInfo infoResolution = entry.getDataSetInfo("resolution"); + NXInt counts = root.openNXInt("run/histogram_data_1/counts"); + std::string firstGoodBin = counts.attributes("first_good_bin"); + if ( !firstGoodBin.empty() && infoResolution.stat != NX_ERROR ) + { + double bin = static_cast<double>(boost::lexical_cast<int>(firstGoodBin)); + double bin_size = static_cast<double>(root.getInt("run/histogram_data_1/resolution"))/1000000.0; + setProperty("FirstGoodData", bin*bin_size); + } + } + catch (::NeXus::Exception&) + {} + + try + { + std::vector<double>defaultDeadTimes; + NXFloat deadTimes = root.openNXFloat("run/instrument/detector/deadtimes"); + deadTimes.load(); + + int length = deadTimes.dim0(); + for (int i = 0; i < length; i++) + { + defaultDeadTimes.push_back(static_cast<double>(*(deadTimes() + i) ) ); + } + setProperty("DeadTimes", defaultDeadTimes); + } + catch (::NeXus::Exception&) + {} + + NXEntry nxRun = root.openEntry("run"); + std::string title; + std::string notes; + try + { + title = nxRun.getString("title"); + notes = nxRun.getString("notes"); + } + catch (::NeXus::Exception&) + {} + std::string run_num; + try + { + run_num = boost::lexical_cast<std::string>(nxRun.getInt("number")); + } + catch (::NeXus::Exception&) + {} + + MuonNexusReader nxload; + if (nxload.readFromFile(m_filename) != 0) + { + g_log.error("Unable to open file " + m_filename); + throw Exception::FileError("Unable to open File:" , m_filename); + } + + // Read in the instrument name from the Nexus file + m_instrument_name = nxload.getInstrumentName(); + // Read in the number of spectra in the Nexus file + m_numberOfSpectra = nxload.t_nsp1; + if(m_entrynumber!=0) + { + m_numberOfPeriods=1; + if(m_entrynumber>nxload.t_nper) + { + throw std::invalid_argument("Invalid Entry Number:Enter a valid number"); + } + } + else + { + // Read the number of periods in this file + m_numberOfPeriods = nxload.t_nper; + } + // Need to extract the user-defined output workspace name + Property *ws = getProperty("OutputWorkspace"); + std::string localWSName = ws->value(); + // If multiperiod, will need to hold the Instrument, Sample & SpectraDetectorMap for copying + boost::shared_ptr<Instrument> instrument; + boost::shared_ptr<Sample> sample; + + // Call private method to validate the optional parameters, if set + checkOptionalProperties(); + + // Read the number of time channels (i.e. bins) from the Nexus file + const int channelsPerSpectrum = nxload.t_ntc1; + // Read in the time bin boundaries + const int lengthIn = channelsPerSpectrum + 1; + float* timeChannels = new float[lengthIn]; + nxload.getTimeChannels(timeChannels, lengthIn); + // Put the read in array into a vector (inside a shared pointer) + boost::shared_ptr<MantidVec> timeChannelsVec + (new MantidVec(timeChannels, timeChannels + lengthIn)); + + // Calculate the size of a workspace, given its number of periods & spectra to read + int64_t total_specs; + if( m_interval || m_list) + { + total_specs = m_spec_list.size(); + if (m_interval) + { + total_specs += (m_spec_max-m_spec_min+1); + m_spec_max += 1; + } + } + else + { + total_specs = m_numberOfSpectra; + // for nexus return all spectra + m_spec_min = 0; // changed to 0 for NeXus, was 1 for Raw + m_spec_max = m_numberOfSpectra; // was +1? + } + + // Create the 2D workspace for the output + DataObjects::Workspace2D_sptr localWorkspace = boost::dynamic_pointer_cast<DataObjects::Workspace2D> + (WorkspaceFactory::Instance().create("Workspace2D",total_specs,lengthIn,lengthIn-1)); + localWorkspace->setTitle(title); + localWorkspace->setComment(notes); + localWorkspace->mutableRun().addLogData(new PropertyWithValue<std::string>("run_number", run_num)); + // Set the unit on the workspace to muon time, for now in the form of a Label Unit + boost::shared_ptr<Kernel::Units::Label> lblUnit = + boost::dynamic_pointer_cast<Kernel::Units::Label>(UnitFactory::Instance().create("Label")); + lblUnit->setLabel("Time","microsecond"); + localWorkspace->getAxis(0)->unit() = lblUnit; + // Set y axis unit + localWorkspace->setYUnit("Counts"); + + WorkspaceGroup_sptr wsGrpSptr=WorkspaceGroup_sptr(new WorkspaceGroup); + if(m_numberOfPeriods>1) + { + setProperty("OutputWorkspace",boost::dynamic_pointer_cast<Workspace>(wsGrpSptr)); + } + + API::Progress progress(this,0.,1.,m_numberOfPeriods * total_specs); + // Loop over the number of periods in the Nexus file, putting each period in a separate workspace + for (int64_t period = 0; period < m_numberOfPeriods; ++period) { + if(m_entrynumber!=0) + { + period=m_entrynumber-1; + if(period!=0) + { + loadRunDetails(localWorkspace); + runLoadInstrument(localWorkspace ); + runLoadMappingTable(localWorkspace ); + } + } + + if (period == 0) + { + // Only run the Child Algorithms once + loadRunDetails(localWorkspace); + runLoadInstrument(localWorkspace ); + runLoadMappingTable(localWorkspace ); + runLoadLog(localWorkspace ); + localWorkspace->populateInstrumentParameters(); + } + else // We are working on a higher period of a multiperiod raw file + { + localWorkspace = boost::dynamic_pointer_cast<DataObjects::Workspace2D> + (WorkspaceFactory::Instance().create(localWorkspace)); + localWorkspace->setTitle(title); + localWorkspace->setComment(notes); + //localWorkspace->newInstrumentParameters(); ??? + + } + + + std::string outws(""); + if(m_numberOfPeriods>1) + { + std::string outputWorkspace = "OutputWorkspace"; + std::stringstream suffix; + suffix << (period+1); + outws =outputWorkspace+"_"+suffix.str(); + std::string WSName = localWSName + "_" + suffix.str(); + declareProperty(new WorkspaceProperty<Workspace>(outws,WSName,Direction::Output)); + if (wsGrpSptr) + { + wsGrpSptr->addWorkspace( localWorkspace ); + } + } + + size_t counter = 0; + for (int64_t i = m_spec_min; i < m_spec_max; ++i) + { + // Shift the histogram to read if we're not in the first period + specid_t histToRead = static_cast<specid_t>(i + period*total_specs); + loadData(timeChannelsVec,counter,histToRead,nxload,lengthIn-1,localWorkspace ); // added -1 for NeXus + counter++; + progress.report(); + } + // Read in the spectra in the optional list parameter, if set + if (m_list) + { + for(size_t i=0; i < m_spec_list.size(); ++i) + { + loadData(timeChannelsVec,counter,m_spec_list[i],nxload,lengthIn-1, localWorkspace ); + counter++; + progress.report(); + } + } + // Just a sanity check + assert(counter == size_t(total_specs) ); + + bool autogroup = getProperty("AutoGroup"); + + if (autogroup) + { + + //Get the groupings + int64_t max_group = 0; + // use a map for mapping group number and output workspace index in case + // there are group numbers > number of groups + std::map<int64_t,int64_t> groups; + m_groupings.resize(nxload.numDetectors); + bool thereAreZeroes = false; + for (int64_t i =0; i < static_cast<int64_t>(nxload.numDetectors); ++i) + { + int64_t ig = static_cast<int64_t>(nxload.detectorGroupings[i]); + if (ig == 0) + { + thereAreZeroes = true; + continue; + } + m_groupings[i] = static_cast<specid_t>(ig); + if (groups.find(ig) == groups.end()) + groups[ig] = static_cast<int64_t>(groups.size()); + if (ig > max_group) max_group = ig; + } + + if (thereAreZeroes) + for (int64_t i =0; i < static_cast<int64_t>(nxload.numDetectors); ++i) + { + int64_t ig = static_cast<int64_t>(nxload.detectorGroupings[i]); + if (ig == 0) + { + ig = ++max_group; + m_groupings[i] = static_cast<specid_t>(ig); + groups[ig] = groups.size(); + } + } + + int numHists = static_cast<int>(localWorkspace->getNumberHistograms()); + size_t ngroups = groups.size(); // number of groups + + // to output groups in ascending order + { + int64_t i=0; + for(std::map<int64_t,int64_t>::iterator it=groups.begin();it!=groups.end();++it,++i) + { + it->second = i; + g_log.information()<<"group "<<it->first<<": "; + bool first = true; + int64_t first_i = -1 * std::numeric_limits<int64_t>::max(); + int64_t last_i = -1 * std::numeric_limits<int64_t>::max(); + for(int64_t i=0;i<static_cast<int64_t>(numHists);i++) + if (m_groupings[i] == it->first) + { + if (first) + { + first = false; + g_log.information()<<i; + first_i = i; + } + else + { + if (first_i >= 0) + { + if (i > last_i + 1) + { + g_log.information()<<'-'<<i; + first_i = -1; + } + } + else + { + g_log.information()<<','<<i; + first_i = i; + } + } + last_i = i; + } + else + { + if (!first && first_i >= 0) + { + if (last_i > first_i) + g_log.information()<<'-'<<last_i; + first_i = -1; + } + } + if (first_i >= 0 && last_i > first_i) + g_log.information()<<'-'<<last_i; + g_log.information()<<'\n'; + } + } + + //Create a workspace with only two spectra for forward and back + DataObjects::Workspace2D_sptr groupedWS = boost::dynamic_pointer_cast<DataObjects::Workspace2D> + (API::WorkspaceFactory::Instance().create(localWorkspace, ngroups, localWorkspace->dataX(0).size(), localWorkspace->blocksize())); + + boost::shared_array<specid_t> spec(new specid_t[numHists]); + boost::shared_array<detid_t> dets(new detid_t[numHists]); + + //Compile the groups + for (int i = 0; i < numHists; ++i) + { + specid_t k = static_cast<specid_t>(groups[ m_groupings[numHists*period + i] ]); + + for (detid_t j = 0; j < static_cast<detid_t>(localWorkspace->blocksize()); ++j) + { + groupedWS->dataY(k)[j] = groupedWS->dataY(k)[j] + localWorkspace->dataY(i)[j]; + + //Add the errors in quadrature + groupedWS->dataE(k)[j] + = sqrt(pow(groupedWS->dataE(k)[j], 2) + pow(localWorkspace->dataE(i)[j], 2)); + } + + //Copy all the X data + groupedWS->dataX(k) = localWorkspace->dataX(i); + spec[i] = k + 1; + dets[i] = i + 1; + } + + m_groupings.clear(); + + // All two spectra + for(detid_t k=0; k<static_cast<detid_t>(ngroups); k++) + { + groupedWS->getAxis(1)->spectraNo(k)= k + 1; + } + + groupedWS->replaceSpectraMap(new API::SpectraDetectorMap(spec.get(),dets.get(),numHists)); + + // Assign the result to the output workspace property + if(m_numberOfPeriods>1) + setProperty(outws, boost::dynamic_pointer_cast<Workspace>(groupedWS)); + else + { + setProperty("OutputWorkspace",boost::dynamic_pointer_cast<Workspace>(groupedWS)); + + } + + } + else + { + // Assign the result to the output workspace property + if(m_numberOfPeriods>1) + setProperty(outws,boost::dynamic_pointer_cast<Workspace>(localWorkspace)); + else + { + setProperty("OutputWorkspace",boost::dynamic_pointer_cast<Workspace>(localWorkspace)); + } + + } + + } // loop over periods + + // Clean up + delete[] timeChannels; + } + + /** Load in a single spectrum taken from a NeXus file + * @param tcbs :: The vector containing the time bin boundaries + * @param hist :: The workspace index + * @param i :: The spectrum number + * @param nxload :: A reference to the MuonNeXusReader object + * @param lengthIn :: The number of elements in a spectrum + * @param localWorkspace :: A pointer to the workspace in which the data will be stored + */ + void LoadMuonNexus1::loadData(const MantidVecPtr::ptr_type& tcbs,size_t hist, specid_t& i, + MuonNexusReader& nxload, const int64_t lengthIn, DataObjects::Workspace2D_sptr localWorkspace) + { + // Read in a spectrum + // Put it into a vector, discarding the 1st entry, which is rubbish + // But note that the last (overflow) bin is kept + // For Nexus, not sure if above is the case, hence give all data for now + MantidVec& Y = localWorkspace->dataY(hist); + Y.assign(nxload.counts + i * lengthIn, nxload.counts + i * lengthIn + lengthIn); + // Create and fill another vector for the errors, containing sqrt(count) + MantidVec& E = localWorkspace->dataE(hist); + typedef double (*uf)(double); + uf dblSqrt = std::sqrt; + std::transform(Y.begin(), Y.end(), E.begin(), dblSqrt); + // Populate the workspace. Loop starts from 1, hence i-1 + localWorkspace->setX(hist, tcbs); + localWorkspace->getAxis(1)->spectraNo(hist)= static_cast<int>(hist) + 1; + } + + + /** Log the run details from the file + * @param localWorkspace :: The workspace details to use + */ + void LoadMuonNexus1::loadRunDetails(DataObjects::Workspace2D_sptr localWorkspace) + { + API::Run & runDetails = localWorkspace->mutableRun(); + + runDetails.addProperty("run_title", localWorkspace->getTitle(), true); + + int numSpectra = static_cast<int>(localWorkspace->getNumberHistograms()); + runDetails.addProperty("nspectra", numSpectra); + + NXRoot root(m_filename); + try + { + std::string start_time = root.getString("run/start_time"); + runDetails.addProperty("run_start", start_time); + } + catch (std::runtime_error &) + { + g_log.warning("run/start_time is not available, run_start log not added."); + } + + + try + { + std::string stop_time = root.getString("run/stop_time"); + runDetails.addProperty("run_end", stop_time); + } + catch (std::runtime_error &) + { + g_log.warning("run/stop_time is not available, run_end log not added."); + } + + try + { + std::string dur = root.getString("run/duration"); + runDetails.addProperty("dur", dur); + runDetails.addProperty("durunits", 1); // 1 means second here + runDetails.addProperty("dur_secs", dur); + } + catch (std::runtime_error &) + { + g_log.warning("run/duration is not available, dur log not added."); + } + + // Get number of good frames + NXEntry runInstrumentBeam = root.openEntry("run/instrument/beam"); + NXInfo infoGoodTotalFrames = runInstrumentBeam.getDataSetInfo("frames_good"); + if (infoGoodTotalFrames.stat != NX_ERROR) + { + int dum = root.getInt("run/instrument/beam/frames_good"); + runDetails.addProperty("goodfrm", dum); + } + + } + + /// Run LoadInstrumentFromNexus as a Child Algorithm (only if loading from instrument definition file fails) + void LoadMuonNexus1::runLoadInstrumentFromNexus(DataObjects::Workspace2D_sptr localWorkspace) + { + g_log.information() << "Instrument definition file not found. Attempt to load information about \n" + << "the instrument from nexus data file.\n"; + + IAlgorithm_sptr loadInst = createChildAlgorithm("LoadInstrumentFromNexus"); + + // Now execute the Child Algorithm. Catch and log any error, but don't stop. + bool executionSuccessful(true); + try + { + loadInst->setPropertyValue("Filename", m_filename); + loadInst->setProperty<MatrixWorkspace_sptr> ("Workspace", localWorkspace); + loadInst->execute(); + } + catch( std::invalid_argument&) + { + g_log.information("Invalid argument to LoadInstrument Child Algorithm"); + executionSuccessful = false; + } + catch (std::runtime_error&) + { + g_log.information("Unable to successfully run LoadInstrument Child Algorithm"); + executionSuccessful = false; + } + + if ( !executionSuccessful ) g_log.error("No instrument definition loaded"); + } + + /// Run the LoadMappingTable Child Algorithm to fill the SpectraToDetectorMap + void LoadMuonNexus1::runLoadMappingTable(DataObjects::Workspace2D_sptr localWorkspace) + { + NXRoot root(m_filename); + NXInt number = root.openNXInt("run/instrument/detector/number"); + number.load(); + detid_t ndet = static_cast<detid_t>(number[0]/m_numberOfPeriods); + boost::shared_array<detid_t> det(new detid_t[ndet]); + for(detid_t i=0;i<ndet;i++) + { + det[i] = i + 1; + } + localWorkspace->replaceSpectraMap(new API::SpectraDetectorMap(det.get(),det.get(),ndet)); + } + + /// Run the LoadLog Child Algorithm + void LoadMuonNexus1::runLoadLog(DataObjects::Workspace2D_sptr localWorkspace) + { + IAlgorithm_sptr loadLog = createChildAlgorithm("LoadMuonLog"); + // Pass through the same input filename + loadLog->setPropertyValue("Filename",m_filename); + // Set the workspace property to be the same one filled above + loadLog->setProperty<MatrixWorkspace_sptr>("Workspace",localWorkspace); + + // Now execute the Child Algorithm. Catch and log any error, but don't stop. + try + { + loadLog->execute(); + } + catch (std::runtime_error&) + { + g_log.error("Unable to successfully run LoadLog Child Algorithm"); + } + catch (std::logic_error&) + { + g_log.error("Unable to successfully run LoadLog Child Algorithm"); + } + + if ( ! loadLog->isExecuted() ) g_log.error("Unable to successfully run LoadLog Child Algorithm"); + + + NXRoot root(m_filename); + + try + { + NXChar orientation = root.openNXChar("run/instrument/detector/orientation"); + // some files have no data there + orientation.load(); + + if (orientation[0] == 't') + { + Kernel::TimeSeriesProperty<double>* p = new Kernel::TimeSeriesProperty<double>("fromNexus"); + std::string start_time = root.getString("run/start_time"); + p->addValue(start_time,-90.0); + localWorkspace->mutableRun().addLogData(p); + setProperty("MainFieldDirection", "Transverse"); + } + else + { + setProperty("MainFieldDirection", "Longitudinal"); + } + } + catch(...) + { + setProperty("MainFieldDirection", "Longitudinal"); + } + + } + + /**checks the file by opening it and reading few lines + * @param filePath :: name of the file inluding its path + * @return an integer value how much this algorithm can load the file + */ + int LoadMuonNexus1::fileCheck(const std::string& filePath) + { + try + { + NXRoot root(filePath); + NXEntry entry = root.openFirstEntry(); + if ( ! entry.containsDataSet( "analysis" ) ) return 0; + std::string versionField = "IDF_version"; + if ( ! entry.containsDataSet( versionField ) ) + { + versionField = "idf_version"; + if ( ! entry.containsDataSet( versionField ) ) return 0; + } + if ( entry.getInt( versionField ) != 1 ) return 0; + std::string definition = entry.getString( "analysis" ); + if ( definition == "muonTD" || definition == "pulsedTD" ) + { + // If all this succeeded then we'll assume this is an ISIS Muon NeXus file version 1 + return 81; + } + } + catch(...) + { + } + return 0; + } + + } // namespace DataHandling +} // namespace Mantid diff --git a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus2.cpp b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus2.cpp index 0ad28d34e658c615dd428b1cef3ec62aa9b9eed8..3a7eeba29f7b028d627da44d2c8ce6ed7db2815f 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus2.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus2.cpp @@ -2,21 +2,21 @@ // Includes //---------------------------------------------------------------------- #include "MantidDataHandling/LoadMuonNexus2.h" +#include "MantidDataHandling/LoadMuonNexus1.h" #include "MantidDataObjects/Workspace2D.h" -#include "MantidKernel/UnitFactory.h" -#include "MantidKernel/ConfigService.h" -#include "MantidKernel/ArrayProperty.h" #include "MantidAPI/FileProperty.h" -#include "MantidKernel/TimeSeriesProperty.h" -#include "MantidGeometry/Instrument/Detector.h" #include "MantidAPI/Progress.h" #include "MantidAPI/SpectraDetectorMap.h" +#include "MantidAPI/LoadAlgorithmFactory.h" +#include "MantidGeometry/Instrument/Detector.h" +#include "MantidKernel/TimeSeriesProperty.h" +#include "MantidKernel/UnitFactory.h" +#include "MantidKernel/ConfigService.h" +#include "MantidKernel/ArrayProperty.h" #include "MantidNexus/NexusClasses.h" #include "MantidNexusCPP/NeXusFile.hpp" #include "MantidNexusCPP/NeXusException.hpp" - -#include "MantidAPI/LoadAlgorithmFactory.h" #include <Poco/Path.h> #include <boost/lexical_cast.hpp> #include <boost/shared_ptr.hpp> @@ -40,8 +40,8 @@ namespace Mantid /// Sets documentation strings for this algorithm void LoadMuonNexus2::initDocs() { - this->setWikiSummary("The LoadMuonNexus algorithm will read the given NeXus Muon data file Version 1 and use the results to populate the named workspace. LoadMuonNexus may be invoked by [[LoadNexus]] if it is given a NeXus file of this type. "); - this->setOptionalMessage("The LoadMuonNexus algorithm will read the given NeXus Muon data file Version 1 and use the results to populate the named workspace. LoadMuonNexus may be invoked by LoadNexus if it is given a NeXus file of this type."); + this->setWikiSummary("The LoadMuonNexus algorithm will read the given NeXus Muon data file Version 2 and use the results to populate the named workspace. LoadMuonNexus may be invoked by [[LoadNexus]] if it is given a NeXus file of this type. "); + this->setOptionalMessage("The LoadMuonNexus algorithm will read the given NeXus Muon data file Version 2 and use the results to populate the named workspace. LoadMuonNexus may be invoked by LoadNexus if it is given a NeXus file of this type."); } @@ -49,13 +49,49 @@ namespace Mantid LoadMuonNexus2::LoadMuonNexus2() : LoadMuonNexus() {} - /** Executes the algorithm. Reading in the file and creating and populating - * the output workspace + /** Executes the right version of the muon nexus loader: versions 1 or 2. * * @throw Exception::FileError If the Nexus file cannot be found/opened * @throw std::invalid_argument If the optional properties are set to invalid values */ void LoadMuonNexus2::exec() + { + std::string filePath = getPropertyValue("Filename"); + LoadMuonNexus1 load1; load1.initialize(); + + int confidence1 = load1.fileCheck( filePath ); + int confidence2 = this->fileCheck( filePath ); + + // if none can load the file throw + if ( confidence1 < 80 && confidence2 < 80) + { + throw Kernel::Exception::FileError("Cannot open the file ", filePath); + } + + if ( confidence2 > confidence1 ) + { + // this loader + doExec(); + } + else + { + // version 1 loader + IAlgorithm_sptr childAlg = createChildAlgorithm("LoadMuonNexus",0,1,true,1); + auto version1Loader = boost::dynamic_pointer_cast<API::Algorithm>( childAlg ); + version1Loader->copyPropertiesFrom( *this ); + version1Loader->executeAsChildAlg(); + this->copyPropertiesFrom( *version1Loader ); + API::Workspace_sptr outWS = version1Loader->getProperty("OutputWorkspace"); + setProperty("OutputWorkspace", outWS); + } + } + + /** Read in a muon nexus file of the version 2. + * + * @throw Exception::FileError If the Nexus file cannot be found/opened + * @throw std::invalid_argument If the optional properties are set to invalid values + */ + void LoadMuonNexus2::doExec() { // Create the root Nexus class NXRoot root(getPropertyValue("Filename")); @@ -67,45 +103,27 @@ namespace Mantid } // Open the data entry - std::string entryName = root.groups()[iEntry].nxname; - NXEntry entry = root.openEntry(entryName); + m_entry_name = root.groups()[iEntry].nxname; + NXEntry entry = root.openEntry(m_entry_name); + + // Read in the instrument name from the Nexus file + m_instrument_name = entry.getString("instrument/name"); - NXInfo info = entry.getDataSetInfo("definition"); - if (info.stat == NX_ERROR) + // Read the number of periods in this file + if ( entry.containsGroup("run") ) { - info = entry.getDataSetInfo("analysis"); - std::string compareString = "muon"; - if (info.stat == NX_OK && entry.getString("analysis").compare(0,compareString.length(),compareString) == 0) + try { - LoadMuonNexus::exec(); - return; + m_numberOfPeriods = entry.getInt("run/number_periods"); } - else + catch (::NeXus::Exception&) { - g_log.debug()<<"analysis=|" << entry.getString("analysis") << "|" << std::endl; - throw std::runtime_error("Unknown Muon NeXus file format"); + //assume 1 + m_numberOfPeriods = 1; } } else { - std::string definition = entry.getString("definition"); - if (info.stat == NX_ERROR || definition != "pulsedTD") - { - throw std::runtime_error("Unknown Muon Nexus file format"); - } - } - - // Read in the instrument name from the Nexus file - m_instrument_name = entry.getString("instrument/name"); - - // Read the number of periods in this file - try - { - m_numberOfPeriods = entry.getInt("run/number_periods"); - } - catch (::NeXus::Exception&) - { - //assume 1 m_numberOfPeriods = 1; } @@ -179,56 +197,44 @@ namespace Mantid //g_log.error()<<" number of perioids= "<<m_numberOfPeriods<<std::endl; WorkspaceGroup_sptr wsGrpSptr=WorkspaceGroup_sptr(new WorkspaceGroup); - try + if ( entry.containsDataSet( "title" ) ) { wsGrpSptr->setTitle(entry.getString("title")); } - catch (::NeXus::Exception&) - {} - try + + if ( entry.containsDataSet( "notes" ) ) { wsGrpSptr->setComment(entry.getString("notes")); } - catch (::NeXus::Exception&) - {} if(m_numberOfPeriods>1) { setProperty("OutputWorkspace",boost::dynamic_pointer_cast<Workspace>(wsGrpSptr)); } - Mantid::NeXus::NXInt period_index = dataGroup.openNXInt("period_index"); - period_index.load(); + // period_index is currently unused + //Mantid::NeXus::NXInt period_index = dataGroup.openNXInt("period_index"); + //period_index.load(); Mantid::NeXus::NXInt counts = dataGroup.openIntData(); counts.load(); + NXInstrument instr = entry.openNXInstrument("instrument"); - try + if ( instr.containsGroup( "detector_fb" ) ) { - NXEntry entryTimeZero = root.openEntry("run/instrument/detector_fb"); - NXInfo infoTimeZero = entryTimeZero.getDataSetInfo("time_zero"); - if (infoTimeZero.stat != NX_ERROR) + NXDetector detector = instr.openNXDetector("detector_fb"); + if (detector.containsDataSet("time_zero")) { - double dum = root.getFloat("run/instrument/detector_fb/time_zero"); + double dum = detector.getFloat("time_zero"); setProperty("TimeZero", dum); } - } - catch (::NeXus::Exception&) - {} - - try - { - NXEntry entryFGB = root.openEntry("run/instrument/detector_fb"); - NXInfo infoFGB = entryFGB.getDataSetInfo("first_good_time"); - if (infoFGB.stat != NX_ERROR) + if (detector.containsDataSet("first_good_time")) { - double dum = root.getFloat("run/instrument/detector_fb/first_good_time"); + double dum = detector.getFloat("first_good_time"); setProperty("FirstGoodData", dum); } } - catch (::NeXus::Exception&) - {} API::Progress progress(this,0.,1.,m_numberOfPeriods * total_specs); // Loop over the number of periods in the Nexus file, putting each period in a separate workspace @@ -321,10 +327,27 @@ namespace Mantid MantidVec& X = localWorkspace->dataX(wsIndex); MantidVec& Y = localWorkspace->dataY(wsIndex); MantidVec& E = localWorkspace->dataE(wsIndex); - int nBins = counts.dim2(); - assert( nBins+1 == static_cast<int>(timeBins.size()) ); X.assign(timeBins.begin(),timeBins.end()); - int *data = &counts(period,spec,0); + + int nBins = 0; + int *data = NULL; + + if ( counts.rank() == 3 ) + { + nBins = counts.dim2(); + data = &counts(period,spec,0); + } + else if ( counts.rank() == 2 ) + { + nBins = counts.dim1(); + data = &counts(spec,0); + } + else + { + throw std::runtime_error("Data have unsupported dimansionality"); + } + assert( nBins+1 == static_cast<int>(timeBins.size()) ); + Y.assign(data,data+nBins); typedef double (*uf)(double); uf dblSqrt = std::sqrt; @@ -357,7 +380,11 @@ namespace Mantid } ws->setTitle(entry.getString("title")); - ws->setComment(entry.getString("notes")); + + if ( entry.containsDataSet("notes") ) + { + ws->setComment(entry.getString("notes")); + } std::string run_num = boost::lexical_cast<std::string>(entry.getInt("run_number")); //The sample is left to delete the property @@ -366,86 +393,6 @@ namespace Mantid ws->populateInstrumentParameters(); } - /**This method does a quick file type check by looking at the first 100 bytes of the file - * @param filePath- path of the file including name. - * @param nread :: no.of bytes read - * @param header :: The first 100 bytes of the file as a union - * @return true if the given file is of type which can be loaded by this algorithm - */ - bool LoadMuonNexus2::quickFileCheck(const std::string& filePath,size_t nread,const file_header& header) - { - std::string extn=extension(filePath); - bool bnexs(false); - (!extn.compare("nxs")||!extn.compare("nx5"))?bnexs=true:bnexs=false; - /* - * HDF files have magic cookie in the first 4 bytes - */ - if ( ((nread >= sizeof(unsigned)) && (ntohl(header.four_bytes) == g_hdf_cookie)) || bnexs ) - { - //hdf - return true; - } - else if ( (nread >= sizeof(g_hdf5_signature)) && (!memcmp(header.full_hdr, g_hdf5_signature, sizeof(g_hdf5_signature))) ) - { - //hdf5 - return true; - } - return false; - - } - /**checks the file by opening it and reading few lines - * @param filePath :: name of the file inluding its path - * @return an integer value how much this algorithm can load the file - */ - int LoadMuonNexus2::fileCheck(const std::string& filePath) - { - int confidence(0); - std::string analysisType; - try - { - ::NeXus::File file = ::NeXus::File(filePath); - // Will throw if this doesn't exist - file.openPath("/run/analysis"); - analysisType = file.getStrData(); - } - catch(::NeXus::Exception&) - { - try - { - ::NeXus::File file = ::NeXus::File(filePath); - file.openPath("/run/definition"); - analysisType = file.getStrData(); - } - catch(::NeXus::Exception&) - { - //one last try - this is the area for PSI written files - try - { - ::NeXus::File file = ::NeXus::File(filePath); - file.openPath("/raw_data_1/definition"); - analysisType = file.getStrData(); - } - catch(::NeXus::Exception&) - { - //no give up this doesn't look like a muon v2 file - analysisType = ""; - } - } - } - std::string compareString = "muon"; - if( analysisType == "pulsedTD" ) - { - confidence = 85; - } - else if( analysisType.compare(0,compareString.length(),compareString) == 0 ) - { - confidence = 50; - } - else confidence = 0; - - return confidence; - } - /** Log the run details from the file * @param localWorkspace :: The workspace details to use */ @@ -460,28 +407,29 @@ namespace Mantid m_filename = getPropertyValue("Filename"); NXRoot root(m_filename); + NXEntry entry = root.openEntry(m_entry_name); - std::string start_time = root.getString("run/start_time"); + std::string start_time = entry.getString("start_time"); runDetails.addProperty("run_start", start_time); - std::string stop_time = root.getString("run/end_time"); + std::string stop_time = entry.getString("end_time"); runDetails.addProperty("run_end", stop_time); - - NXEntry runRun = root.openEntry("run/run"); - - NXInfo infoGoodTotalFrames = runRun.getDataSetInfo("good_total_frames"); - if (infoGoodTotalFrames.stat != NX_ERROR) + if ( entry.containsGroup( "run" ) ) { - int dum = root.getInt("run/run/good_total_frames"); - runDetails.addProperty("goodfrm", dum); - } + NXClass runRun = entry.openNXGroup("run"); - NXInfo infoNumberPeriods = runRun.getDataSetInfo("number_periods"); - if (infoNumberPeriods.stat != NX_ERROR) - { - int dum = root.getInt("run/run/number_periods"); - runDetails.addProperty("nperiods", dum); + if ( runRun.containsDataSet("good_total_frames") ) + { + int dum = runRun.getInt("good_total_frames"); + runDetails.addProperty("goodfrm", dum); + } + + if ( runRun.containsDataSet("number_periods") ) + { + int dum = runRun.getInt("number_periods"); + runDetails.addProperty("nperiods", dum); + } } { // Duration taken to be stop_time minus stat_time @@ -490,9 +438,37 @@ namespace Mantid double duration_in_secs = DateAndTime::secondsFromDuration( end - start); runDetails.addProperty("dur_secs",duration_in_secs); } + } - - + /**checks the file by opening it and reading few lines + * @param filePath :: name of the file inluding its path + * @return an integer value how much this algorithm can load the file + */ + int LoadMuonNexus2::fileCheck(const std::string& filePath) + { + try + { + NXRoot root(filePath); + NXEntry entry = root.openFirstEntry(); + if ( ! entry.containsDataSet( "definition" ) ) return 0; + std::string versionField = "IDF_version"; + if ( ! entry.containsDataSet( versionField ) ) + { + versionField = "idf_version"; + if ( ! entry.containsDataSet( versionField ) ) return 0; + } + if ( entry.getInt( versionField ) != 2 ) return 0; + std::string definition = entry.getString( "definition" ); + if ( definition == "muonTD" || definition == "pulsedTD" ) + { + // If all this succeeded then we'll assume this is an ISIS Muon NeXus file version 2 + return 81; + } + } + catch( ... ) + { + } + return 0; } } // namespace DataHandling diff --git a/Code/Mantid/Framework/DataHandling/test/GroupDetectors2Test.h b/Code/Mantid/Framework/DataHandling/test/GroupDetectors2Test.h index c6f55455d95743f732b68a04b965ba18659900db..70bf0c22b77b93645e45fbd8ded1816065b954c9 100644 --- a/Code/Mantid/Framework/DataHandling/test/GroupDetectors2Test.h +++ b/Code/Mantid/Framework/DataHandling/test/GroupDetectors2Test.h @@ -12,7 +12,7 @@ #include "MantidKernel/ArrayProperty.h" #include "MantidKernel/Exception.h" #include "MantidKernel/UnitFactory.h" -#include "MantidDataHandling/LoadMuonNexus2.h" +#include "MantidDataHandling/LoadMuonNexus1.h" #include "MantidTestHelpers/WorkspaceCreationHelper.h" #include <cxxtest/TestSuite.h> #include <fstream> @@ -351,7 +351,7 @@ public: void testReadingFromXML() { - Mantid::DataHandling::LoadMuonNexus2 nxLoad; + Mantid::DataHandling::LoadMuonNexus1 nxLoad; nxLoad.initialize(); // Now set required filename and output workspace name @@ -391,7 +391,7 @@ public: void testReadingFromXMLCheckDublicateIndex() { - Mantid::DataHandling::LoadMuonNexus2 nxLoad; + Mantid::DataHandling::LoadMuonNexus1 nxLoad; nxLoad.initialize(); // Now set required filename and output workspace name @@ -431,7 +431,7 @@ public: void testReadingFromXMLCheckDublicateIndex2() { - Mantid::DataHandling::LoadMuonNexus2 nxLoad; + Mantid::DataHandling::LoadMuonNexus1 nxLoad; nxLoad.initialize(); // Now set required filename and output workspace name diff --git a/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus1Test.h b/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus1Test.h new file mode 100644 index 0000000000000000000000000000000000000000..0e533d3d8cd9b76a4113c067ddd1fbcb5fddadbd --- /dev/null +++ b/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus1Test.h @@ -0,0 +1,415 @@ +#ifndef LOADMUONNEXUS1TEST_H_ +#define LOADMUONNEXUS1TEST_H_ + + + +// These includes seem to make the difference between initialization of the +// workspace names (workspace2D/1D etc), instrument classes and not for this test case. +#include "MantidDataObjects/WorkspaceSingleValue.h" +#include "MantidDataHandling/LoadInstrument.h" +// + +#include <fstream> +#include <cxxtest/TestSuite.h> + +#include "MantidDataHandling/LoadMuonNexus1.h" +#include "MantidAPI/WorkspaceFactory.h" +#include "MantidDataObjects/ManagedWorkspace2D.h" +#include "MantidAPI/AnalysisDataService.h" +#include "MantidAPI/FrameworkManager.h" +#include "MantidKernel/ConfigService.h" +#include "MantidKernel/TimeSeriesProperty.h" +#include "MantidAPI/SpectraDetectorMap.h" +#include <Poco/Path.h> + +using namespace Mantid::API; +using namespace Mantid::Kernel; +using namespace Mantid::DataHandling; +using namespace Mantid::DataObjects; + +class LoadMuonNexus1Test : public CxxTest::TestSuite +{ +public: + + + void testInit() + { + TS_ASSERT_THROWS_NOTHING(nxLoad.initialize()); + TS_ASSERT( nxLoad.isInitialized() ); + } + + + void testExec() + { + if ( !nxLoad.isInitialized() ) nxLoad.initialize(); + // Should fail because mandatory parameter has not been set + TS_ASSERT_THROWS(nxLoad.execute(),std::runtime_error); + + // Now set required filename and output workspace name + inputFile = "emu00006473.nxs"; + nxLoad.setPropertyValue("FileName", inputFile); + + outputSpace="outer"; + nxLoad.setPropertyValue("OutputWorkspace", outputSpace); + + // + // Test execute to read file and populate workspace + // + TS_ASSERT_THROWS_NOTHING(nxLoad.execute()); + TS_ASSERT( nxLoad.isExecuted() ); + + // Test additional output parameters + std::string field = nxLoad.getProperty("MainFieldDirection"); + TS_ASSERT( field == "Longitudinal" ); + + // + // Test workspace data (copied from LoadRawTest.h) + // + MatrixWorkspace_sptr output; + output = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace); + Workspace2D_sptr output2D = boost::dynamic_pointer_cast<Workspace2D>(output); + // Should be 32 for file inputFile = "../../../../Test/Nexus/emu00006473.nxs"; + TS_ASSERT_EQUALS( output2D->getNumberHistograms(), 32); + // Check two X vectors are the same + TS_ASSERT( (output2D->dataX(3)) == (output2D->dataX(31)) ); + // Check two Y arrays have the same number of elements + TS_ASSERT_EQUALS( output2D->dataY(5).size(), output2D->dataY(17).size() ); + // Check one particular value + TS_ASSERT_EQUALS( output2D->dataY(11)[686], 81); + // Check that the error on that value is correct + TS_ASSERT_EQUALS( output2D->dataE(11)[686], 9); + // Check that the time is as expected from bin boundary update + TS_ASSERT_DELTA( output2D->dataX(11)[687], 10.738,0.001); + + // Check the unit has been set correctly + TS_ASSERT_EQUALS( output->getAxis(0)->unit()->unitID(), "Label" ); + TS_ASSERT( ! output-> isDistribution() ); + + /* - other tests from LoadRawTest - These test data not in current Nexus files + //---------------------------------------------------------------------- + // Tests taken from LoadInstrumentTest to check Child Algorithm is running properly + //---------------------------------------------------------------------- + boost::shared_ptr<Instrument> i = output->getInstrument(); + Mantid::Geometry::Component* source = i->getSource(); + + TS_ASSERT_EQUALS( source->getName(), "undulator"); + TS_ASSERT_DELTA( source->getPos().Y(), 0.0,0.01); + + Mantid::Geometry::Component* samplepos = i->getSample(); + TS_ASSERT_EQUALS( samplepos->getName(), "nickel-holder"); + TS_ASSERT_DELTA( samplepos->getPos().Y(), 10.0,0.01); + + Mantid::Geometry::Detector *ptrDet103 = dynamic_cast<Mantid::Geometry::Detector*>(i->getDetector(103)); + TS_ASSERT_EQUALS( ptrDet103->getID(), 103); + TS_ASSERT_EQUALS( ptrDet103->getName(), "pixel"); + TS_ASSERT_DELTA( ptrDet103->getPos().X(), 0.4013,0.01); + TS_ASSERT_DELTA( ptrDet103->getPos().Z(), 2.4470,0.01); + */ + //---------------------------------------------------------------------- + // Test code copied from LoadLogTest to check Child Algorithm is running properly + //---------------------------------------------------------------------- + //boost::shared_ptr<Sample> sample = output->getSample(); + Property *l_property = output->run().getLogData( std::string("beamlog_current") ); + TimeSeriesProperty<double> *l_timeSeriesDouble = dynamic_cast<TimeSeriesProperty<double>*>(l_property); + std::string timeSeriesString = l_timeSeriesDouble->value(); + TS_ASSERT_EQUALS( timeSeriesString.substr(0,27), "2006-Nov-21 07:03:08 182.8" ); + //check that sample name has been set correctly + TS_ASSERT_EQUALS(output->sample().getName(), "Cr2.7Co0.3Si"); + + /* + //---------------------------------------------------------------------- + // Tests to check that Loading SpectraDetectorMap is done correctly + //---------------------------------------------------------------------- + map= output->getSpectraMap(); + + // Check the total number of elements in the map for HET + TS_ASSERT_EQUALS(map->nElements(),24964); + + // Test one to one mapping, for example spectra 6 has only 1 pixel + TS_ASSERT_EQUALS(map->ndet(6),1); + + // Test one to many mapping, for example 10 pixels contribute to spectra 2084 + TS_ASSERT_EQUALS(map->ndet(2084),10); + // Check the id number of all pixels contributing + std::vector<Mantid::Geometry::IDetector*> detectorgroup; + detectorgroup=map->getDetectors(2084); + std::vector<Mantid::Geometry::IDetector*>::iterator it; + int pixnum=101191; + for (it=detectorgroup.begin();it!=detectorgroup.end();it++) + TS_ASSERT_EQUALS((*it)->getID(),pixnum++); + + // Test with spectra that does not exist + // Test that number of pixel=0 + TS_ASSERT_EQUALS(map->ndet(5),0); + // Test that trying to get the Detector throws. + boost::shared_ptr<Mantid::Geometry::IDetector> test; + TS_ASSERT_THROWS(test=map->getDetector(5),std::runtime_error); + */ + + } +// void testWithManagedWorkspace() +// { +// ConfigService::Instance().updateConfig("UseManagedWS.properties"); +// //LoadRaw loader4; +// //loader4.initialize(); +// //loader4.setPropertyValue("Filename", inputFile); +// //loader4.setPropertyValue("OutputWorkspace", "managedws"); +// // TS_ASSERT_THROWS_NOTHING( loader4.execute() ) +// //TS_ASSERT( loader4.isExecuted() ) +// +// // Get back workspace and check it really is a ManagedWorkspace2D +// MatrixWorkspace_sptr output; +// TS_ASSERT_THROWS_NOTHING( output = AnalysisDataService::Instance().retrieve("managedws") ); +// TS_ASSERT( dynamic_cast<ManagedWorkspace2D*>(output.get()) ) +// } + + + + void testTransvereDataset() + { + LoadMuonNexus1 nxL; + if ( !nxL.isInitialized() ) nxL.initialize(); + + // Now set required filename and output workspace name + std::string inputFile_musr00022725 = "MUSR00022725.nxs"; + nxL.setPropertyValue("FileName", inputFile_musr00022725); + + outputSpace="outermusr00022725"; + nxL.setPropertyValue("OutputWorkspace", outputSpace); + + TS_ASSERT_THROWS_NOTHING(nxL.execute()); + TS_ASSERT( nxL.isExecuted() ); + + // Test additional output parameters + std::string field = nxL.getProperty("MainFieldDirection"); + TS_ASSERT( field == "Transverse" ); + double timeZero = nxL.getProperty("TimeZero"); + TS_ASSERT_DELTA( timeZero, 0.55,0.001); + double firstgood = nxL.getProperty("FirstGoodData"); + TS_ASSERT_DELTA( firstgood, 0.656,0.001); + std::vector<double> deadTimes = nxL.getProperty("DeadTimes"); + TS_ASSERT_DELTA( deadTimes[0], 0.006,0.001); + TS_ASSERT_DELTA( deadTimes[deadTimes.size()-1], 0.011,0.001); + } + + void testExec2() + { + //test for multi period + // Now set required filename and output workspace name + inputFile2 = "emu00006475.nxs"; + nxLoad.setPropertyValue("FileName", inputFile2); + + outputSpace="outer2"; + nxLoad.setPropertyValue("OutputWorkspace", outputSpace); + nxLoad.setPropertyValue("EntryNumber", "1"); + int64_t entryNumber=nxLoad.getProperty("EntryNumber"); + + // + // Test execute to read file and populate workspace + // + TS_ASSERT_THROWS_NOTHING(nxLoad.execute()); + TS_ASSERT( nxLoad.isExecuted() ); + // + // Test workspace data - should be 4 separate workspaces for this 4 period file + // + if(entryNumber==0) + { + WorkspaceGroup_sptr outGrp; + TS_ASSERT_THROWS_NOTHING(outGrp = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(outputSpace)); + + } + //if entry number is given + if(entryNumber==1) + { + MatrixWorkspace_sptr output; + output = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace); + + Workspace2D_sptr output2D = boost::dynamic_pointer_cast<Workspace2D>(output); + //Workspace2D_sptr output2D2 = boost::dynamic_pointer_cast<Workspace2D>(output2); + // Should be 32 for file inputFile = "../../../../Test/Nexus/emu00006475.nxs"; + TS_ASSERT_EQUALS( output2D->getNumberHistograms(), 32); + // Check two X vectors are the same + TS_ASSERT( (output2D->dataX(3)) == (output2D->dataX(31)) ); + // Check two Y arrays have the same number of elements + TS_ASSERT_EQUALS( output2D->dataY(5).size(), output2D->dataY(17).size() ); + // Check that the time is as expected from bin boundary update + TS_ASSERT_DELTA( output2D->dataX(11)[687], 10.738,0.001); + + // Check the unit has been set correctly + TS_ASSERT_EQUALS( output->getAxis(0)->unit()->unitID(), "Label" ); + TS_ASSERT( ! output-> isDistribution() ); + + //check that sample name has been set correctly + //boost::shared_ptr<Sample> sample,sample2; + //sample = output->getSample(); + //sample2 = output2->getSample(); + //TS_ASSERT_EQUALS(sample->getName(), sample2->getName()); + TS_ASSERT_EQUALS(output->sample().getName(), "ptfe test"); + + } + MatrixWorkspace_sptr output,output2,output3,output4; + WorkspaceGroup_sptr outGrp; + //if no entry number load the group workspace + if(entryNumber==0) + { + TS_ASSERT_THROWS_NOTHING(outGrp = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(outputSpace)); + + (output = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace+"_1")); + (output2 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace+"_2")); + (output3 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace+"_3")); + (output4 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace+"_4")); + + Workspace2D_sptr output2D = boost::dynamic_pointer_cast<Workspace2D>(output); + Workspace2D_sptr output2D2 = boost::dynamic_pointer_cast<Workspace2D>(output2); + // Should be 32 for file inputFile = "../../../../Test/Nexus/emu00006475.nxs"; + TS_ASSERT_EQUALS( output2D->getNumberHistograms(), 32); + // Check two X vectors are the same + TS_ASSERT( (output2D->dataX(3)) == (output2D->dataX(31)) ); + // Check two Y arrays have the same number of elements + TS_ASSERT_EQUALS( output2D->dataY(5).size(), output2D->dataY(17).size() ); + // Check one particular value + TS_ASSERT_EQUALS( output2D2->dataY(8)[502], 121); + // Check that the error on that value is correct + TS_ASSERT_EQUALS( output2D2->dataE(8)[502], 11); + // Check that the time is as expected from bin boundary update + TS_ASSERT_DELTA( output2D->dataX(11)[687], 10.738,0.001); + + // Check the unit has been set correctly + TS_ASSERT_EQUALS( output->getAxis(0)->unit()->unitID(), "Label" ); + TS_ASSERT( ! output-> isDistribution() ); + + //check that sample name has been set correctly + // boost::shared_ptr<Sample> sample,sample2; + //sample = output->getSample(); + // sample2 = output2->getSample(); + TS_ASSERT_EQUALS(output->sample().getName(), output2->sample().getName()); + TS_ASSERT_EQUALS(output->sample().getName(), "ptfe test"); + + } + } + void testExec2withZeroEntryNumber() + { + //test for multi period + // Now set required filename and output workspace name + inputFile2 = "emu00006475.nxs"; + nxLoad.setPropertyValue("FileName", inputFile2); + + outputSpace="outer2"; + nxLoad.setPropertyValue("OutputWorkspace", outputSpace); + nxLoad.setPropertyValue("EntryNumber", "0"); + int64_t entryNumber=nxLoad.getProperty("EntryNumber"); + + // + // Test execute to read file and populate workspace + // + TS_ASSERT_THROWS_NOTHING(nxLoad.execute()); + TS_ASSERT( nxLoad.isExecuted() ); + // + // Test workspace data - should be 4 separate workspaces for this 4 period file + // + WorkspaceGroup_sptr outGrp; + TS_ASSERT_THROWS_NOTHING(outGrp = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(outputSpace)); + + MatrixWorkspace_sptr output,output2,output3,output4; + //WorkspaceGroup_sptr outGrp; + //if no entry number load the group workspace + if(entryNumber==0) + { + //TS_ASSERT_THROWS_NOTHING(outGrp = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(outputSpace)); + + (output = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace+"_1")); + (output2 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace+"_2")); + (output3 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace+"_3")); + (output4 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace+"_4")); + + Workspace2D_sptr output2D = boost::dynamic_pointer_cast<Workspace2D>(output); + Workspace2D_sptr output2D2 = boost::dynamic_pointer_cast<Workspace2D>(output2); + // Should be 32 for file inputFile = "../../../../Test/Nexus/emu00006475.nxs"; + TS_ASSERT_EQUALS( output2D->getNumberHistograms(), 32); + // Check two X vectors are the same + TS_ASSERT( (output2D->dataX(3)) == (output2D->dataX(31)) ); + // Check two Y arrays have the same number of elements + TS_ASSERT_EQUALS( output2D->dataY(5).size(), output2D->dataY(17).size() ); + // Check one particular value + TS_ASSERT_EQUALS( output2D2->dataY(8)[502], 121); + // Check that the error on that value is correct + TS_ASSERT_EQUALS( output2D2->dataE(8)[502], 11); + // Check that the time is as expected from bin boundary update + TS_ASSERT_DELTA( output2D->dataX(11)[687], 10.738,0.001); + + // Check the unit has been set correctly + TS_ASSERT_EQUALS( output->getAxis(0)->unit()->unitID(), "Label" ); + TS_ASSERT( ! output-> isDistribution() ); + + //check that sample name has been set correctly + //boost::shared_ptr<Sample> sample,sample2; + // sample = output->getSample(); + // sample2 = output2->getSample(); + TS_ASSERT_EQUALS(output->sample().getName(), output2->sample().getName()); + TS_ASSERT_EQUALS(output->sample().getName(), "ptfe test"); + + } + } + + void testarrayin() + { + if ( !nxload3.isInitialized() ) nxload3.initialize(); + + nxload3.setPropertyValue("Filename", inputFile); + nxload3.setPropertyValue("OutputWorkspace", "outWS"); + nxload3.setPropertyValue("SpectrumList", "29,30,31"); + nxload3.setPropertyValue("SpectrumMin", "5"); + nxload3.setPropertyValue("SpectrumMax", "10"); + + TS_ASSERT_THROWS_NOTHING(nxload3.execute()); + TS_ASSERT( nxload3.isExecuted() ); + + // Get back the saved workspace + MatrixWorkspace_sptr output; + (output = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>("outWS")); + Workspace2D_sptr output2D = boost::dynamic_pointer_cast<Workspace2D>(output); + + // Should be 6 for selected input + TS_ASSERT_EQUALS( output2D->getNumberHistograms(), 9); + + // Check two X vectors are the same + TS_ASSERT( (output2D->dataX(1)) == (output2D->dataX(5)) ); + + // Check two Y arrays have the same number of elements + TS_ASSERT_EQUALS( output2D->dataY(2).size(), output2D->dataY(7).size() ); + + // Check one particular value + TS_ASSERT_EQUALS( output2D->dataY(8)[479], 144); + // Check that the error on that value is correct + TS_ASSERT_EQUALS( output2D->dataE(8)[479], 12); + // Check that the error on that value is correct + TS_ASSERT_DELTA( output2D->dataX(8)[479], 7.410, 0.0001); + } + +private: + LoadMuonNexus1 nxLoad,nxload2,nxload3; + std::string outputSpace; + std::string entryName; + std::string inputFile; + std::string inputFile2; + boost::shared_ptr<SpectraDetectorMap> map; +}; + +////------------------------------------------------------------------------------ +//// Performance test +////------------------------------------------------------------------------------ +// +//class LoadMuonNexus1TestPerformance : public CxxTest::TestSuite +//{ +//public: +// void testDefaultLoad() +// { +// LoadMuonNexus1 loader; +// loader.initialize(); +// loader.setPropertyValue("Filename", "deltat_tdc_gpd_0900.nxs"); +// loader.setPropertyValue("OutputWorkspace", "ws"); +// TS_ASSERT( loader.execute() ); +// } +//}; +// +#endif /*LOADMUONNEXUS1TEST_H_*/ diff --git a/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus2Test.h b/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus2Test.h index a3bb3d0084597ba16f00e2a67c22c00b07176c82..17909c0d7de9b5126f9ca6bd55beda736bcde180 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus2Test.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus2Test.h @@ -358,7 +358,7 @@ public: check_spectra_and_detectors(output); - AnalysisDataService::Instance().remove(outputSpace); + AnalysisDataService::Instance().clear(); } void testExec2() @@ -443,9 +443,69 @@ public: check_spectra_and_detectors(output); - AnalysisDataService::Instance().remove(outputSpace); + AnalysisDataService::Instance().clear(); } + void test_gpd_file() + { + LoadMuonNexus2 nxLoad; + nxLoad.initialize(); + + // Now set required filename and output workspace name + std::string inputFile = "deltat_tdc_gpd_0900.nxs"; + nxLoad.setPropertyValue("FileName", inputFile); + + std::string outputSpace="outer"; + nxLoad.setPropertyValue("OutputWorkspace", outputSpace); + + // + // Test execute to read file and populate workspace + // + TS_ASSERT_THROWS_NOTHING(nxLoad.execute()); + TS_ASSERT( nxLoad.isExecuted() ); + + // + // Test additional output parameters + // + std::string field = nxLoad.getProperty("MainFieldDirection"); + TS_ASSERT( field == "Transverse" ); + // TimeZero and FirstGoodData are not read yet so they are 0 + double timeZero = nxLoad.getProperty("TimeZero"); + TS_ASSERT_DELTA( timeZero, 0.0,0.001); + double firstgood = nxLoad.getProperty("FirstGoodData"); + TS_ASSERT_DELTA( firstgood, 0.0,0.001); + + // + // Test workspace data + // + MatrixWorkspace_sptr output; + output = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace); + Workspace2D_sptr output2D = boost::dynamic_pointer_cast<Workspace2D>(output); + // Should be 192 for file inputFile = "argus0026287.nxs"; + TS_ASSERT_EQUALS( output2D->getNumberHistograms(), 2); + TS_ASSERT_EQUALS( output2D->blocksize(), 8192); + // Check two X vectors are the same + TS_ASSERT( (output2D->dataX(0)) == (output2D->dataX(1)) ); + // Check two Y arrays have the same number of elements + TS_ASSERT_EQUALS( output2D->dataY(0).size(), output2D->dataY(1).size() ); + // Check one particular value + TS_ASSERT_EQUALS( output2D->dataY(0)[686], 516); + TS_ASSERT_EQUALS( output2D->dataY(0)[687], 413); + TS_ASSERT_EQUALS( output2D->dataY(1)[686], 381); + + // Check that the error on that value is correct + TS_ASSERT_DELTA( output2D->dataE(0)[686], 22.7156,0.001); + TS_ASSERT_DELTA( output2D->dataE(0)[687], 20.3224,0.001); + TS_ASSERT_DELTA( output2D->dataE(1)[686], 19.5192,0.001); + // Check that the time is as expected from bin boundary update + TS_ASSERT_DELTA( output2D->dataX(1)[687], 0.8050,0.001); + + // Check the unit has been set correctly + TS_ASSERT_EQUALS( output->getAxis(0)->unit()->unitID(), "Label" ); + TS_ASSERT( ! output-> isDistribution() ); + + AnalysisDataService::Instance().remove(outputSpace); + } }; //------------------------------------------------------------------------------ diff --git a/Code/Mantid/Framework/DataHandling/test/LoadMuonNexusTest.h b/Code/Mantid/Framework/DataHandling/test/LoadMuonNexusTest.h index 6c62b27823a2d5adbffce7ba14c51d9e179da6e1..3bbae100287517f2ef0ddd3138bdad66c198d713 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadMuonNexusTest.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadMuonNexusTest.h @@ -1,397 +1,20 @@ #ifndef LOADMUONNEXUSTEST_H_ #define LOADMUONNEXUSTEST_H_ - - -// These includes seem to make the difference between initialization of the -// workspace names (workspace2D/1D etc), instrument classes and not for this test case. -#include "MantidDataObjects/WorkspaceSingleValue.h" -#include "MantidDataHandling/LoadInstrument.h" -// - -#include <fstream> #include <cxxtest/TestSuite.h> -#include "MantidDataHandling/LoadMuonNexus.h" -#include "MantidAPI/WorkspaceFactory.h" -#include "MantidDataObjects/ManagedWorkspace2D.h" -#include "MantidAPI/AnalysisDataService.h" -#include "MantidAPI/FrameworkManager.h" -#include "MantidKernel/ConfigService.h" -#include "MantidKernel/TimeSeriesProperty.h" -#include "MantidAPI/SpectraDetectorMap.h" -#include <Poco/Path.h> +#include "MantidDataHandling/LoadMuonNexus3.h" -using namespace Mantid::API; -using namespace Mantid::Kernel; using namespace Mantid::DataHandling; -using namespace Mantid::DataObjects; class LoadMuonNexusTest : public CxxTest::TestSuite { public: - - void testInit() - { - TS_ASSERT_THROWS_NOTHING(nxLoad.initialize()); - TS_ASSERT( nxLoad.isInitialized() ); - } - - void testExec() { - if ( !nxLoad.isInitialized() ) nxLoad.initialize(); - // Should fail because mandatory parameter has not been set - TS_ASSERT_THROWS(nxLoad.execute(),std::runtime_error); - - // Now set required filename and output workspace name - inputFile = "emu00006473.nxs"; - nxLoad.setPropertyValue("FileName", inputFile); - - outputSpace="outer"; - nxLoad.setPropertyValue("OutputWorkspace", outputSpace); - - // - // Test execute to read file and populate workspace - // - TS_ASSERT_THROWS_NOTHING(nxLoad.execute()); - TS_ASSERT( nxLoad.isExecuted() ); - - // Test additional output parameters - std::string field = nxLoad.getProperty("MainFieldDirection"); - TS_ASSERT( field == "Longitudinal" ); - - // - // Test workspace data (copied from LoadRawTest.h) - // - MatrixWorkspace_sptr output; - output = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace); - Workspace2D_sptr output2D = boost::dynamic_pointer_cast<Workspace2D>(output); - // Should be 32 for file inputFile = "../../../../Test/Nexus/emu00006473.nxs"; - TS_ASSERT_EQUALS( output2D->getNumberHistograms(), 32); - // Check two X vectors are the same - TS_ASSERT( (output2D->dataX(3)) == (output2D->dataX(31)) ); - // Check two Y arrays have the same number of elements - TS_ASSERT_EQUALS( output2D->dataY(5).size(), output2D->dataY(17).size() ); - // Check one particular value - TS_ASSERT_EQUALS( output2D->dataY(11)[686], 81); - // Check that the error on that value is correct - TS_ASSERT_EQUALS( output2D->dataE(11)[686], 9); - // Check that the time is as expected from bin boundary update - TS_ASSERT_DELTA( output2D->dataX(11)[687], 10.738,0.001); - - // Check the unit has been set correctly - TS_ASSERT_EQUALS( output->getAxis(0)->unit()->unitID(), "Label" ); - TS_ASSERT( ! output-> isDistribution() ); - - /* - other tests from LoadRawTest - These test data not in current Nexus files - //---------------------------------------------------------------------- - // Tests taken from LoadInstrumentTest to check Child Algorithm is running properly - //---------------------------------------------------------------------- - boost::shared_ptr<Instrument> i = output->getInstrument(); - Mantid::Geometry::Component* source = i->getSource(); - - TS_ASSERT_EQUALS( source->getName(), "undulator"); - TS_ASSERT_DELTA( source->getPos().Y(), 0.0,0.01); - - Mantid::Geometry::Component* samplepos = i->getSample(); - TS_ASSERT_EQUALS( samplepos->getName(), "nickel-holder"); - TS_ASSERT_DELTA( samplepos->getPos().Y(), 10.0,0.01); - - Mantid::Geometry::Detector *ptrDet103 = dynamic_cast<Mantid::Geometry::Detector*>(i->getDetector(103)); - TS_ASSERT_EQUALS( ptrDet103->getID(), 103); - TS_ASSERT_EQUALS( ptrDet103->getName(), "pixel"); - TS_ASSERT_DELTA( ptrDet103->getPos().X(), 0.4013,0.01); - TS_ASSERT_DELTA( ptrDet103->getPos().Z(), 2.4470,0.01); - */ - //---------------------------------------------------------------------- - // Test code copied from LoadLogTest to check Child Algorithm is running properly - //---------------------------------------------------------------------- - //boost::shared_ptr<Sample> sample = output->getSample(); - Property *l_property = output->run().getLogData( std::string("beamlog_current") ); - TimeSeriesProperty<double> *l_timeSeriesDouble = dynamic_cast<TimeSeriesProperty<double>*>(l_property); - std::string timeSeriesString = l_timeSeriesDouble->value(); - TS_ASSERT_EQUALS( timeSeriesString.substr(0,27), "2006-Nov-21 07:03:08 182.8" ); - //check that sample name has been set correctly - TS_ASSERT_EQUALS(output->sample().getName(), "Cr2.7Co0.3Si"); - - /* - //---------------------------------------------------------------------- - // Tests to check that Loading SpectraDetectorMap is done correctly - //---------------------------------------------------------------------- - map= output->getSpectraMap(); - - // Check the total number of elements in the map for HET - TS_ASSERT_EQUALS(map->nElements(),24964); - - // Test one to one mapping, for example spectra 6 has only 1 pixel - TS_ASSERT_EQUALS(map->ndet(6),1); - - // Test one to many mapping, for example 10 pixels contribute to spectra 2084 - TS_ASSERT_EQUALS(map->ndet(2084),10); - // Check the id number of all pixels contributing - std::vector<Mantid::Geometry::IDetector*> detectorgroup; - detectorgroup=map->getDetectors(2084); - std::vector<Mantid::Geometry::IDetector*>::iterator it; - int pixnum=101191; - for (it=detectorgroup.begin();it!=detectorgroup.end();it++) - TS_ASSERT_EQUALS((*it)->getID(),pixnum++); - - // Test with spectra that does not exist - // Test that number of pixel=0 - TS_ASSERT_EQUALS(map->ndet(5),0); - // Test that trying to get the Detector throws. - boost::shared_ptr<Mantid::Geometry::IDetector> test; - TS_ASSERT_THROWS(test=map->getDetector(5),std::runtime_error); - */ - } -// void testWithManagedWorkspace() -// { -// ConfigService::Instance().updateConfig("UseManagedWS.properties"); -// //LoadRaw loader4; -// //loader4.initialize(); -// //loader4.setPropertyValue("Filename", inputFile); -// //loader4.setPropertyValue("OutputWorkspace", "managedws"); -// // TS_ASSERT_THROWS_NOTHING( loader4.execute() ) -// //TS_ASSERT( loader4.isExecuted() ) -// -// // Get back workspace and check it really is a ManagedWorkspace2D -// MatrixWorkspace_sptr output; -// TS_ASSERT_THROWS_NOTHING( output = AnalysisDataService::Instance().retrieve("managedws") ); -// TS_ASSERT( dynamic_cast<ManagedWorkspace2D*>(output.get()) ) -// } - - - void testTransvereDataset() - { - LoadMuonNexus nxL; - if ( !nxL.isInitialized() ) nxL.initialize(); - - // Now set required filename and output workspace name - std::string inputFile_musr00022725 = "MUSR00022725.nxs"; - nxL.setPropertyValue("FileName", inputFile_musr00022725); - - outputSpace="outermusr00022725"; - nxL.setPropertyValue("OutputWorkspace", outputSpace); - - TS_ASSERT_THROWS_NOTHING(nxL.execute()); - TS_ASSERT( nxL.isExecuted() ); - - // Test additional output parameters - std::string field = nxL.getProperty("MainFieldDirection"); - TS_ASSERT( field == "Transverse" ); - double timeZero = nxL.getProperty("TimeZero"); - TS_ASSERT_DELTA( timeZero, 0.55,0.001); - double firstgood = nxL.getProperty("FirstGoodData"); - TS_ASSERT_DELTA( firstgood, 0.656,0.001); - std::vector<double> deadTimes = nxL.getProperty("DeadTimes"); - TS_ASSERT_DELTA( deadTimes[0], 0.006,0.001); - TS_ASSERT_DELTA( deadTimes[deadTimes.size()-1], 0.011,0.001); - } - - void testExec2() - { - //test for multi period - // Now set required filename and output workspace name - inputFile2 = "emu00006475.nxs"; - nxLoad.setPropertyValue("FileName", inputFile2); - - outputSpace="outer2"; - nxLoad.setPropertyValue("OutputWorkspace", outputSpace); - nxLoad.setPropertyValue("EntryNumber", "1"); - int64_t entryNumber=nxLoad.getProperty("EntryNumber"); - - // - // Test execute to read file and populate workspace - // - TS_ASSERT_THROWS_NOTHING(nxLoad.execute()); - TS_ASSERT( nxLoad.isExecuted() ); - // - // Test workspace data - should be 4 separate workspaces for this 4 period file - // - if(entryNumber==0) - { - WorkspaceGroup_sptr outGrp; - TS_ASSERT_THROWS_NOTHING(outGrp = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(outputSpace)); - - } - //if entry number is given - if(entryNumber==1) - { - MatrixWorkspace_sptr output; - output = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace); - - Workspace2D_sptr output2D = boost::dynamic_pointer_cast<Workspace2D>(output); - //Workspace2D_sptr output2D2 = boost::dynamic_pointer_cast<Workspace2D>(output2); - // Should be 32 for file inputFile = "../../../../Test/Nexus/emu00006475.nxs"; - TS_ASSERT_EQUALS( output2D->getNumberHistograms(), 32); - // Check two X vectors are the same - TS_ASSERT( (output2D->dataX(3)) == (output2D->dataX(31)) ); - // Check two Y arrays have the same number of elements - TS_ASSERT_EQUALS( output2D->dataY(5).size(), output2D->dataY(17).size() ); - // Check that the time is as expected from bin boundary update - TS_ASSERT_DELTA( output2D->dataX(11)[687], 10.738,0.001); - - // Check the unit has been set correctly - TS_ASSERT_EQUALS( output->getAxis(0)->unit()->unitID(), "Label" ); - TS_ASSERT( ! output-> isDistribution() ); - - //check that sample name has been set correctly - //boost::shared_ptr<Sample> sample,sample2; - //sample = output->getSample(); - //sample2 = output2->getSample(); - //TS_ASSERT_EQUALS(sample->getName(), sample2->getName()); - TS_ASSERT_EQUALS(output->sample().getName(), "ptfe test"); - - } - MatrixWorkspace_sptr output,output2,output3,output4; - WorkspaceGroup_sptr outGrp; - //if no entry number load the group workspace - if(entryNumber==0) - { - TS_ASSERT_THROWS_NOTHING(outGrp = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(outputSpace)); - - (output = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace+"_1")); - (output2 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace+"_2")); - (output3 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace+"_3")); - (output4 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace+"_4")); - - Workspace2D_sptr output2D = boost::dynamic_pointer_cast<Workspace2D>(output); - Workspace2D_sptr output2D2 = boost::dynamic_pointer_cast<Workspace2D>(output2); - // Should be 32 for file inputFile = "../../../../Test/Nexus/emu00006475.nxs"; - TS_ASSERT_EQUALS( output2D->getNumberHistograms(), 32); - // Check two X vectors are the same - TS_ASSERT( (output2D->dataX(3)) == (output2D->dataX(31)) ); - // Check two Y arrays have the same number of elements - TS_ASSERT_EQUALS( output2D->dataY(5).size(), output2D->dataY(17).size() ); - // Check one particular value - TS_ASSERT_EQUALS( output2D2->dataY(8)[502], 121); - // Check that the error on that value is correct - TS_ASSERT_EQUALS( output2D2->dataE(8)[502], 11); - // Check that the time is as expected from bin boundary update - TS_ASSERT_DELTA( output2D->dataX(11)[687], 10.738,0.001); - - // Check the unit has been set correctly - TS_ASSERT_EQUALS( output->getAxis(0)->unit()->unitID(), "Label" ); - TS_ASSERT( ! output-> isDistribution() ); - - //check that sample name has been set correctly - // boost::shared_ptr<Sample> sample,sample2; - //sample = output->getSample(); - // sample2 = output2->getSample(); - TS_ASSERT_EQUALS(output->sample().getName(), output2->sample().getName()); - TS_ASSERT_EQUALS(output->sample().getName(), "ptfe test"); - - } - } - void testExec2withZeroEntryNumber() - { - //test for multi period - // Now set required filename and output workspace name - inputFile2 = "emu00006475.nxs"; - nxLoad.setPropertyValue("FileName", inputFile2); - - outputSpace="outer2"; - nxLoad.setPropertyValue("OutputWorkspace", outputSpace); - nxLoad.setPropertyValue("EntryNumber", "0"); - int64_t entryNumber=nxLoad.getProperty("EntryNumber"); - - // - // Test execute to read file and populate workspace - // - TS_ASSERT_THROWS_NOTHING(nxLoad.execute()); - TS_ASSERT( nxLoad.isExecuted() ); - // - // Test workspace data - should be 4 separate workspaces for this 4 period file - // - WorkspaceGroup_sptr outGrp; - TS_ASSERT_THROWS_NOTHING(outGrp = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(outputSpace)); - - MatrixWorkspace_sptr output,output2,output3,output4; - //WorkspaceGroup_sptr outGrp; - //if no entry number load the group workspace - if(entryNumber==0) - { - //TS_ASSERT_THROWS_NOTHING(outGrp = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(outputSpace)); - - (output = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace+"_1")); - (output2 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace+"_2")); - (output3 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace+"_3")); - (output4 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace+"_4")); - - Workspace2D_sptr output2D = boost::dynamic_pointer_cast<Workspace2D>(output); - Workspace2D_sptr output2D2 = boost::dynamic_pointer_cast<Workspace2D>(output2); - // Should be 32 for file inputFile = "../../../../Test/Nexus/emu00006475.nxs"; - TS_ASSERT_EQUALS( output2D->getNumberHistograms(), 32); - // Check two X vectors are the same - TS_ASSERT( (output2D->dataX(3)) == (output2D->dataX(31)) ); - // Check two Y arrays have the same number of elements - TS_ASSERT_EQUALS( output2D->dataY(5).size(), output2D->dataY(17).size() ); - // Check one particular value - TS_ASSERT_EQUALS( output2D2->dataY(8)[502], 121); - // Check that the error on that value is correct - TS_ASSERT_EQUALS( output2D2->dataE(8)[502], 11); - // Check that the time is as expected from bin boundary update - TS_ASSERT_DELTA( output2D->dataX(11)[687], 10.738,0.001); - - // Check the unit has been set correctly - TS_ASSERT_EQUALS( output->getAxis(0)->unit()->unitID(), "Label" ); - TS_ASSERT( ! output-> isDistribution() ); - - //check that sample name has been set correctly - //boost::shared_ptr<Sample> sample,sample2; - // sample = output->getSample(); - // sample2 = output2->getSample(); - TS_ASSERT_EQUALS(output->sample().getName(), output2->sample().getName()); - TS_ASSERT_EQUALS(output->sample().getName(), "ptfe test"); - - } - } - - void testarrayin() - { - if ( !nxload3.isInitialized() ) nxload3.initialize(); - - nxload3.setPropertyValue("Filename", inputFile); - nxload3.setPropertyValue("OutputWorkspace", "outWS"); - nxload3.setPropertyValue("SpectrumList", "29,30,31"); - nxload3.setPropertyValue("SpectrumMin", "5"); - nxload3.setPropertyValue("SpectrumMax", "10"); - - TS_ASSERT_THROWS_NOTHING(nxload3.execute()); - TS_ASSERT( nxload3.isExecuted() ); - - // Get back the saved workspace - MatrixWorkspace_sptr output; - (output = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>("outWS")); - Workspace2D_sptr output2D = boost::dynamic_pointer_cast<Workspace2D>(output); - - // Should be 6 for selected input - TS_ASSERT_EQUALS( output2D->getNumberHistograms(), 9); - - // Check two X vectors are the same - TS_ASSERT( (output2D->dataX(1)) == (output2D->dataX(5)) ); - - // Check two Y arrays have the same number of elements - TS_ASSERT_EQUALS( output2D->dataY(2).size(), output2D->dataY(7).size() ); - - // Check one particular value - TS_ASSERT_EQUALS( output2D->dataY(8)[479], 144); - // Check that the error on that value is correct - TS_ASSERT_EQUALS( output2D->dataE(8)[479], 12); - // Check that the error on that value is correct - TS_ASSERT_DELTA( output2D->dataX(8)[479], 7.410, 0.0001); - } - -private: - LoadMuonNexus nxLoad,nxload2,nxload3; - std::string outputSpace; - std::string entryName; - std::string inputFile; - std::string inputFile2; - boost::shared_ptr<SpectraDetectorMap> map; }; + #endif /*LOADMUONNEXUSTEST_H_*/ diff --git a/Code/Mantid/Framework/Nexus/inc/MantidNexus/NexusClasses.h b/Code/Mantid/Framework/Nexus/inc/MantidNexus/NexusClasses.h index 1a215c1991371ad55865ed47c0c0444697cf6432..f63827b2aed8ebb1219e32b49529c13731e68228 100644 --- a/Code/Mantid/Framework/Nexus/inc/MantidNexus/NexusClasses.h +++ b/Code/Mantid/Framework/Nexus/inc/MantidNexus/NexusClasses.h @@ -399,7 +399,7 @@ namespace Mantid alloc(n); getSlab(m_data.get(),start,m_size); } - protected: + private: /** Allocates memory for the data buffer * @param n :: The number of elements to allocate. */ @@ -559,7 +559,10 @@ namespace Mantid * @return NXInfo::stat is set to NX_ERROR if the dataset does not exist */ NXInfo getDataSetInfo(const std::string& name)const; - void close();///< Close this class + /// Returns whether an individual dataset is present + bool containsDataSet(const std::string & query) const; + /// Close this class + void close(); /// Opens this NXClass using NXopengrouppath. Can be slow (or is slow) void open(); /// Opens this NXClass using NXopengroup. It is fast, but the parent of this class must be open at diff --git a/Code/Mantid/Framework/Nexus/src/NexusClasses.cpp b/Code/Mantid/Framework/Nexus/src/NexusClasses.cpp index ab7cf50613d7fb2a6e578774db4d76050872d387..153924ee68da0e7e61486c63d119321ad23abb33 100644 --- a/Code/Mantid/Framework/Nexus/src/NexusClasses.cpp +++ b/Code/Mantid/Framework/Nexus/src/NexusClasses.cpp @@ -307,6 +307,11 @@ bool NXClass::containsGroup(const std::string & query) const return false; } +/** + * Returns NXInfo for a dataset + * @param name :: The name of the dataset + * @return NXInfo::stat is set to NX_ERROR if the dataset does not exist + */ NXInfo NXClass::getDataSetInfo(const std::string& name)const { NXInfo info; @@ -318,6 +323,14 @@ NXInfo NXClass::getDataSetInfo(const std::string& name)const return info; } +/** + * Returns whether an individual dataset is present. + */ +bool NXClass::containsDataSet(const std::string & query) const +{ + return getDataSetInfo( query ).stat != NX_ERROR; +} + //--------------------------------------------------------- // NXNote methods //--------------------------------------------------------- diff --git a/Test/AutoTestData/deltat_tdc_gpd_0900.nxs b/Test/AutoTestData/deltat_tdc_gpd_0900.nxs new file mode 100644 index 0000000000000000000000000000000000000000..7ca142986212bcd165779924d1a96ceb243176c1 Binary files /dev/null and b/Test/AutoTestData/deltat_tdc_gpd_0900.nxs differ