diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/AlgorithmFactory.h b/Code/Mantid/Framework/API/inc/MantidAPI/AlgorithmFactory.h index 69c2c63a61e480494296be6ff8059666c594a486..0c71e9cfb22a2556bdf91a1ee5bce3d7039b65a9 100644 --- a/Code/Mantid/Framework/API/inc/MantidAPI/AlgorithmFactory.h +++ b/Code/Mantid/Framework/API/inc/MantidAPI/AlgorithmFactory.h @@ -68,7 +68,7 @@ public: /// algorithm factory specific function to subscribe algorithms, calls the dynamic factory subscribe function internally template <class C> - std::string subscribe() + std::pair<std::string,int> subscribe() { Kernel::Instantiator<C, Algorithm>* newI = new Kernel::Instantiator<C, Algorithm>; return this->subscribe(newI); @@ -82,7 +82,7 @@ public: * @returns The classname that was registered */ template<class T> - std::string subscribe(Kernel::AbstractInstantiator<T> *instantiator, const SubscribeAction replaceExisting = ErrorIfExists) + std::pair<std::string,int> subscribe(Kernel::AbstractInstantiator<T> *instantiator, const SubscribeAction replaceExisting = ErrorIfExists) { boost::shared_ptr<IAlgorithm> tempAlg = instantiator-> createInstance(); const int version = extractAlgVersion(tempAlg); @@ -110,8 +110,9 @@ public: } Kernel::DynamicFactory<Algorithm>::subscribe(key, instantiator, replaceExisting); } - else throw std::invalid_argument("Cannot register empty algorithm name"); - return className; + else + throw std::invalid_argument("Cannot register empty algorithm name"); + return std::make_pair(className,version); } /// Unsubscribe the given algorithm void unsubscribe(const std::string & algorithmName, const int version); diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/FileLoaderRegistry.h b/Code/Mantid/Framework/API/inc/MantidAPI/FileLoaderRegistry.h index 5d365aa815fda01e02f7331d0313989a91148d82..6467ea1a7e198b96c18036d128397fc662caf851 100644 --- a/Code/Mantid/Framework/API/inc/MantidAPI/FileLoaderRegistry.h +++ b/Code/Mantid/Framework/API/inc/MantidAPI/FileLoaderRegistry.h @@ -5,7 +5,7 @@ #include "MantidAPI/AlgorithmFactory.h" #include "MantidKernel/SingletonHolder.h" -#include <set> +#include <map> #include <string> #include <vector> @@ -18,6 +18,8 @@ namespace Mantid } namespace API { + // Forward declaration + class IAlgorithm; /** Keeps a registry of algorithm's that are file loading algorithms to allow them to be searched @@ -68,15 +70,15 @@ namespace Mantid template<typename Type> void subscribe(LoaderFormat format) { - const std::string name = AlgorithmFactory::Instance().subscribe<Type>(); + const auto nameVersion = AlgorithmFactory::Instance().subscribe<Type>(); // If the factory didn't throw then the name is valid - m_names[format].insert(name); + m_names[format].insert(nameVersion); m_totalSize += 1; - m_log.debug() << "Registered '" << name << "' as file loader\n"; + m_log.debug() << "Registered '" << nameVersion.first << "' version '" << nameVersion.second << "' as file loader\n"; } /// Returns the name of an Algorithm that can load the given filename - const std::string chooseLoader(const std::string &filename) const; + const boost::shared_ptr<IAlgorithm> chooseLoader(const std::string &filename) const; private: /// Friend so that CreateUsingNew @@ -88,7 +90,7 @@ namespace Mantid ~FileLoaderRegistryImpl(); /// The list of names. The index pointed to by LoaderFormat defines a set for that format - std::vector<std::set<std::string> > m_names; + std::vector<std::multimap<std::string,int> > m_names; /// Total number of names registered size_t m_totalSize; diff --git a/Code/Mantid/Framework/API/src/FileLoaderRegistry.cpp b/Code/Mantid/Framework/API/src/FileLoaderRegistry.cpp index 0554a9b85e121096790fc492ec4d4dbd26789455..da1cb58965d176f055a3949684fb0c7611ebb32e 100644 --- a/Code/Mantid/Framework/API/src/FileLoaderRegistry.cpp +++ b/Code/Mantid/Framework/API/src/FileLoaderRegistry.cpp @@ -35,27 +35,29 @@ namespace Mantid * was found */ template<typename DescriptorType, typename FileLoaderType> - const std::string searchForLoader(DescriptorType & descriptor,const std::set<std::string> & names, - Kernel::Logger & logger) + const IAlgorithm_sptr searchForLoader(DescriptorType & descriptor,const std::multimap<std::string, int> & names, + Kernel::Logger & logger) { const auto & factory = AlgorithmFactory::Instance(); - std::string bestLoader; + IAlgorithm_sptr bestLoader; int maxConfidence(0); DescriptorCallback<DescriptorType> callback; auto iend = names.end(); for(auto it = names.begin(); it != iend; ++it) { - const std::string & name = *it; - logger.debug() << "Checking " << name << std::endl; + const std::string & name = it->first; + const int version = it->second; + logger.debug() << "Checking " << name << " version " << version << std::endl; - auto alg = boost::static_pointer_cast<FileLoaderType>(factory.create(name, -1)); // highest version + auto alg = boost::static_pointer_cast<FileLoaderType>(factory.create(name, version)); // highest version try { const int confidence = alg->confidence(descriptor); + logger.debug() << name << " returned with confidence=" << confidence << std::endl; if(confidence > maxConfidence) // strictly greater { - bestLoader = name; + bestLoader = alg; maxConfidence = confidence; } } @@ -81,32 +83,33 @@ namespace Mantid * @return A string containing the name of an algorithm to load the file * @throws Exception::NotFoundError if an algorithm cannot be found */ - const std::string FileLoaderRegistryImpl::chooseLoader(const std::string &filename) const + const boost::shared_ptr<IAlgorithm> FileLoaderRegistryImpl::chooseLoader(const std::string &filename) const { using Kernel::FileDescriptor; using Kernel::HDFDescriptor; + using Kernel::Logger; - m_log.debug() << "Trying to find loader for '" << filename << "'" << std::endl; + if(m_log.is(Logger::Priority::PRIO_DEBUG)) m_log.debug() << "Trying to find loader for '" << filename << "'" << std::endl; - std::string bestLoader; + IAlgorithm_sptr bestLoader; if(HDFDescriptor::isHDF(filename)) { - m_log.debug() << filename << " looks like a HDF file. Checking registered HDF loaders\n"; + if(m_log.is(Logger::Priority::PRIO_DEBUG)) m_log.debug() << filename << " looks like a HDF file. Checking registered HDF loaders\n"; HDFDescriptor descriptor(filename); bestLoader = searchForLoader<HDFDescriptor,IHDFFileLoader>(descriptor, m_names[HDF], m_log); } else { - m_log.debug() << "Checking registered non-HDF loaders\n"; + if(m_log.is(Logger::Priority::PRIO_DEBUG)) m_log.debug() << "Checking registered non-HDF loaders\n"; FileDescriptor descriptor(filename); bestLoader = searchForLoader<FileDescriptor,IFileLoader>(descriptor, m_names[NonHDF], m_log); } - if(bestLoader.empty()) + if(!bestLoader) { throw Kernel::Exception::NotFoundError(filename, "Unable to find loader"); } - m_log.debug() << "Found loader " << bestLoader << " for file '" << filename << "'" << std::endl; + if(m_log.is(Logger::Priority::PRIO_DEBUG)) m_log.debug() << "Found loader " << bestLoader->name() << " for file '" << filename << "'" << std::endl; return bestLoader; } @@ -118,7 +121,7 @@ namespace Mantid * Creates an empty registry */ FileLoaderRegistryImpl::FileLoaderRegistryImpl() : - m_names(2, std::set<std::string>()), m_totalSize(0), + m_names(2, std::multimap<std::string,int>()), m_totalSize(0), m_log(Kernel::Logger::get("FileLoaderRegistry")) { } diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/Load.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/Load.h index 0cd5b24d193d77bdf35a2b7d4be55a22ed418361..e728bd3fd44f9be704bd430cab7323f8c96bd2fd 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/Load.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/Load.h @@ -79,7 +79,7 @@ namespace Mantid /// Overrides the cancel() method to call m_loader->cancel() void cancel(); /// Create the concrete instance use for the actual loading. - API::IAlgorithm_sptr createLoader(const std::string & name, const double startProgress = -1.0, + API::IAlgorithm_sptr createLoader(const double startProgress = -1.0, const double endProgress=-1.0, const bool logging = true) const; /// Set the loader option for use as a Child Algorithm. void setUpLoader(API::IAlgorithm_sptr & loader, const double startProgress = -1.0, diff --git a/Code/Mantid/Framework/DataHandling/src/Load.cpp b/Code/Mantid/Framework/DataHandling/src/Load.cpp index 3c23011d23df594f8b2599b61dd96ac725a14697..b72efa98ff2fd0193ab721b69ca5eed6edc26990 100644 --- a/Code/Mantid/Framework/DataHandling/src/Load.cpp +++ b/Code/Mantid/Framework/DataHandling/src/Load.cpp @@ -234,90 +234,23 @@ namespace Mantid */ API::IAlgorithm_sptr Load::getFileLoader(const std::string& filePath) { -// /* Open the file and read in the first bufferSize bytes - these will -// * be used to determine the type of the file -// */ -// FILE* fp = fopen(filePath.c_str(), "rb"); -// if (fp == NULL) -// { -// throw Kernel::Exception::FileError("Unable to open the file:", filePath); -// } -// file_header header; -// size_t nread = fread(&header,sizeof(unsigned char), g_hdr_bytes, fp); -// // Ensure the character string is null terminated. -// header.full_hdr[g_hdr_bytes] = '\0'; -// -// if (fclose(fp) != 0) -// { -// throw std::runtime_error("Error while closing file \"" + filePath + "\""); -// } -// -// Poco::Mutex::ScopedLock lock( m_mutex ); -// -// // Iterate through all loaders and attempt to find the best qualified for the job. -// // Each algorithm has a quick and long file check. The long version returns an integer -// // giving its certainty about be able to load the file. The highest wins. -// std::vector<std::string> loaderNames = API::LoadAlgorithmFactory::Instance().getKeys(); -// int highestPref(0); -// API::IDataFileChecker_sptr winningLoader; -// std::vector<std::string>::const_iterator cend = loaderNames.end(); -// for( std::vector<std::string>::const_iterator citr = loaderNames.begin(); citr != cend; -// ++citr ) -// { -// IDataFileChecker_sptr loader = API::LoadAlgorithmFactory::Instance().create(*citr); -// try -// { -// if( loader->quickFileCheck(filePath, nread, header) ) -// { -// int pref = loader->fileCheck(filePath); -// // Can't just pick the first as there might be one later in the list with a higher -// // preference -// if( pref > highestPref ) -// { -// highestPref = pref; -// winningLoader = loader; -// } -// } -// } -// catch (std::exception & e) -// { -// g_log.debug() << "Error running file check of " << loader->name() << std::endl; -// g_log.debug() << e.what() << std::endl; -// -// } -// -// } -// -// if( !winningLoader ) -// { -// // Clear what may have been here previously -// setPropertyValue("LoaderName", ""); -// throw std::runtime_error("Cannot find an algorithm that is able to load \"" + filePath + "\".\n" -// "Check that the file is a supported type."); -// } -// g_log.debug() << "Winning loader is " << winningLoader->name() << std::endl; -// setPropertyValue("LoaderName", winningLoader->name()); -// winningLoader->initialize(); -// setUpLoader(winningLoader); -// return winningLoader; - std::string winningLoader; + API::IAlgorithm_sptr winningLoader; try { - CALLGRIND_START_INSTRUMENTATION; winningLoader = API::FileLoaderRegistry::Instance().chooseLoader(filePath); - CALLGRIND_STOP_INSTRUMENTATION; } catch(Exception::NotFoundError&) { // Clear what may have been here previously setPropertyValue("LoaderName", ""); + setProperty("LoaderVersion", -1); throw std::runtime_error("Cannot find an algorithm that is able to load \"" + filePath + "\".\n" "Check that the file is a supported type."); } - const IAlgorithm_sptr loader = AlgorithmManager::Instance().create(winningLoader,-1); - loader->initialize(); + winningLoader->initialize(); + setUpLoader(winningLoader,0,1); // Use the first file property as the main Filename - const auto & props = loader->getProperties(); + const auto & props = winningLoader->getProperties(); for(auto it = props.begin(); it != props.end(); ++it) { if(auto *fp = dynamic_cast<API::FileProperty*>(*it)) @@ -329,9 +262,12 @@ namespace Mantid if(m_filenamePropName.empty()) { setPropertyValue("LoaderName", ""); - throw std::runtime_error("Cannot find FileProperty on " + winningLoader + " algorithm."); + setProperty("LoaderVersion", -1); + throw std::runtime_error("Cannot find FileProperty on " + winningLoader->name() + " algorithm."); } - return loader; + setPropertyValue("LoaderName", winningLoader->name()); + setProperty("LoaderVersion", winningLoader->version()); + return winningLoader; } /** @@ -402,6 +338,8 @@ namespace Mantid declareProperty("LoaderName", std::string(""), "When an algorithm has been found that will load the given file, its name is set here.", Direction::Output); + declareProperty("LoaderVersion", -1, "When an algorithm has been found that will load the given file, its version is set here.", + Direction::Output); // Save for later what the base Load properties are const std::vector<Property*> & props = this->getProperties(); for( size_t i = 0; i < this->propertyCount(); ++i ) @@ -437,11 +375,10 @@ namespace Mantid { m_loader = getFileLoader(getPropertyValue("Filename")); loaderName = m_loader->name(); - setPropertyValue("LoaderName",loaderName); } else { - m_loader = createLoader(loaderName,0,1); + m_loader = createLoader(0,1); } g_log.information() << "Using " << loaderName << " version " << m_loader->version() << ".\n"; ///get the list properties for the concrete loader load algorithm @@ -556,17 +493,17 @@ namespace Mantid /** * Create the concrete instance use for the actual loading. - * @param name :: The name of the loader to instantiate * @param startProgress :: The percentage progress value of the overall * algorithm where this child algorithm starts * @param endProgress :: The percentage progress value of the overall * algorithm where this child algorithm ends * @param logging :: Set to false to disable logging from the child algorithm */ - API::IAlgorithm_sptr Load::createLoader(const std::string & name, const double startProgress, - const double endProgress, const bool logging) const + API::IAlgorithm_sptr Load::createLoader(const double startProgress, const double endProgress, const bool logging) const { - API::IAlgorithm_sptr loader = API::AlgorithmManager::Instance().createUnmanaged(name); + std::string name = getPropertyValue("LoaderName"); + int version = getProperty("LoaderVersion"); + API::IAlgorithm_sptr loader = API::AlgorithmManager::Instance().createUnmanaged(name, version); loader->initialize(); if( !loader ) { diff --git a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp index ba199326eae49c8d4e652e815a31aab2a9a33591..54464f8b8c63d6a6f36844e26f581abc656e36d2 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp @@ -641,26 +641,34 @@ namespace Mantid */ int LoadMuonNexus1::confidence(const Kernel::HDFDescriptor & descriptor) const { + const auto & firstEntryNameType = descriptor.firstEntryNameType(); + const std::string root = "/" + firstEntryNameType.first; + if(!descriptor.pathExists(root + "/analysis")) return 0; + + bool upperIDF(true); + if(descriptor.pathExists(root + "/IDF_version")) upperIDF = true; + else + { + if(descriptor.pathExists(root + "/idf_version")) upperIDF = false; + else return 0; + } + try { NXRoot root(descriptor.filename()); 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; - } + std::string versionField = "idf_version"; + if(upperIDF) versionField = "IDF_version"; + 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 + // If all this succeeded then we'll assume this is an ISIS Muon NeXus file version 2 return 81; } } - catch(...) + catch( ... ) { } return 0; diff --git a/Code/Mantid/Framework/DataHandling/src/LoadRKH.cpp b/Code/Mantid/Framework/DataHandling/src/LoadRKH.cpp index b46c35cd1a520ac7a4552c6fe654288d13a69c19..a28ae7660dba7e1a636367c6a032197d9bec1b37 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadRKH.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadRKH.cpp @@ -43,7 +43,6 @@ int LoadRKH::confidence(Kernel::FileDescriptor & descriptor) const { if(!descriptor.isAscii()) return 0; - int confidence = 0; typedef boost::tokenizer<boost::char_separator<char> > tokenizer; boost::char_separator<char> sep(" "); diff --git a/Code/Mantid/Framework/Kernel/src/HDFDescriptor.cpp b/Code/Mantid/Framework/Kernel/src/HDFDescriptor.cpp index 9c9a185ee521405dbc9c1fc02913a3b5e2092190..fb1d3dac585b43235d68e43f654d884ca2758bde 100644 --- a/Code/Mantid/Framework/Kernel/src/HDFDescriptor.cpp +++ b/Code/Mantid/Framework/Kernel/src/HDFDescriptor.cpp @@ -8,6 +8,7 @@ #include <Poco/Path.h> #include <cstring> +#include <iostream> namespace Mantid { @@ -200,8 +201,12 @@ namespace Mantid m_rootAttrs.insert(attrInfos[i].name); } auto entries = file.getEntries(); - auto entryIter = entries.begin(); - m_firstEntryNameType = std::make_pair(entryIter->first, entryIter->second); + for(auto it = entries.begin(); it != entries.end(); ++it) + { + if(it->second == "CDF0.0") continue; + m_firstEntryNameType = std::make_pair(it->first, it->second); + break; + } m_typesToPaths = file.getTypeMap(); }