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"
Gigg, Martyn Anthony
committed
#include "MantidAPI/AlgorithmManager.h"
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
//--------------------------------------------------------------------------
// Public methods
//--------------------------------------------------------------------------
Gigg, Martyn Anthony
committed
/// Default constructor
Gigg, Martyn Anthony
committed
Load::Load() : IDataFileChecker(), m_loaderProps()
Gigg, Martyn Anthony
committed
{
}
/**
Gigg, Martyn Anthony
committed
* Override setPropertyValue
* @param name The name of the property
* @param value The value of the property as a string
*/
void Load::setPropertyValue(const std::string &name, const std::string &value)
{
IDataFileChecker::setPropertyValue(name, value);
if( name == "Filename" )
{
IAlgorithm_sptr loader = getFileLoader(getPropertyValue(name));
declareLoaderProperties(loader);
}
}
//--------------------------------------------------------------------------
// Private methods
//--------------------------------------------------------------------------
/**
* 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;
}
Gigg, Martyn Anthony
committed
/**
* Get a shared pointer to the load algorithm with highest preference for loading
* @param filePath :: path of the file
* @returns A shared pointer to the unmanaged algorithm
*/
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
}
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
}
Gigg, Martyn Anthony
committed
setPropertyValue("LoaderName", winningLoader->name());
winningLoader->initialize();
Gigg, Martyn Anthony
committed
return winningLoader;
}
Gigg, Martyn Anthony
committed
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/**
* Declare any additional properties of the concrete loader here
* @param loader A pointer to the concrete loader
*/
void Load::declareLoaderProperties(const IAlgorithm_sptr loader)
{
if( !m_loaderProps.empty() )
{
std::list<std::string>::const_iterator cend = m_loaderProps.end();
for( std::list<std::string>::const_iterator citr = m_loaderProps.begin();
citr != cend; ++citr )
{
this->removeProperty(*citr);
}
m_loaderProps.clear();
}
const std::vector<Property*> &loaderProps = loader->getProperties();
size_t numProps(loaderProps.size());
for (size_t i = 0; i < numProps; ++i)
{
Property* loadProp = loaderProps[i];
try
{
declareProperty(loadProp->clone(), loadProp->documentation());
}
catch(Exception::ExistsError&)
{
// Already exists as a static property
continue;
}
// Save just in case a this function is called again so that we
// can remove the dynamically generated properties
m_loaderProps.push_back(loadProp->name());
}
}
/// Initialisation method.
void Load::init()
{
std::vector<std::string> exts;
exts.push_back(".raw");
exts.push_back(".s*");
exts.push_back(".add");
Sofia Antony
committed
Gigg, Martyn Anthony
committed
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
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");
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).");
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.");
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)");
declareProperty("LoaderName", std::string(""), "A string containing the name of the concrete loader used",
Direction::Output);
}
/**
* Executes the algorithm.
Gigg, Martyn Anthony
committed
*/
Gigg, Martyn Anthony
committed
void Load::exec()
Gigg, Martyn Anthony
committed
const std::string loaderName = getPropertyValue("LoaderName");
if( loaderName.empty() )
{
throw std::invalid_argument("Cannot find loader, LoaderName property has not been set.");
}
IAlgorithm_sptr loader = createLoader(loaderName);
g_log.information() << "Using " << loaderName << " version " << loader->version() << ".\n";
// Get the list of properties for the Load algorithm
std::vector<Kernel::Property*> props = this->getProperties();
///get the list properties for the concrete loader load algorithm
std::vector<Kernel::Property*> loader_props = loader->getProperties();
//loop through the properties of this algorithm
std::vector<Kernel::Property*>::iterator itr;
for (itr = props.begin(); itr != props.end(); ++itr)
{
const std::string propName = (*itr)->name();
if( loader->existsProperty(propName) )
{
loader->setPropertyValue(propName, getPropertyValue(propName));
}
}
Sofia Antony
committed
Gigg, Martyn Anthony
committed
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
// Execute the concrete loader
loader->execute();
// Set the workspace. Deals with possible multiple periods
setOutputWorkspace(loader);
}
/**
* Create the concrete instance use for the actual loading.
* @param name :: The name of the loader to instantiate
* @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 logging :: Set to false to disable logging from the child algorithm
*/
API::IAlgorithm_sptr Load::createLoader(const std::string & name, const double startProgress,
const double endProgress, const bool logging) const
{
IAlgorithm_sptr loader = AlgorithmManager::Instance().createUnmanaged(name);
loader->initialize();
if( !loader )
{
throw std::runtime_error("Cannot create loader for \"" + getPropertyValue("Filename") + "\"");
}
//Set as a child so that we are in control of output storage
loader->setChild(true);
loader->setLogging(logging);
Sofia Antony
committed
// If output workspaces are nameless, give them a temporary name to satisfy validator
Gigg, Martyn Anthony
committed
const std::vector< Property*> &props = loader->getProperties();
Sofia Antony
committed
for (unsigned int i = 0; i < props.size(); ++i)
{
Gigg, Martyn Anthony
committed
if (props[i]->direction() == Direction::Output &&
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
loader->addObserver(m_progressObserver);
loader->setChildStartProgress(startProgress);
loader->setChildEndProgress(endProgress);
Sofia Antony
committed
}
Gigg, Martyn Anthony
committed
return loader;
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
}
}
} // namespace DataHandling
} // namespace Mantid