diff --git a/Framework/DataHandling/inc/MantidDataHandling/LoadLog.h b/Framework/DataHandling/inc/MantidDataHandling/LoadLog.h index 7de2cb3ab667218a4fc352a3868a07bf419b34fc..87412001212e1885a5c8d037e844d371df68803a 100644 --- a/Framework/DataHandling/inc/MantidDataHandling/LoadLog.h +++ b/Framework/DataHandling/inc/MantidDataHandling/LoadLog.h @@ -100,10 +100,14 @@ private: /// Checks if the file is an ASCII file bool isAscii(const std::string &filename); - /// Check if first 19 characters of a string is data-time string according to + /// Check if first 19 characters of a string is date-time string according to /// yyyy-mm-ddThh:mm:ss bool isDateTimeString(const std::string &str) const; + /// Check whether the first 24 characters of a string are consistent with + /// the date-time format used in older unsupported log files. + bool isOldDateTimeFormat(std::ifstream &logFileStream) const; + /// Checks if a log file name was provided (e.g. through setPropertyValue). If /// not it creates one based on provided path. std::string extractLogName(const std::vector<std::string> &logName); diff --git a/Framework/DataHandling/src/LoadLog.cpp b/Framework/DataHandling/src/LoadLog.cpp index c771655cb7074ad72a821c71a55a2f2ba7b81172..df67c5718622f0026622264ee33f219cdc371237 100644 --- a/Framework/DataHandling/src/LoadLog.cpp +++ b/Framework/DataHandling/src/LoadLog.cpp @@ -27,6 +27,7 @@ #include <Poco/Path.h> #include <boost/algorithm/string.hpp> #include <fstream> // used to get ifstream +#include <regex> #include <sstream> #include <utility> @@ -143,6 +144,13 @@ void LoadLog::exec() { "More than one log name provided. Invalid ISIS log file."); } + // If it's an old log file (pre-2007), then it is not currently supported. + if (isOldDateTimeFormat(logFileStream)) { + throw std::invalid_argument( + "File " + m_filename + + " cannot be read because it has an old unsupported format."); + } + int colNum = static_cast<int>(getProperty("NumberOfColumns")); if (colNum == Mantid::EMPTY_INT()) { @@ -181,7 +189,7 @@ void LoadLog::loadTwoColumnLogFile(std::ifstream &logFileStream, std::string aLine; if (Mantid::Kernel::Strings::extractToEOL(logFileStream, aLine)) { if (!isDateTimeString(aLine)) { - throw std::invalid_argument("File" + m_filename + + throw std::invalid_argument("File " + m_filename + " is not a standard ISIS log file. Expected " "to be a two column file."); } @@ -239,7 +247,7 @@ void LoadLog::loadThreeColumnLogFile(std::ifstream &logFileStream, while (Mantid::Kernel::Strings::extractToEOL(logFileStream, str)) { if (!isDateTimeString(str) && !str.empty()) { - throw std::invalid_argument("File" + logFileName + + throw std::invalid_argument("File " + logFileName + " is not a standard ISIS log file. Expected " "to be a file starting with DateTime String " "format."); @@ -267,7 +275,7 @@ void LoadLog::loadThreeColumnLogFile(std::ifstream &logFileStream, if (LoadLog::string != l_kind) { throw std::invalid_argument( - "ISIS log file contains unrecognised second column entries:" + + "ISIS log file contains unrecognised second column entries: " + logFileName); } @@ -491,6 +499,27 @@ bool LoadLog::isDateTimeString(const std::string &str) const { return Types::Core::DateAndTimeHelpers::stringIsISO8601(str.substr(0, 19)); } +/** + * Check whether the string is consistent with the old log file + * date-time format, for example: + * Fri 31-JAN-2003 11:28:15 + * Wed 9-FEB-2005 09:47:01 + * @param logFileStream :: The file to test + * @return true if the format matches the old log file format. + */ +bool LoadLog::isOldDateTimeFormat(std::ifstream &logFileStream) const { + // extract first line of file + std::string firstLine; + Mantid::Kernel::Strings::extractToEOL(logFileStream, firstLine); + // reset file back to the beginning + logFileStream.seekg(0); + + std::regex oldDateFormat( + R"([A-Z][a-z]{2} [ 1-3]\d-[A-Z]{3}-\d{4} \d{2}:\d{2}:\d{2})"); + + return std::regex_match(firstLine.substr(0, 24), oldDateFormat); +} + /** * Read a line of a SNS-style text file. * @param str :: The string to test @@ -532,7 +561,7 @@ int LoadLog::countNumberColumns(std::ifstream &logFileStream, Mantid::Kernel::Strings::extractToEOL(logFileStream, str); if (!isDateTimeString(str)) { - throw std::invalid_argument("File" + logFileName + + throw std::invalid_argument("File " + logFileName + " is not a standard ISIS log file. Expected to " "be a file starting with DateTime String " "format."); @@ -548,7 +577,7 @@ int LoadLog::countNumberColumns(std::ifstream &logFileStream, if (LoadLog::string != l_kind && LoadLog::number != l_kind) { throw std::invalid_argument( - "ISIS log file contains unrecognised second column entries:" + + "ISIS log file contains unrecognised second column entries: " + logFileName); } diff --git a/Framework/DataHandling/test/LoadLogTest.h b/Framework/DataHandling/test/LoadLogTest.h index 65d6fa273e906de8db2bcfb1c512ca6db594e1c8..9a1bb00857fc2274942e209bb1436017820f6702 100644 --- a/Framework/DataHandling/test/LoadLogTest.h +++ b/Framework/DataHandling/test/LoadLogTest.h @@ -142,6 +142,35 @@ public: AnalysisDataService::Instance().remove(outputSpace); } + void testOldLogFileWithSingleDigitDate() { + // Snippet from an old log file with unsupported format. + std::string oldLogText( + "Sat 8-FEB-2003 11:29:24 EXECUTING DOSANS\n" + "Sat 8-FEB-2003 11:29:25 LOAD INST.UPD\n" + "Sat 8-FEB-2003 11:29:25 CHANGE RUNTABLE " + "LOQ$DISK0:[LOQ]INST.UPD;15625\n" + "Sat 8-FEB-2003 11:29:27 CSET TRANS OUT\n" + "Sat 8-FEB-2003 11:29:27 COMND TRANS WR 05 2 1 16 4\n"); + + TS_ASSERT(oldLogFileGivesCorrectWarning(oldLogText)); + } + + void testOldLogFileWithDoubleDigitDate() { + // Snippet from an old log file with unsupported format. + std::string oldLogText("Fri 31-JAN-2003 11:28:15 EXECUTING DOTRANS\n" + "Fri 31-JAN-2003 11:28:41 STOPD A2 _LTA5007: " + " 2.7000 2.7000\n" + "Fri 31-JAN-2003 11:28:42 LOAD INST.UPD\n" + "Fri 31-JAN-2003 11:28:42 CHANGE RUNTABLE " + "LOQ$DISK0:[LOQ]INST.UPD;14965\n" + "Fri 31-JAN-2003 11:28:42 DEBUG 1 ack 001 suc 000\n" + "Fri 31-JAN-2003 11:28:42 DEBUG 1 res 001 suc 002 " + "H000000F0 H00000006\n" + "Fri 31-JAN-2003 11:28:43 CSET TRANS IN\n"); + + TS_ASSERT(oldLogFileGivesCorrectWarning(oldLogText)); + } + void test_log_file_has_error() { std::string logFileText("2007-11-16T13:25:48 i1 0 \n" "2007-11-16T13:29:36 str1 a\n" @@ -312,4 +341,33 @@ private: std::string inputFile; std::string outputSpace; std::string inputSpace; + + bool oldLogFileGivesCorrectWarning(std::string &logFileText) { + + ScopedFile oldLogFile(logFileText, "oldLogFile.log"); + + MatrixWorkspace_sptr ws = + WorkspaceFactory::Instance().create("Workspace2D", 1, 1, 1); + + LoadLog loadAlg; + loadAlg.initialize(); + loadAlg.setPropertyValue("Filename", oldLogFile.getFileName()); + loadAlg.setProperty("Workspace", ws); + // We want to see what the exception message is. + loadAlg.setRethrows(true); + + // LoadLog algorithm should throw exception with an error message that + // contains "" + try { + loadAlg.execute(); + } catch (std::exception &ex) { + std::string errorMessage(ex.what()); + + if (errorMessage.find("old unsupported format") != std::string::npos) { + return true; + } + } + + return false; + } }; diff --git a/docs/source/release/v6.1.0/framework.rst b/docs/source/release/v6.1.0/framework.rst index 83e14798e188a816e488cc91805a40cdf0d51971..fac7bd445aca56332cfb42eb446b17923079c747 100644 --- a/docs/source/release/v6.1.0/framework.rst +++ b/docs/source/release/v6.1.0/framework.rst @@ -22,6 +22,7 @@ Algorithms - :ref:`CompareWorkspaces <algm-CompareWorkspaces>` compares the positions of both source and sample (if extant) when property `checkInstrument` is set. - :ref:`SetGoniometer <algm-SetGoniometer>` can now set multiple goniometers from log values instead of just the time-avereged value. - Added the ability to specify the spectrum number in :ref:`FindPeaksAutomatic <algm-FindPeaksAutomatic>`. +- :ref:`LoadLog <algm-LoadLog>` will now detect old unsupported log files and set an appropriate explanatory string in the exception. Data Objects