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)
{
}
/**
* 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
*/
bool Load::quickFileCheck(const std::string& filePath,size_t nread,const file_header& header)
{
(void)filePath; (void)nread; (void)header;
return false;
}
/**
* File check by looking at the structure of the data file
* @param filePath The full file path
* @returns -1
*/
int Load::fileCheck(const std::string& filePath)
{
(void)filePath;
return -1;
}
/// Initialisation method.
void Load::init()
{
Sofia Antony
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");
Sofia Antony
committed
declareProperty(new FileProperty("Filename", "", FileProperty::Load, exts),
"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),
"The name of the workspace that will be created, filled with the\n"
"read-in data and stored in the Analysis Data Service.");
Gigg, Martyn Anthony
committed
declareProperty("FindLoader", false, "If true the algorithm will only be run as\n"
"far as is necessary to discover the concrete Load algorithm to use");
declareProperty("LoaderName", std::string(""), "A string containing the name of the concrete loader used",
Direction::Output);
Gigg, Martyn Anthony
committed
namespace
{
Gigg, Martyn Anthony
committed
//@cond
Gigg, Martyn Anthony
committed
/**
* Checks this property exists in the list of algorithm properties.
*/
struct hasProperty
{
/** constructor which takes 1 arguement.
*@param name :: name of the property
Gigg, Martyn Anthony
committed
*/
Gigg, Martyn Anthony
committed
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
//@endcond
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 "
<< loader->name() << " and it version is "
<< loader->version() <<std::endl;
double startProgress(0.0), endProgress(1.0);
initialiseLoadSubAlgorithm(loader,startProgress,endProgress,true,-1);
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();
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())
{
Gigg, Martyn Anthony
committed
loader->setPropertyValue((*prop)->name(),getPropertyValue((*prop)->name()));
}
Sofia Antony
committed
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
Janik Zikovsky
committed
*@param filePath :: path of the file
Sofia Antony
committed
*@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
Sofia Antony
committed
* be used to determine the type of the file
*/
Gigg, Martyn Anthony
committed
FILE* fp = fopen(filePath.c_str(), "rb");
if (fp == NULL)
{
throw Kernel::Exception::FileError("Unable to open the file:", filePath);
}
//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)
{
fclose(fp);
}
Sofia Antony
committed
Gigg, Martyn Anthony
committed
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
if (fclose(fp) != 0)
{
throw std::runtime_error("Error while closing file \"" + filePath + "\"");
}
// 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;
++citr )
{
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;
}
}
}
Sofia Antony
committed
Gigg, Martyn Anthony
committed
if( !winningLoader )
{
throw std::runtime_error("Cannot find a loader for \"" + filePath + "\"");
}
return winningLoader;
}
Sofia Antony
committed
Gigg, Martyn Anthony
committed
/** This method set the algorithm as a child algorithm.
* @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.
*/
void Load::initialiseLoadSubAlgorithm(API::IAlgorithm_sptr alg,
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
}
Sofia Antony
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());
Sofia Antony
committed
Gigg, Martyn Anthony
committed
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
}
Sofia Antony
committed
} // namespace DataHandling
} // namespace Mantid