21template <
typename T>
struct DescriptorCallback {
22 void apply(std::shared_ptr<T> & ) {}
24template <>
struct DescriptorCallback<Kernel::FileDescriptor> {
25 void apply(std::shared_ptr<Kernel::FileDescriptor> &descriptor) { descriptor->resetStreamToStart(); }
30template <
typename T>
struct DescriptorSetter {
32 void apply(std::shared_ptr<NexusFileLoader> & , std::shared_ptr<T> & ) {}
34template <>
struct DescriptorSetter<Nexus::NexusDescriptor> {
35 void apply(std::shared_ptr<NexusFileLoader> &loader,
const std::shared_ptr<Nexus::NexusDescriptor> &descriptor) {
36 loader->setFileInfo(descriptor);
49template <
typename DescriptorType,
typename FileLoaderType>
50std::pair<IAlgorithm_sptr, int> searchForLoader(
const std::string &filename,
51 const std::multimap<std::string, int> &names, Kernel::Logger &logger) {
52 const auto &factory = AlgorithmFactory::Instance();
55 auto descriptor = std::make_shared<DescriptorType>(filename);
56 DescriptorCallback<DescriptorType> callback;
57 DescriptorSetter<DescriptorType> setdescriptor;
59 auto iend = names.end();
60 for (
auto it = names.begin(); it != iend; ++it) {
61 const std::string &
name = it->first;
62 const int version = it->second;
63 logger.debug() <<
"Checking " <<
name <<
" version " << version <<
'\n';
67 auto alg = std::static_pointer_cast<FileLoaderType>(factory.create(
name, version));
69 const int confidence = alg->confidence(*(descriptor.get()));
70 logger.debug() <<
name <<
" returned with confidence=" << confidence <<
'\n';
71 if (confidence > maxConfidence)
74 maxConfidence = confidence;
76 }
catch (std::exception &exc) {
77 logger.warning() <<
"Checking loader '" <<
name <<
"' raised an error: '" << exc.what() <<
"'. Loader skipped.\n";
79 callback.apply(descriptor);
82 auto nxsLoader = std::dynamic_pointer_cast<NexusFileLoader>(bestLoader);
84 setdescriptor.apply(nxsLoader, descriptor);
86 return {bestLoader, maxConfidence};
102 for (
auto it =
m_names.begin(); it != iend; ++it) {
119 m_log.
debug() <<
"Trying to find loader for '" << filename <<
"'\n";
123 if (H5::H5File::isHdf5(filename)) {
126 std::pair<IAlgorithm_sptr, int> NexusLazyResult =
127 searchForLoader<Nexus::NexusDescriptorLazy, IFileLoader<Nexus::NexusDescriptorLazy>>(filename,
130 if (NexusLazyResult.second < 80) {
131 std::pair<IAlgorithm_sptr, int> NexusResult =
132 searchForLoader<NexusDescriptor, IFileLoader<NexusDescriptor>>(filename,
m_names[
Nexus],
m_log);
135 if (NexusResult.second < 80) {
139 std::pair<IAlgorithm_sptr, int> LegacyNexusResult =
140 searchForLoader<LegacyNexusDescriptor, IFileLoader<LegacyNexusDescriptor>>(filename,
m_names[
LegacyNexus],
143 bestLoader = std::max({NexusResult, NexusLazyResult, LegacyNexusResult}, [](
const auto &a,
const auto &b) {
144 return a.second < b.second;
147 bestLoader = std::max({NexusResult, NexusLazyResult}, [](
const auto &a,
const auto &b) {
148 return a.second < b.second;
152 bestLoader = NexusLazyResult.first;
156 bestLoader = searchForLoader<LegacyNexusDescriptor, IFileLoader<LegacyNexusDescriptor>>(
159 }
catch (std::exception
const &e) {
160 m_log.
debug() <<
"Error in looking for NeXus files: " << e.what() <<
'\n';
165 bestLoader = searchForLoader<FileDescriptor, IFileLoader<FileDescriptor>>(filename,
m_names[
Generic],
m_log).first;
170 m_log.
debug() <<
"Found loader " << bestLoader->name() <<
" for file '" << filename <<
"'\n";
192 if (!(legacynexus || nexus || nonHDF || lazyNexus))
193 throw std::invalid_argument(
"FileLoaderRegistryImpl::canLoad - Algorithm '" + algorithmName +
194 "' is not registered as a loader.");
196 std::multimap<std::string, int> names{{algorithmName, -1}};
200 loader = searchForLoader<LegacyNexusDescriptor, IFileLoader<LegacyNexusDescriptor>>(filename, names,
m_log).first;
201 }
catch (std::exception
const &e) {
202 m_log.
debug() <<
"Error in looking for NeXus files: " << e.what() <<
'\n';
205 if (H5::H5File::isHdf5(filename)) {
207 loader = searchForLoader<NexusDescriptor, IFileLoader<NexusDescriptor>>(filename, names,
m_log).first;
208 }
catch (
const std::invalid_argument &e) {
209 m_log.
debug() <<
"Error in looking for HDF5 based NeXus files: " << e.what() <<
'\n';
212 }
else if (lazyNexus) {
213 if (H5::H5File::isHdf5(filename)) {
216 searchForLoader<Nexus::NexusDescriptorLazy, IFileLoader<Nexus::NexusDescriptorLazy>>(filename, names,
m_log)
218 }
catch (
const std::invalid_argument &e) {
219 m_log.
debug() <<
"Error in looking for lazy HDF5 based NeXus files: " << e.what() <<
'\n';
223 loader = searchForLoader<FileDescriptor, IFileLoader<FileDescriptor>>(filename, names,
m_log).first;
225 return static_cast<bool>(loader);
246 std::multimap<std::string, int> &typedLoaders) {
249 typedLoaders.erase(
name);
252 auto range = typedLoaders.equal_range(
name);
253 for (
auto ritr = range.first; ritr != range.second; ++ritr) {
254 if (ritr->second == version) {
255 typedLoaders.erase(ritr);
std::array< std::multimap< std::string, int >, enum_count > m_names
The list of names.
const std::shared_ptr< IAlgorithm > chooseLoader(const std::string &filename) const
Returns the name of an Algorithm that can load the given filename.
FileLoaderRegistryImpl()
Default constructor (for singleton)
void unsubscribe(const std::string &name, const int version=-1)
Unsubscribe a named algorithm and version from the loader registration.
bool canLoad(const std::string &algorithmName, const std::string &filename) const
Checks whether the given algorithm can load the file.
void removeAlgorithm(const std::string &name, const int version, std::multimap< std::string, int > &typedLoaders)
Remove a named algorithm & version from the given map.
Kernel::Logger m_log
Reference to a logger.
~FileLoaderRegistryImpl()
Destructor.
Exception for when an item is not found in a collection.
Defines a wrapper around an open file.
Defines a wrapper around a file whose internal structure can be accessed using the NeXus API.
void debug(const std::string &msg)
Logs at debug level.
std::shared_ptr< IAlgorithm > IAlgorithm_sptr
shared pointer to Mantid::API::IAlgorithm