Skip to content

Commit

Permalink
Fix bug with running correct version of loader. Refs #7263
Browse files Browse the repository at this point in the history
  • Loading branch information
martyngigg committed Jul 3, 2013
1 parent 146d72e commit e1dcfe7
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 118 deletions.
9 changes: 5 additions & 4 deletions Code/Mantid/Framework/API/inc/MantidAPI/AlgorithmFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class MANTID_API_DLL AlgorithmFactoryImpl : public Kernel::DynamicFactory<Algori

/// 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);
Expand All @@ -82,7 +82,7 @@ class MANTID_API_DLL AlgorithmFactoryImpl : public Kernel::DynamicFactory<Algori
* @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);
Expand Down Expand Up @@ -110,8 +110,9 @@ class MANTID_API_DLL AlgorithmFactoryImpl : public Kernel::DynamicFactory<Algori
}
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);
Expand Down
14 changes: 8 additions & 6 deletions Code/Mantid/Framework/API/inc/MantidAPI/FileLoaderRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include "MantidAPI/AlgorithmFactory.h"
#include "MantidKernel/SingletonHolder.h"

#include <set>
#include <map>
#include <string>
#include <vector>

Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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;

Expand Down
33 changes: 18 additions & 15 deletions Code/Mantid/Framework/API/src/FileLoaderRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand All @@ -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;
}

Expand All @@ -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"))
{
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
97 changes: 17 additions & 80 deletions Code/Mantid/Framework/DataHandling/src/Load.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,90 +236,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))
Expand All @@ -331,9 +264,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;
}

/**
Expand Down Expand Up @@ -404,6 +340,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 )
Expand Down Expand Up @@ -439,11 +377,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
Expand Down Expand Up @@ -558,17 +495,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 )
{
Expand Down
26 changes: 17 additions & 9 deletions Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 0 additions & 1 deletion Code/Mantid/Framework/DataHandling/src/LoadRKH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(" ");

Expand Down

0 comments on commit e1dcfe7

Please sign in to comment.