Newer
Older
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidDataHandling/Load.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/FileProperty.h"
#include "MantidKernel/ArrayProperty.h"
#include "MantidDataObjects/Workspace2D.h"
Sofia Antony
committed
#include "MantidAPI/LoadAlgorithmFactory.h"
#include<algorithm>
namespace Mantid
{
namespace DataHandling
{
// Register the algorithm into the algorithm factory
Gigg, Martyn Anthony
committed
DECLARE_ALGORITHM(Load);
using namespace Kernel;
using namespace API;
Gigg, Martyn Anthony
committed
/// Default constructor
Load::Load() : IDataFileChecker(), m_header_buffer(NULL)
{
}
/**
Gigg, Martyn Anthony
committed
* Quick file always returns false here
* @param filePath File path
* @param nread Number of bytes read
* @param header_buffer A buffer containing the nread bytes
*/
Gigg, Martyn Anthony
committed
bool Load::quickFileCheck(const std::string& filePath,size_t nread,const file_header& header)
{
(void)filePath; (void)nread; (void)header;
return false;
}
/**
Gigg, Martyn Anthony
committed
* File check by looking at the structure of the data file
* @param filePath The full file path
* @returns -1
*/
Gigg, Martyn Anthony
committed
int Load::fileCheck(const std::string& filePath)
{
(void)filePath;
return -1;
}
/// Initialisation method.
void Load::init()
{
Gigg, Martyn Anthony
committed
std::vector<std::string> exts;
exts.push_back(".raw");
exts.push_back(".s*");
exts.push_back(".add");
exts.push_back(".nxs");
exts.push_back(".nx5");
exts.push_back(".xml");
exts.push_back(".n*");
exts.push_back(".dat");
exts.push_back(".txt");
exts.push_back(".csv");
exts.push_back(".spe");
Gigg, Martyn Anthony
committed
declareProperty(new FileProperty("Filename", "", FileProperty::Load, exts),
Gigg, Martyn Anthony
committed
"The name of the file to read, including its full or relative\n"
"path. (N.B. case sensitive if running on Linux).");
Gigg, Martyn Anthony
committed
declareProperty(new WorkspaceProperty<Workspace>("OutputWorkspace", "",Direction::Output, true),
Gigg, Martyn Anthony
committed
"The name of the workspace that will be created, filled with the\n"
"read-in data and stored in the Analysis Data Service.");
BoundedValidator<int> *mustBePositive = new BoundedValidator<int>();
mustBePositive->setLower(1);
declareProperty("SpectrumMin", 1, mustBePositive);
declareProperty("SpectrumMax", EMPTY_INT(), mustBePositive->clone());
declareProperty(new ArrayProperty<int>("SpectrumList"));
declareProperty("EntryNumber", 0,
"Load a particular entry, if supported by the file format (default: Load all entries)");
Gigg, Martyn Anthony
committed
declareProperty("FindLoader", false, "If true the algorithm will only be run as\n"
Gigg, Martyn Anthony
committed
"far as is necessary to discover the concrete Load algorithm to use");
Gigg, Martyn Anthony
committed
declareProperty("LoaderName", std::string(""), "A string containing the name of the concrete loader used",
Gigg, Martyn Anthony
committed
Direction::Output);
Gigg, Martyn Anthony
committed
namespace
{
Gigg, Martyn Anthony
committed
//@cond
Gigg, Martyn Anthony
committed
/**
Gigg, Martyn Anthony
committed
* Checks this property exists in the list of algorithm properties.
*/
Gigg, Martyn Anthony
committed
struct hasProperty
{
Gigg, Martyn Anthony
committed
/** constructor which takes 1 arguement.
*@param name :: name of the property
*/
hasProperty(const std::string name):m_name(name){}
/**This method comapres teh property name
*@param prop :: shared pointer to property
*@return true if the property exists in the list of properties.
*/
bool operator()(Mantid::Kernel::Property* prop)
{
std::string name=prop->name();
return (!name.compare(m_name));
}
/// name of teh property
std::string m_name;
Gigg, Martyn Anthony
committed
};
Gigg, Martyn Anthony
committed
//@endcond
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
/**
Gigg, Martyn Anthony
committed
* Executes the algorithm.
*/
void Load::exec()
{
std::string fileName = getPropertyValue("Filename");
std::string::size_type i = fileName.find_last_of('.');
std::string ext = fileName.substr(i+1);
std::transform(ext.begin(),ext.end(),ext.begin(),tolower);
Sofia Antony
committed
//get the shared pointer to the specialised load algorithm to execute
Gigg, Martyn Anthony
committed
API::IAlgorithm_sptr loader = getFileLoader(fileName);
if( !loader )
{
throw std::runtime_error("Cannot find a loader for \"" + fileName + "\"");
}
else
Gigg, Martyn Anthony
committed
setPropertyValue("LoaderName", loader->name());
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
bool findOnly = getProperty("FindLoader");
if( findOnly ) return;
Gigg, Martyn Anthony
committed
g_log.information()<<"The sub load algorithm created to execute is "
Gigg, Martyn Anthony
committed
<< loader->name() << " and it version is "
<< loader->version() <<std::endl;
Gigg, Martyn Anthony
committed
double startProgress(0.0), endProgress(1.0);
initialiseLoadSubAlgorithm(loader,startProgress,endProgress,true,-1);
Gigg, Martyn Anthony
committed
Sofia Antony
committed
//get the list of properties for this algorithm
std::vector<Kernel::Property*> props=getProperties();
///get the list properties for the sub load algorithm
Gigg, Martyn Anthony
committed
std::vector<Kernel::Property*>loader_props=loader->getProperties();
Gigg, Martyn Anthony
committed
Sofia Antony
committed
//loop through the properties of this algorithm
std::vector<Kernel::Property*>::iterator itr;
for (itr=props.begin();itr!=props.end();++itr)
{
Gigg, Martyn Anthony
committed
std::vector<Mantid::Kernel::Property*>::iterator prop;
//if the load sub algorithm has the same property then set it.
prop=std::find_if(loader_props.begin(),loader_props.end(),hasProperty((*itr)->name()));
if(prop!=loader_props.end())
{
loader->setPropertyValue((*prop)->name(),getPropertyValue((*prop)->name()));
}
Gigg, Martyn Anthony
committed
// Execute the concrete loader
loader->execute();
// Set the workspace. Deals with possible multiple periods
setOutputWorkspace(loader);
Gigg, Martyn Anthony
committed
/** Get a shared pointer to the load algorithm with highest preference for loading
Gigg, Martyn Anthony
committed
*@param filePath :: path of the file
*@return filePath - path of the file
*/
Gigg, Martyn Anthony
committed
API::IAlgorithm_sptr Load::getFileLoader(const std::string& filePath)
{
/* Open the file and read in the first bufferSize bytes - these will
Gigg, Martyn Anthony
committed
* be used to determine the type of the file
*/
Gigg, Martyn Anthony
committed
FILE* fp = fopen(filePath.c_str(), "rb");
if (fp == NULL)
{
Gigg, Martyn Anthony
committed
throw Kernel::Exception::FileError("Unable to open the file:", filePath);
Gigg, Martyn Anthony
committed
}
//unsigned char* header_buffer = header_buffer_union.c;
//unsigned char * header_buffer = IDataFileChecker::g_hdr_buf.get();
file_header header;
int 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 (nread == -1)
{
Gigg, Martyn Anthony
committed
fclose(fp);
Gigg, Martyn Anthony
committed
}
Sofia Antony
committed
Gigg, Martyn Anthony
committed
if (fclose(fp) != 0)
{
Gigg, Martyn Anthony
committed
throw std::runtime_error("Error while closing file \"" + filePath + "\"");
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
// 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::IAlgorithm_sptr winningLoader;
std::vector<std::string>::const_iterator cend = loaderNames.end();
for( std::vector<std::string>::const_iterator citr = loaderNames.begin(); citr != cend;
Gigg, Martyn Anthony
committed
++citr )
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
IDataFileChecker_sptr loader = API::LoadAlgorithmFactory::Instance().create(*citr);
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;
}
}
Gigg, Martyn Anthony
committed
}
Sofia Antony
committed
Gigg, Martyn Anthony
committed
if( !winningLoader )
{
Gigg, Martyn Anthony
committed
throw std::runtime_error("Cannot find a loader for \"" + filePath + "\"");
Gigg, Martyn Anthony
committed
}
return winningLoader;
}
Sofia Antony
committed
Gigg, Martyn Anthony
committed
/** This method set the algorithm as a child algorithm.
Gigg, Martyn Anthony
committed
* @param alg :: The shared pointer to a algorithm
* @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 enableLogging :: Set to false to disable logging from the child algorithm
* @param version :: The version of the child algorithm to create.
* By default gives the latest version.
*/
Gigg, Martyn Anthony
committed
void Load::initialiseLoadSubAlgorithm(API::IAlgorithm_sptr alg,
Gigg, Martyn Anthony
committed
const double startProgress, const double endProgress,
const bool enableLogging, const int& version)
(void) version; // Avoid compiler warning.
Gigg, Martyn Anthony
committed
//Set as a child so that we are in control of output storage
Sofia Antony
committed
alg->initialize();
alg->setChild(true);
alg->setLogging(enableLogging);
// If output workspaces are nameless, give them a temporary name to satisfy validator
const std::vector< Property*> &props = alg->getProperties();
for (unsigned int i = 0; i < props.size(); ++i)
{
Gigg, Martyn Anthony
committed
if (props[i]->direction() == 1 && dynamic_cast<IWorkspaceProperty*>(props[i]) )
{
if ( props[i]->value().empty() ) props[i]->setValue("LoadChildWorkspace");
}
Sofia Antony
committed
}
Gigg, Martyn Anthony
committed
if (startProgress >= 0. && endProgress > startProgress && endProgress <= 1.)
Sofia Antony
committed
{
Gigg, Martyn Anthony
committed
alg->addObserver(m_progressObserver);
alg->setChildStartProgress(startProgress);
alg->setChildEndProgress(endProgress);
Sofia Antony
committed
}
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
* Set the output workspace(s) if the load's return workspace
* has type API::Workspace
*@param load :: shared pointer to load algorithm
*/
void Load::setOutputWorkspace(API::IAlgorithm_sptr& load)
{
Sofia Antony
committed
try
Gigg, Martyn Anthony
committed
Workspace_sptr ws = load->getProperty("OutputWorkspace");
WorkspaceGroup_sptr wsg = boost::dynamic_pointer_cast<WorkspaceGroup>(ws);
if (wsg)
{
setProperty("OutputWorkspace",ws);
std::vector<std::string> names = wsg->getNames();
for(size_t i = 0; i < names.size(); ++i)
{
std::ostringstream propName;
propName << "OutputWorkspace_" << (i+1);
DataObjects::Workspace2D_sptr memberwsws1 = load->getProperty(propName.str());
std::string memberwsName = load->getPropertyValue(propName.str());
declareProperty(new WorkspaceProperty<>(propName.str(),memberwsName,Direction::Output));
setProperty(propName.str(),boost::dynamic_pointer_cast<MatrixWorkspace>(memberwsws1));
}
}
else
{
setProperty("OutputWorkspace",ws);
}
Sofia Antony
committed
catch(std::runtime_error&)
{
Gigg, Martyn Anthony
committed
MatrixWorkspace_sptr mws=load->getProperty("OutputWorkspace");
setProperty("OutputWorkspace",boost::dynamic_pointer_cast<Workspace>(mws));
Sofia Antony
committed
}
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
} // namespace DataHandling
} // namespace Mantid