Newer
Older
Anders Markvardsen
committed
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidDataHandling/LoadLog.h"
#include "MantidKernel/TimeSeriesProperty.h"
Anders Markvardsen
committed
#include "MantidDataObjects/Workspace2D.h"
#include "boost/filesystem/operations.hpp"
#include "boost/filesystem/path.hpp"
Anders Markvardsen
committed
#include <fstream> // used to get ifstream
Anders Markvardsen
committed
namespace Mantid
{
namespace DataHandling
{
// Register the algorithm into the algorithm factory
DECLARE_ALGORITHM(LoadLog)
using namespace Kernel;
Anders Markvardsen
committed
using DataObjects::Workspace2D;
namespace fs = boost::filesystem; // to help clarify which bits are boost in code below
Anders Markvardsen
committed
Logger& LoadLog::g_log = Logger::get("LoadLog");
/// Empty default constructor
LoadLog::LoadLog() { }
Anders Markvardsen
committed
Anders Markvardsen
committed
/** Initialisation method.
Dickon Champion
committed
* */
void LoadLog::init()
Anders Markvardsen
committed
{
declareProperty("Filename",".");
}
Anders Markvardsen
committed
/** Executes the algorithm. Reading in ISIS log file(s)
Anders Markvardsen
committed
*
Dickon Champion
committed
* @throw Mantid::Kernel::Exception::FileError Thrown if errors with file opening and existence
* @throw std::runtime_error Thrown with Workspace problems
Anders Markvardsen
committed
*/
Dickon Champion
committed
void LoadLog::exec()
Anders Markvardsen
committed
{
// Retrieve the filename from the properties
Anders Markvardsen
committed
Dickon Champion
committed
m_filename = getPropertyValue("Filename");
Anders Markvardsen
committed
Anders Markvardsen
committed
// Retrieve the ws names from the properties
Anders Markvardsen
committed
Anders Markvardsen
committed
std::string inputWorkspaceName;
std::string outputWorkspaceName;
try
{
inputWorkspaceName = getPropertyValue("InputWorkspace");
}
catch (Kernel::Exception::NotFoundError& ex)
{
g_log.debug("InputWorkspace has not been set.");
}
try
{
outputWorkspaceName = getPropertyValue("OutputWorkspace");
}
catch (Kernel::Exception::NotFoundError& ex)
{
Dickon Champion
committed
g_log.error()<<"OutputWorkspace has not been set."<<ex.what();
throw std::runtime_error("OutputWorkspace has not been set");
Anders Markvardsen
committed
}
// Create the 2D workspace for the output
// Get a pointer to the workspace factory (later will be shared)
if (inputWorkspaceName != outputWorkspaceName)
{
API::WorkspaceFactory *factory = API::WorkspaceFactory::Instance();
m_outputWorkspace = factory->create("Workspace2D");
}
else
{
m_outputWorkspace = m_inputWorkspace;
Anders Markvardsen
committed
Anders Markvardsen
committed
// the log file(s) will be loaded into the Sample container of the workspace
API::Sample& sample = m_outputWorkspace->getSample();
Anders Markvardsen
committed
Anders Markvardsen
committed
// do some initial checks on the input m_filename
Anders Markvardsen
committed
fs::path l_path( m_filename );
if ( !fs::exists( l_path ) )
{
g_log.error("In LoadLog: " + m_filename + " does not exist.");
Dickon Champion
committed
throw Exception::FileError("File does not exist:" , m_filename);
Anders Markvardsen
committed
}
if ( fs::is_directory( l_path ) )
{
g_log.error("In LoadLog: " + m_filename + " must be a filename not a directory.");
Dickon Champion
committed
throw Exception::FileError("Filename is a directory:" , m_filename);
Anders Markvardsen
committed
}
Anders Markvardsen
committed
// If m_filename is the filename of a raw datafile then search for potential log files
// in the directory of this raw datafile. Otherwise check if m_filename is a potential
// log file. Add the filename of these potential log files to: potentialLogFiles.
Anders Markvardsen
committed
Anders Markvardsen
committed
std::vector<std::string> potentialLogFiles;
// strip out filename part
std::string l_filenamePart = l_path.leaf();
if ( isLogFile(l_filenamePart) )
Anders Markvardsen
committed
{
Anders Markvardsen
committed
// then we will assume that m_filename is an ISIS log file
potentialLogFiles.push_back(m_filename);
Anders Markvardsen
committed
}
Anders Markvardsen
committed
else if ( stringToLower(l_filenamePart).find(".raw") != std::string::npos && l_filenamePart.size() >= 12 )
{
// then we will assume that m_filename is an ISIS raw file
// strip out the raw data file identifier
Anders Markvardsen
committed
Anders Markvardsen
committed
size_t l_pos = l_filenamePart.find(".");
std::string l_rawID = stringToLower(l_filenamePart.substr(0,l_pos));
// look for log files in the directory of the raw datafile
Anders Markvardsen
committed
Anders Markvardsen
committed
l_path = l_path.remove_leaf();
Anders Markvardsen
committed
Anders Markvardsen
committed
fs::directory_iterator end_iter;
for ( fs::directory_iterator dir_itr( l_path ); dir_itr != end_iter; ++dir_itr )
{
if ( fs::is_regular( dir_itr->status() ) )
{
l_filenamePart = dir_itr->path().leaf();
if ( isLogFile(l_filenamePart) )
if ( stringToLower(l_filenamePart).find(l_rawID) != std::string::npos )
potentialLogFiles.push_back( dir_itr->path().string() );
}
}
}
Anders Markvardsen
committed
Anders Markvardsen
committed
// Attempt to load the content of each potential log file into the Sample object
Anders Markvardsen
committed
for (unsigned int i = 0; i < potentialLogFiles.size(); i++)
Anders Markvardsen
committed
{
Anders Markvardsen
committed
// open log file
std::ifstream inLogFile(potentialLogFiles[i].c_str());
if (!inLogFile)
Anders Markvardsen
committed
{
Anders Markvardsen
committed
// Unable to open file
g_log.error("Unable to open file " + potentialLogFiles[i]);
Dickon Champion
committed
throw Exception::FileError("Unable to open file:" , potentialLogFiles[i]);
Anders Markvardsen
committed
}
Anders Markvardsen
committed
Anders Markvardsen
committed
Anders Markvardsen
committed
// figure out if second column is a number or a string
std::string aLine;
std::string dateAndTime;
kind l_kind;
bool l_JumpToNextLogFile = false;
Anders Markvardsen
committed
while ( std::getline(inLogFile, aLine, '\n') )
{
Anders Markvardsen
committed
{
g_log.warning("File" + potentialLogFiles[i] + " is not a standard ISIS log file. Expected to be a two column file.");
l_JumpToNextLogFile = true;
inLogFile.close();
break;
}
Anders Markvardsen
committed
std::stringstream ins(aLine);
Anders Markvardsen
committed
Anders Markvardsen
committed
ins >> dateAndTime;
Anders Markvardsen
committed
Anders Markvardsen
committed
// read in what follows the date-time string in the log file and figure out
Anders Markvardsen
committed
// what type it is
Anders Markvardsen
committed
Anders Markvardsen
committed
std::string whatType;
Anders Markvardsen
committed
Anders Markvardsen
committed
ins >> whatType;
Anders Markvardsen
committed
Anders Markvardsen
committed
l_kind = classify(whatType);
Anders Markvardsen
committed
Anders Markvardsen
committed
if ( LoadLog::string != l_kind && LoadLog::number != l_kind )
{
g_log.error("File" + potentialLogFiles[i] + " is not a ISIS log file. Can't recognise TYPE");
throw Exception::FileError("ISIS log file contain unrecognised second column entries:", potentialLogFiles[i]);
Anders Markvardsen
committed
}
Anders Markvardsen
committed
Anders Markvardsen
committed
break;
} // end while
Anders Markvardsen
committed
if ( l_JumpToNextLogFile )
{
continue; // jump to next log file
}
Anders Markvardsen
committed
Anders Markvardsen
committed
// reset random access to beginning
Anders Markvardsen
committed
Anders Markvardsen
committed
inLogFile.seekg(0, std::ios::beg);
Anders Markvardsen
committed
Anders Markvardsen
committed
// Read log file into Property which is then stored in Sample object
Anders Markvardsen
committed
TimeSeriesProperty<std::string> *l_PropertyString = new TimeSeriesProperty<std::string>(potentialLogFiles[i]);
TimeSeriesProperty<double> *l_PropertyDouble = new TimeSeriesProperty<double>(potentialLogFiles[i]);
Anders Markvardsen
committed
Anders Markvardsen
committed
// read in the log file
Anders Markvardsen
committed
while ( std::getline(inLogFile, aLine, '\n') )
Anders Markvardsen
committed
{
Anders Markvardsen
committed
{
g_log.warning("File" + potentialLogFiles[i] + " is not a standard ISIS log file. Expected to be two a column file.");
l_JumpToNextLogFile = true;
inLogFile.close();
break; // break out of while look
Anders Markvardsen
committed
}
std::istringstream ins(aLine);
Anders Markvardsen
committed
Anders Markvardsen
committed
ins >> dateAndTime;
Anders Markvardsen
committed
Anders Markvardsen
committed
// strim down the date-time string to format YYYYMMDDTHHmmss
Anders Markvardsen
committed
Anders Markvardsen
committed
dateAndTime.erase(16,1);
dateAndTime.erase(13,1);
dateAndTime.erase(7,1);
dateAndTime.erase(4,1);
Anders Markvardsen
committed
Anders Markvardsen
committed
// Store log file line in Property
Anders Markvardsen
committed
if ( l_kind == LoadLog::number )
{
double readNumber;
ins >> readNumber;
Anders Markvardsen
committed
Anders Markvardsen
committed
l_PropertyDouble->addValue(dateAndTime, readNumber);
}
else
{
l_PropertyString->addValue(dateAndTime, aLine.erase(0,19));
}
Anders Markvardsen
committed
Anders Markvardsen
committed
} // end while
if ( l_JumpToNextLogFile )
{
continue; // jump to next log file
}
Anders Markvardsen
committed
Anders Markvardsen
committed
// store Property in Sample object
Anders Markvardsen
committed
if ( l_kind == LoadLog::number )
{
Anders Markvardsen
committed
sample.addLogData(l_PropertyDouble);
Anders Markvardsen
committed
}
else
{
Anders Markvardsen
committed
sample.addLogData(l_PropertyString);
Anders Markvardsen
committed
}
Anders Markvardsen
committed
inLogFile.close();
} // end for
// operation was a success and ended normally
Dickon Champion
committed
return;
Anders Markvardsen
committed
}
/** Finalisation method. Does nothing at present.
Dickon Champion
committed
*
Anders Markvardsen
committed
*/
Dickon Champion
committed
void LoadLog::final()
Anders Markvardsen
committed
{
}
/** Takes as input a string and try to determine what type it is.
Anders Markvardsen
committed
* @param s string to be classified
Anders Markvardsen
committed
* @return A enum kind which tells what type the string is
*/
LoadLog::kind LoadLog::classify(const std::string& s)
{
using std::string;
const string lower("abcdefghijklmnopqrstuvwxyz");
const string upper("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
const string letters = lower + upper + '_';
if (s.empty())
return LoadLog::empty;
if (letters.find_first_of(s) != string::npos)
return LoadLog::string;
else
return LoadLog::number;
}
/// change each element of the string to lower case
Anders Markvardsen
committed
std::string LoadLog::stringToLower(std::string strToConvert)
{
for(unsigned int i=0;i<strToConvert.length();i++)
{
strToConvert[i] = tolower(strToConvert[i]);
}
return strToConvert; //return the converted string
}
/// looks whether filename has the .txt extension and contain a '_'
Anders Markvardsen
committed
bool LoadLog::isLogFile(const std::string& filenamePart)
{
if ( stringToLower(filenamePart).find(".txt") != std::string::npos && filenamePart.find("_") != std::string::npos )
return true;
else
return false;
}
/// check if first 19 characters of a string is data-time string according to yyyy-mm-ddThh:mm:ss
bool LoadLog::isDateTimeString(const std::string& str)
{
if ( str.size() >= 19 )
if ( str.compare(4,1,"-") == 0 && str.compare(7,1,"-") == 0 && str.compare(13,1,":") == 0
&& str.compare(16,1,":") == 0 && str.compare(10,1,"T") == 0 )
return true;
return false;
}
Anders Markvardsen
committed
} // namespace DataHandling
} // namespace Mantid