Commit 622fa5dd authored by David Fairbrother's avatar David Fairbrother
Browse files

Move GetIPFPath into ExperimentInfo

Moves the method for getting IPF Paths into Experiment info as a static
method, so it can be called internally and by Python APIs
parent 9ad3975c
......@@ -158,6 +158,12 @@ public:
/// Get the IDF using the instrument name and date
static std::string getInstrumentFilename(const std::string &instrumentName,
const std::string &date = "");
/// Search instrument directories for Parameter file,
/// return full path name if found, else "".
static std::string getFullPathParamIDF(std::string instName,
const std::string &dirHint = "");
const Geometry::DetectorInfo &detectorInfo() const;
Geometry::DetectorInfo &mutableDetectorInfo();
......
......@@ -43,7 +43,6 @@
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/regex.hpp>
#include <memory>
#include <Poco/DirectoryIterator.h>
#include <Poco/Path.h>
......@@ -51,6 +50,9 @@
#include <Poco/SAX/ContentHandler.h>
#include <Poco/SAX/SAXParser.h>
#include <nexus/NeXusException.hpp>
#include <algorithm>
#include <memory>
#include <tuple>
using namespace Mantid::Geometry;
......@@ -1004,6 +1006,85 @@ ExperimentInfo::getInstrumentFilename(const std::string &instrumentName,
return instFile;
}
//-----------------------------------------------------------------------------------------------------------------------
/// Search the directory for the Parameter IDF file and return full path name if
/// found, else return "".
// directoryName must include a final '/'.
std::string ExperimentInfo::getFullPathParamIDF(std::string instName,
const std::string &dirHint) {
constexpr auto lookupFile = [](const std::string &dir,
const std::string &filename) {
Poco::Path directoryPath(dir);
directoryPath.makeDirectory();
// Remove the path from the filename
Poco::Path filePath(filename);
const std::string &instrumentFile = filePath.getFileName();
// First check whether there is a parameter file whose name is the same as
// the IDF file, but with 'Parameters' instead of 'Definition'.
std::string definitionPart("_Definition");
const std::string::size_type prefix_end(
instrumentFile.find(definitionPart));
const std::string::size_type suffix_start =
prefix_end + definitionPart.length();
// Get prefix and leave case sensitive
std::string prefix = instrumentFile.substr(0, prefix_end);
// Make suffix ensuring it has positive length
std::string suffix = ".xml";
if (suffix_start < instrumentFile.length()) {
suffix = instrumentFile.substr(suffix_start, std::string::npos);
}
// Assemble parameter file name
std::string fullPathParamIDF =
directoryPath.setFileName(prefix + "_Parameters" + suffix).toString();
if (!Poco::File(fullPathParamIDF)
.exists()) { // No such file exists, so look
// for file based on instrument
// ID
// given by the prefix
fullPathParamIDF =
directoryPath.setFileName(prefix + "_Parameters.xml").toString();
}
if (!Poco::File(fullPathParamIDF)
.exists()) { // No such file exists, indicate
// none found in this directory.
fullPathParamIDF = "";
}
return fullPathParamIDF;
};
// All inst names are stored as capitals currently,
// so we need to also do this for case-sensitive filesystems
std::transform(instName.begin(), instName.end(), instName.begin(), ::toupper);
// Try the hinted dir first
if (!dirHint.empty()) {
const std::string result = lookupFile(dirHint, instName);
if (!result.empty()) {
return result;
}
}
Kernel::ConfigServiceImpl &configService = Kernel::ConfigService::Instance();
std::vector<std::string> directoryNames =
configService.getInstrumentDirectories();
for (const auto &dirName : directoryNames) {
// This will iterate around the directories from user ->etc ->install, and
// find the first beat file
const std::string result = lookupFile(dirName, instName);
if (!result.empty()) {
return result;
}
}
return "";
}
/** Return a const reference to the DetectorInfo object.
*
* Setting a new instrument via ExperimentInfo::setInstrument will invalidate
......
......@@ -5,7 +5,6 @@
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
// SPDX - License - Identifier: GPL - 3.0 +
#pragma once
#include "MantidAPI/ExperimentInfo.h"
#include "MantidAPI/Run.h"
#include "MantidAPI/Sample.h"
......@@ -25,14 +24,16 @@
#include "MantidTestHelpers/NexusTestHelper.h"
#include "PropertyManagerHelper.h"
// clang-format off
#include <nexus/NeXusFile.hpp>
#include <nexus/NeXusException.hpp>
// clang-format on
#include <nexus/NeXusFile.hpp>
#include <cxxtest/TestSuite.h>
#include <boost/regex.hpp>
#include <Poco/DirectoryIterator.h>
#include <Poco/File.h>
#include <Poco/Path.h>
#include <Poco/TemporaryFile.h>
#include <boost/algorithm/string.hpp>
#include <boost/regex.hpp>
#include <cxxtest/TestSuite.h>
#include <set>
#include <unordered_map>
......@@ -424,6 +425,44 @@ public:
}
}
void testFindIPF() {
// Check that instrument dirs are searched correctly
const std::string expectedFileName = "GEM_parameters.xml";
const auto result = ExperimentInfo::getFullPathParamIDF("GEM");
TS_ASSERT(boost::icontains(result, expectedFileName));
// Should be case insensitive
const auto mixedResult = ExperimentInfo::getFullPathParamIDF("GeM");
TS_ASSERT_EQUALS(result, mixedResult);
}
void testFindIPFNonExistant() {
const auto result = ExperimentInfo::getFullPathParamIDF("NotThere");
TS_ASSERT_EQUALS("", result);
}
void testFindIPFWithHint() {
const auto tmpDir = Poco::Path::temp();
const std::string filename = "TEST_Parameters.xml";
const std::string expectedPath = tmpDir + filename;
Poco::TemporaryFile::registerForDeletion(expectedPath);
Poco::File fileHandle(expectedPath);
fileHandle.createFile();
const auto result = ExperimentInfo::getFullPathParamIDF("test", tmpDir);
// Ensure file was found and it's in the tmp dir
TS_ASSERT(result.find(filename) != std::string::npos);
TS_ASSERT(result.find(tmpDir) != std::string::npos);
}
void testNonExistantIPFWithHint() {
const auto tmpDir = Poco::Path::temp();
const auto result = ExperimentInfo::getFullPathParamIDF("notThere", tmpDir);
TS_ASSERT(result.empty());
}
//
void testHelperFunctions() {
ConfigService::Instance().updateFacilities();
......
......@@ -84,11 +84,6 @@ private:
void runLoadParameterFile(const std::shared_ptr<API::MatrixWorkspace> &ws,
const std::string &filename);
/// Search instrument directories for Parameter file,
/// return full path name if found, else "".
std::string getFullPathParamIDF(const std::string &filename,
const std::string &dirHint = "");
/// Mutex to avoid simultaneous access
static std::recursive_mutex m_mutex;
};
......
......@@ -263,7 +263,8 @@ void LoadInstrument::runLoadParameterFile(
const std::string::size_type dir_end = filename.find_last_of("\\/");
std::string directoryName =
filename.substr(0, dir_end + 1); // include final '/'.
std::string fullPathParamIDF = getFullPathParamIDF(filename, directoryName);
std::string fullPathParamIDF =
ExperimentInfo::getFullPathParamIDF(filename, directoryName);
if (!fullPathParamIDF.empty()) {
......@@ -291,80 +292,5 @@ void LoadInstrument::runLoadParameterFile(
}
}
//-----------------------------------------------------------------------------------------------------------------------
/// Search the directory for the Parameter IDF file and return full path name if
/// found, else return "".
// directoryName must include a final '/'.
std::string LoadInstrument::getFullPathParamIDF(const std::string &filename,
const std::string &dirHint) {
constexpr auto lookupFile = [](const std::string &dir,
const std::string &filename) {
Poco::Path directoryPath(dir);
directoryPath.makeDirectory();
// Remove the path from the filename
Poco::Path filePath(filename);
const std::string &instrumentFile = filePath.getFileName();
// First check whether there is a parameter file whose name is the same as
// the IDF file, but with 'Parameters' instead of 'Definition'.
std::string definitionPart("_Definition");
const std::string::size_type prefix_end(
instrumentFile.find(definitionPart));
const std::string::size_type suffix_start =
prefix_end + definitionPart.length();
// Get prefix and leave case sensitive
std::string prefix = instrumentFile.substr(0, prefix_end);
// Make suffix ensuring it has positive length
std::string suffix = ".xml";
if (suffix_start < instrumentFile.length()) {
suffix = instrumentFile.substr(suffix_start, std::string::npos);
}
// Assemble parameter file name
std::string fullPathParamIDF =
directoryPath.setFileName(prefix + "_Parameters" + suffix).toString();
if (!Poco::File(fullPathParamIDF)
.exists()) { // No such file exists, so look
// for file based on instrument
// ID
// given by the prefix
fullPathParamIDF =
directoryPath.setFileName(prefix + "_Parameters.xml").toString();
}
if (!Poco::File(fullPathParamIDF)
.exists()) { // No such file exists, indicate
// none found in this directory.
fullPathParamIDF = "";
}
return fullPathParamIDF;
};
// Try the hinted dir first
if (!dirHint.empty()) {
const std::string result = lookupFile(dirHint, filename);
if (!result.empty()) {
return result;
}
}
Kernel::ConfigServiceImpl &configService = Kernel::ConfigService::Instance();
std::vector<std::string> directoryNames =
configService.getInstrumentDirectories();
for (const auto &dirName : directoryNames) {
// This will iterate around the directories from user ->etc ->install, and
// find the first beat file
const std::string result = lookupFile(dirName, filename);
if (!result.empty()) {
return result;
}
}
return "";
}
} // namespace DataHandling
} // namespace Mantid
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment