Newer
Older
Janik Zikovsky
committed
/*WIKI*
The Load algorithm is a more intelligent algorithm than most other load algorithms. When passed a filename it attempts to search the existing load [[:Category:Algorithms|algorithms]] and find the most appropriate to load the given file. The specific load algorithm is then run as a child algorithm with the exception that it logs messages to the Mantid logger.
==== Specific Load Algorithm Properties ====
Each specific loader will have its own properties that are appropriate to it: SpectrumMin and SpectrumMax for ISIS RAW/NeXuS, FilterByTof_Min and FilterByTof_Max for Event data. The Load algorithm cannot know about these properties until it has been told the filename and found the correct loader. Once this has happened the properties of the specific Load algorithm are redeclared on to that copy of Load.
== Usage ==
==== Python ====
Given the variable number and types of possible arguments that Load can take, its simple Python function cannot just list the properties as arguments like the others do. Instead the Python function <code>Load</code> can handle any number of arguments. The OutputWorkspace and Filename arguments are the exceptions in that they are always checked for. A snippet regarding usage from the <code>help(Load)</code> is shown below
<div style="border:1pt dashed blue; background:#f9f9f9;padding: 1em 0;">
<source lang="python">
# Simple usage, ISIS NeXus file
Load('INSTR00001000.nxs', 'run_ws')
# ISIS NeXus with SpectrumMin and SpectrumMax = 1
Load('INSTR00001000.nxs', 'run_ws', SpectrumMin=1,SpectrumMax=1)
# SNS Event NeXus with precount on
Load('INSTR_1000_event.nxs', 'event_ws', Precount=True)
# A mix of keyword and non-keyword is also possible
Load('event_ws', Filename='INSTR_1000_event.nxs',Precount=True)
</source></div>
*WIKI*/
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidDataHandling/Load.h"
#include "MantidAPI/MultipleFileProperty.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/IEventWorkspace.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/IWorkspaceProperty.h"
Sofia Antony
committed
#include "MantidAPI/LoadAlgorithmFactory.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/AlgorithmManager.h"
Gigg, Martyn Anthony
committed
#include "MantidKernel/FacilityInfo.h"
#include <Poco/Path.h>
#include <functional>
#include <numeric>
#include <set>
Janik Zikovsky
committed
#include "MantidAPI/IMDEventWorkspace.h"
namespace
{
/**
* Convenience function that returns true if the passed vector of vector of strings
* contains a single string, false if contains more than that (or zero).
*
* @param fileNames :: a vector of vectors of file name strings.
*
* @returns true if there is exactly one string, else false.
*/
bool isSingleFile(const std::vector<std::vector<std::string> > & fileNames)
{
if(fileNames.size() == 1)
{
std::vector<std::vector<std::string> >::const_iterator first = fileNames.begin();
if(first->size() == 1)
return true;
}
return false;
}
/**
* Helper function that takes a vector of runs, and generates a suggested workspace name.
* This will likely need to be improved and may have to include instrument name, etc.
*
* @param runs :: a vector of run numbers.
*
* @returns a string containing a suggested ws name based on the given run numbers.
std::string generateWsNameFromRuns(std::vector<unsigned int> runs)
{
std::string wsName("");
for(size_t i = 0; i < runs.size(); ++i)
{
if(!wsName.empty())
wsName += "_";
wsName += boost::lexical_cast<std::string>(runs[i]);
}
return wsName;
}
/**
* Helper function that takes a vector of filenames, and generates a suggested workspace name.
*
* @param filenames :: a vector of filenames.
*
* @returns a string containing a suggested ws name based on the given file names.
*/
std::string generateWsNameFromFileNames(std::vector<std::string> filenames)
{
std::string wsName("");
for(size_t i = 0; i < filenames.size(); ++i)
{
if(!wsName.empty())
wsName += "_";
Poco::Path path(filenames[i]);
wsName += path.getBaseName();
}
return wsName;
}
/**
* Helper function that takes a vector of vectors of items and flattens it into
* a single vector of items.
*/
std::vector<std::string> flattenVecOfVec(std::vector<std::vector<std::string> > vecOfVec)
std::vector<std::string> flattenedVec;
std::vector<std::vector<std::string> >::const_iterator it = vecOfVec.begin();
for(; it != vecOfVec.end(); ++it)
{
flattenedVec.insert(
flattenedVec.end(),
it->begin(), it->end());
}
return flattenedVec;
}
namespace Mantid
{
namespace DataHandling
{
// Register the algorithm into the algorithm factory
Gigg, Martyn Anthony
committed
DECLARE_ALGORITHM(Load);
Janik Zikovsky
committed
/// Sets documentation strings for this algorithm
void Load::initDocs()
{
this->setWikiSummary("Attempts to load a given file by finding an appropriate Load algorithm. ");
this->setOptionalMessage("Attempts to load a given file by finding an appropriate Load algorithm.");
}
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_baseProps()
Gigg, Martyn Anthony
committed
{
}
Russell Taylor
committed
/** Override setPropertyValue to catch if filename is being set, as this may mean
* a change of concrete loader. If it's any other property, just forward the call.
* @param name The name of the property
* @param value The value of the property as a string
*/
Gigg, Martyn Anthony
committed
void Load::setPropertyValue(const std::string &name, const std::string &value)
{
Russell Taylor
committed
// Call base class method in all cases.
// For a filename property is deals with resolving the full path.
IDataFileChecker::setPropertyValue(name, value);
std::string NAME(name);
std::transform(name.begin(),name.end(),NAME.begin(),toupper);
if( NAME == "FILENAME" )
Gigg, Martyn Anthony
committed
{
// Get back full path before passing to getFileLoader method, and also
// find out whether this is a multi file load.
std::vector<std::string> fileNames = flattenVecOfVec(getProperty("Filename"));
// If it's a single file load, then it's fine to change loader.
if(fileNames.size() == 1)
{
IDataFileChecker_sptr loader = getFileLoader(getPropertyValue(name));
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
218
219
assert(loader); // (getFileLoader should throw if no loader is found.)
declareLoaderProperties(loader);
}
// Else we've got multiple files, and must enforce the rule that only one type of loader is allowed.
// Allowing more than one would mean that "extra" properties defined by the class user (for example
// "LoadLogFiles") are potentially ambiguous.
else if(fileNames.size() > 1)
{
IDataFileChecker_sptr loader = getFileLoader(fileNames[0]);
// If the first file has a loader ...
if( loader )
{
// ... store it's name and version and check that all other files have loaders with the same name and version.
std::string name = loader->name();
int version = loader->version();
for(size_t i = 1; i < fileNames.size(); ++i)
{
loader = getFileLoader(fileNames[i]);
if( name != loader->name() || version != loader->version() )
throw std::runtime_error("Cannot load multiple files when more than one Loader is needed.");
}
}
assert(loader); // (getFileLoader should throw if no loader is found.)
declareLoaderProperties(loader);
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
//--------------------------------------------------------------------------
// Private methods
//--------------------------------------------------------------------------
/**
Gigg, Martyn Anthony
committed
* Quick file always returns false here
* @param filePath :: File path
* @param nread :: Number of bytes read
* @param header :: A buffer containing the nread bytes
Gigg, Martyn Anthony
committed
*/
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
Gigg, Martyn Anthony
committed
* @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::IDataFileChecker_sptr Load::getFileLoader(const std::string& filePath)
Gigg, Martyn Anthony
committed
{
/* 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;
size_t nread = fread(&header,sizeof(unsigned char), g_hdr_bytes, fp);
Gigg, Martyn Anthony
committed
// Ensure the character string is null terminated.
header.full_hdr[g_hdr_bytes] = '\0';
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);
Gigg, Martyn Anthony
committed
API::IDataFileChecker_sptr winningLoader;
Gigg, Martyn Anthony
committed
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);
Janik Zikovsky
committed
try
Gigg, Martyn Anthony
committed
{
Janik Zikovsky
committed
if( loader->quickFileCheck(filePath, nread, header) )
Gigg, Martyn Anthony
committed
{
Janik Zikovsky
committed
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
}
}
Janik Zikovsky
committed
catch (std::exception & e)
{
g_log.debug() << "Error running file check of " << loader->name() << std::endl;
g_log.debug() << e.what() << std::endl;
}
Gigg, Martyn Anthony
committed
}
Sofia Antony
committed
Gigg, Martyn Anthony
committed
if( !winningLoader )
{
Gigg, Martyn Anthony
committed
// Clear what may have been here previously
setPropertyValue("LoaderName", "");
Gigg, Martyn Anthony
committed
throw std::runtime_error("Cannot find an algorithm that is able to load \"" + filePath + "\".\n"
Russell Taylor
committed
"Check that the file is a supported type.");
Gigg, Martyn Anthony
committed
}
Janik Zikovsky
committed
g_log.debug() << "Winning loader is " << winningLoader->name() << std::endl;
Gigg, Martyn Anthony
committed
setPropertyValue("LoaderName", winningLoader->name());
winningLoader->initialize();
Gigg, Martyn Anthony
committed
setUpLoader(winningLoader);
Gigg, Martyn Anthony
committed
return winningLoader;
}
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
/**
Gigg, Martyn Anthony
committed
* Declare any additional properties of the concrete loader here
* @param loader A pointer to the concrete loader
*/
Gigg, Martyn Anthony
committed
void Load::declareLoaderProperties(const IDataFileChecker_sptr loader)
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
// If we have switch loaders then the concrete loader will have different properties
// so take care of ensuring Load has the correct ones
Gigg, Martyn Anthony
committed
const std::vector<Property*> existingProps = this->getProperties();
for( size_t i = 0; i < existingProps.size(); ++i )
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
const std::string name = existingProps[i]->name();
Russell Taylor
committed
// Wipe all properties except the Load native ones
if( m_baseProps.find(name) == m_baseProps.end() )
Gigg, Martyn Anthony
committed
{
this->removeProperty(name, false);
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
}
const std::vector<Property*> &loaderProps = loader->getProperties();
Gigg, Martyn Anthony
committed
const std::string filePropName(loader->filePropertyName());
Gigg, Martyn Anthony
committed
size_t numProps(loaderProps.size());
for (size_t i = 0; i < numProps; ++i)
{
Gigg, Martyn Anthony
committed
Property* loadProp = loaderProps[i];
if( loadProp->name() == filePropName ) continue;
try
{
Property * propClone = loadProp->clone();
propClone->deleteSettings(); //Get rid of special settings because it does not work in custom GUI.
declareProperty(propClone, loadProp->documentation());
Gigg, Martyn Anthony
committed
}
catch(Exception::ExistsError&)
{
// Already exists as a static property
continue;
}
Gigg, Martyn Anthony
committed
}
}
/// Initialisation method.
void Load::init()
{
Gigg, Martyn Anthony
committed
// Take extensions first from Facility object
const FacilityInfo & defaultFacility = Mantid::Kernel::ConfigService::Instance().getFacility();
Gigg, Martyn Anthony
committed
std::vector<std::string> exts = defaultFacility.extensions();
// Add in some other known extensions
Gigg, Martyn Anthony
committed
exts.push_back(".xml");
exts.push_back(".dat");
exts.push_back(".txt");
exts.push_back(".csv");
exts.push_back(".spe");
exts.push_back(".nxspe");
Gigg, Martyn Anthony
committed
declareProperty(new MultipleFileProperty("Filename", exts),
"The name of the file(s) to read, including the full or relative\n"
"path. (N.B. case sensitive if running on Linux). Multiple runs\n"
"can be loaded and added together, e.g. INST10,11+12,13.ext");
Gigg, Martyn Anthony
committed
declareProperty(new WorkspaceProperty<Workspace>("OutputWorkspace", "",Direction::Output),
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.");
Gigg, Martyn Anthony
committed
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
// Save for later what the base Load properties are
Gigg, Martyn Anthony
committed
const std::vector<Property*> & props = this->getProperties();
for( size_t i = 0; i < this->propertyCount(); ++i )
{
Gigg, Martyn Anthony
committed
m_baseProps.insert(props[i]->name());
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
}
/**
* Executes the algorithm.
*/
Gigg, Martyn Anthony
committed
void Load::exec()
{
std::vector<std::vector<std::string> > fileNames = getProperty("Filename");
if(isSingleFile(fileNames))
{
// This is essentially just the same code that was called before multiple files were supported.
loadSingleFile();
}
else
{
// Code that supports multiple file loading.
loadMultipleFiles();
}
}
void Load::loadSingleFile()
Gigg, Martyn Anthony
committed
std::string loaderName = getPropertyValue("LoaderName");
Gigg, Martyn Anthony
committed
if( loaderName.empty() )
{
Roman Tolchenov
committed
m_loader = getFileLoader(getPropertyValue("Filename"));
loaderName = m_loader->name();
Russell Taylor
committed
setPropertyValue("LoaderName",loaderName);
Gigg, Martyn Anthony
committed
}
else
{
Roman Tolchenov
committed
m_loader = createLoader(loaderName,0,1);
Gigg, Martyn Anthony
committed
}
Roman Tolchenov
committed
g_log.information() << "Using " << loaderName << " version " << m_loader->version() << ".\n";
Gigg, Martyn Anthony
committed
///get the list properties for the concrete loader load algorithm
Roman Tolchenov
committed
const std::vector<Kernel::Property*> & loader_props = m_loader->getProperties();
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
// Loop through and set the properties on the sub algorithm
std::vector<Kernel::Property*>::const_iterator itr;
for (itr = loader_props.begin(); itr != loader_props.end(); ++itr)
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
const std::string propName = (*itr)->name();
if( this->existsProperty(propName) )
{
Roman Tolchenov
committed
m_loader->setPropertyValue(propName, getPropertyValue(propName));
Gigg, Martyn Anthony
committed
}
Roman Tolchenov
committed
else if( propName == m_loader->filePropertyName() )
Gigg, Martyn Anthony
committed
{
Roman Tolchenov
committed
m_loader->setPropertyValue(propName, getPropertyValue("Filename"));
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
}
Sofia Antony
committed
Gigg, Martyn Anthony
committed
// Execute the concrete loader
Roman Tolchenov
committed
m_loader->execute();
Gigg, Martyn Anthony
committed
// Set the workspace. Deals with possible multiple periods
Roman Tolchenov
committed
setOutputWorkspace(m_loader);
Gigg, Martyn Anthony
committed
}
void Load::loadMultipleFiles()
{
MultipleFileProperty * multiFileProp = dynamic_cast<MultipleFileProperty*>(getPointerToProperty("Filename"));
const std::vector<std::vector<std::string> > values = getProperty("Filename");
std::string outputWsName = getProperty("OutputWorkspace");
// Generate ws names for the files to be loaded.
const std::vector<std::vector<unsigned int> > runs = multiFileProp->getRuns();
std::vector<std::string> wsNames;
wsNames.resize(values.size());
// If we successfully parsed run numbers (in the cases where we were given a string of "inst[runs].raw") then
// we can use them to generate the ws names.
if( ! runs.empty() )
{
std::transform(
runs.begin(), runs.end(),
wsNames.begin(),
generateWsNameFromRuns);
}
// Else if no runs were returned then the string we were given was of the form "inst1.raw, inst2.raw, ...".
// It would not make sense to generate ws names from just the run numbers in this case, since we could have
// two files with the same run number with but with different instruments.
else
{
std::transform(
values.begin(), values.end(),
wsNames.begin(),
generateWsNameFromFileNames);
std::vector<std::string> loadedWsNames;
std::vector<std::vector<std::string> >::const_iterator values_it = values.begin();
std::vector<std::string >::const_iterator wsNames_it = wsNames.begin();
// Cycle through the fileNames and wsNames.
for(; values_it != values.end(); ++values_it, ++wsNames_it)
std::vector<std::string> fileNames = *values_it;
std::string wsName = *wsNames_it;
// If there is only one filename, then just load it to the given wsName.
loadFileToHiddenWs(fileNames.at(0), wsName);
loadedWsNames.push_back("__" + wsName);
}
// Else there is more than one filename. Load them all, sum them, and rename the
// result to the given wsName.
else
{
// Load all files and place the resulting workspaces in a vector.
std::vector<Workspace_sptr> loadedWs;
std::vector<std::string>::const_iterator vIt = fileNames.begin();
for(; vIt != fileNames.end(); ++vIt)
Workspace_sptr ws = loadFileToHiddenWs(*vIt, (*vIt) + "_temp");
loadedWs.push_back(ws);
}
// Add all workspaces together, sticking the result in sum.
Workspace_sptr sum;
for(
size_t i = 1; // Start at second workspace in list.
i < loadedWs.size();
i++)
{
Workspace_sptr firstWsToAdd;
// If there have been no workspaces added yet, then the first workspace to add
// is the first workspace in the list.
if(sum == Workspace_sptr())
firstWsToAdd = loadedWs.at(i-1);
// Else the first workspace to add is "sum" itself.
else
firstWsToAdd = sum;
Workspace_sptr secondWsToAdd = loadedWs.at(i);
sum = plusWs(firstWsToAdd, secondWsToAdd);
}
// Delete all of the temporarily loaded workspaces except the first one, so that we are left only
// with sum at this point.
for(size_t i = 1; i < fileNames.size(); i++)
{
deleteWs("__" + fileNames.at(i) + "_temp");
}
// Rename the sum and add to the list of loaded workspace names.
renameWs(sum->name(), "__" + wsName);
loadedWsNames.push_back("__" + wsName);
}
}
// If we only have one loaded ws, set it as the output.
if(loadedWsNames.size() == 1)
renameWs(loadedWsNames.at(0), outputWsName);
setProperty("OutputWorkspace", AnalysisDataService::Instance().retrieve(outputWsName.c_str()));
}
// Else we have multiple loaded workspaces - group them and set the group as output.
else
{
Mantid::API::IAlgorithm_sptr groupingAlg = this->createSubAlgorithm("GroupWorkspaces",0, 0, true, 1);
groupingAlg->setAlwaysStoreInADS(true);
groupingAlg->setProperty("InputWorkspaces",loadedWsNames);
groupingAlg->setProperty("OutputWorkspace",outputWsName.c_str());
groupingAlg->execute();
auto outws = AnalysisDataService::Instance().retrieve(outputWsName.c_str());
unhideWs(outputWsName);
setProperty("OutputWorkspace", outws);
Gigg, Martyn Anthony
committed
/**
Gigg, Martyn Anthony
committed
* 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
*/
Gigg, Martyn Anthony
committed
API::IDataFileChecker_sptr Load::createLoader(const std::string & name, const double startProgress,
Gigg, Martyn Anthony
committed
const double endProgress, const bool logging) const
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
IDataFileChecker_sptr loader = boost::static_pointer_cast<IDataFileChecker>(
Gigg, Martyn Anthony
committed
API::AlgorithmManager::Instance().createUnmanaged(name));
Gigg, Martyn Anthony
committed
loader->initialize();
if( !loader )
{
Gigg, Martyn Anthony
committed
throw std::runtime_error("Cannot create loader for \"" + getPropertyValue("Filename") + "\"");
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
setUpLoader(loader,startProgress,endProgress, logging);
return loader;
}
Gigg, Martyn Anthony
committed
Gigg, Martyn Anthony
committed
/**
* Set the loader option for use as a sub algorithm.
* @param loader :: Concrete loader
* @param startProgress :: The start progress fraction
* @param endProgress :: The end progress fraction
* @param logging:: If true, enable logging
*/
void Load::setUpLoader(API::IDataFileChecker_sptr loader, const double startProgress,
const double endProgress, const bool logging) const
{
Gigg, Martyn Anthony
committed
//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);
setChildStartProgress(startProgress);
setChildEndProgress(endProgress);
Sofia Antony
committed
}
Gigg, Martyn Anthony
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 loader :: Shared pointer to load algorithm
*/
Gigg, Martyn Anthony
committed
void Load::setOutputWorkspace(const API::IDataFileChecker_sptr loader)
Gigg, Martyn Anthony
committed
// Go through each OutputWorkspace property and check whether we need to make a counterpart here
const std::vector<Property*> loaderProps = loader->getProperties();
const size_t count = loader->propertyCount();
for( size_t i = 0; i < count; ++i )
Gigg, Martyn Anthony
committed
Property *prop = loaderProps[i];
if( dynamic_cast<IWorkspaceProperty*>(prop) && prop->direction() == Direction::Output )
{
const std::string & name = prop->name();
if( !this->existsProperty(name) )
{
declareProperty(new WorkspaceProperty<Workspace>(name, loader->getPropertyValue(name),
Direction::Output));
}
Workspace_sptr wkspace = getOutputWorkspace(name, loader);
setProperty(name, wkspace);
}
Sofia Antony
committed
}
Gigg, Martyn Anthony
committed
* Return an output workspace property dealing with the lack of connection between of
* WorkspaceProperty types
* @param propName :: The name of the property
* @param loader :: The loader algorithm
* @returns A pointer to the OutputWorkspace property of the sub algorithm
*/
Gigg, Martyn Anthony
committed
API::Workspace_sptr Load::getOutputWorkspace(const std::string & propName,
Gigg, Martyn Anthony
committed
const API::IDataFileChecker_sptr loader) const
Gigg, Martyn Anthony
committed
// @todo Need to try and find a better way using the getValue methods
try
{
Gigg, Martyn Anthony
committed
return loader->getProperty(propName);
}
catch(std::runtime_error&)
Janik Zikovsky
committed
{ }
// Try a MatrixWorkspace
try
{
Gigg, Martyn Anthony
committed
MatrixWorkspace_sptr childWS = loader->getProperty(propName);
return childWS;
}
catch(std::runtime_error&)
Janik Zikovsky
committed
{ }
Gigg, Martyn Anthony
committed
// EventWorkspace
try
{
Gigg, Martyn Anthony
committed
IEventWorkspace_sptr childWS = loader->getProperty(propName);
return childWS;
Gigg, Martyn Anthony
committed
}
catch(std::runtime_error&)
Janik Zikovsky
committed
{ }
// IMDEventWorkspace
try
Gigg, Martyn Anthony
committed
{
Janik Zikovsky
committed
IMDEventWorkspace_sptr childWS = loader->getProperty(propName);
return childWS;
Gigg, Martyn Anthony
committed
}
Janik Zikovsky
committed
catch(std::runtime_error&)
{ }
// Just workspace?
try
{
Workspace_sptr childWS = loader->getProperty(propName);
return childWS;
}
catch(std::runtime_error&)
{ }
g_log.debug() << "Workspace property " << propName << " did not return to MatrixWorkspace, EventWorkspace, or IMDEventWorkspace." << std::endl;
return Workspace_sptr();
}
Roman Tolchenov
committed
/*
* Overrides the default cancel() method. Calls cancel() on the actual loader.
*/
Roman Tolchenov
committed
void Load::cancel()const
{
if (m_loader)
{
m_loader->cancel();
}
}
/**
* Loads a file into a *hidden* workspace.
*
* @param fileName :: file name to load.
* @param wsName :: workspace name, which will be prefixed by a "__"
*
* @returns a pointer to the loaded workspace
*/
API::Workspace_sptr Load::loadFileToHiddenWs(
const std::string & fileName,
const std::string & wsName)
{
Mantid::API::IAlgorithm_sptr loadAlg = createSubAlgorithm("Load", 1);
// Here, as a workaround for groupworkspaces who's members have names but no
// accompanying entries in the ADS, we set the sub algo to setAlwaysStoreInADS.
//loadAlg->setChild(false);
loadAlg->setAlwaysStoreInADS(true);
// Get the list properties for the concrete loader load algorithm
const std::vector<Kernel::Property*> & props = getProperties();
// Loop through and set the properties on the sub algorithm
std::vector<Kernel::Property*>::const_iterator itr;
for (itr = props.begin(); itr != props.end(); ++itr)
const std::string propName = (*itr)->name();
if( this->existsProperty(propName) )
{
if(propName == "Filename")
{
loadAlg->setPropertyValue("Filename",fileName);
}
else if(propName == "OutputWorkspace")
{
loadAlg->setPropertyValue("OutputWorkspace","__" + wsName);
}
else
{
loadAlg->setPropertyValue(propName, getPropertyValue(propName));
}
}
}
loadAlg->executeAsSubAlg();
return AnalysisDataService::Instance().retrieve("__" + wsName);
}
/**
* Plus two workspaces together, "in place".
*
* @param ws1 :: The first workspace.
* @param ws2 :: The second workspace.
*
* @returns a pointer to the result (the first workspace).
*/
API::Workspace_sptr Load::plusWs(
Workspace_sptr ws1,
Workspace_sptr ws2)
{
Mantid::API::IAlgorithm_sptr plusAlg = createSubAlgorithm("Plus", 1);
plusAlg->setPropertyValue("LHSWorkspace", ws1->name());
plusAlg->setPropertyValue("RHSWorkspace", ws2->name());
plusAlg->setPropertyValue("OutputWorkspace", ws1->name());
plusAlg->executeAsSubAlg();
return ws1;
}
/**
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
* Renames a workspace.
*
* @param oldName :: the old workspace name.
* @param newName :: the new workspace name.
*/
void Load::renameWs(
const std::string & oldName,
const std::string & newName)
{
if(oldName == newName)
return;
Mantid::API::IAlgorithm_sptr renameAlg = createSubAlgorithm("RenameWorkspace", 1);
renameAlg->setChild(true); // Must be keep child=true to prevent locking errors
renameAlg->setAlwaysStoreInADS(true);
renameAlg->setPropertyValue("InputWorkspace", oldName);
renameAlg->setPropertyValue("OutputWorkspace", newName);
renameAlg->executeAsSubAlg();
}
/**
* Deletes a given workspace. If the given workspace is a group workspace,
* then this function calls itself recursively for each workspace in the group.
*
* @param wsName :: the name of the workspace to delete.
*/
void Load::deleteWs(const std::string & wsName)
{
Workspace_sptr ws = AnalysisDataService::Instance().retrieve(wsName);
if(WorkspaceGroup_sptr wsGrpSptr =
boost::dynamic_pointer_cast<WorkspaceGroup>(ws))
{
std::vector<std::string> childWsNames = wsGrpSptr->getNames();
std::vector<std::string>::iterator vIt = childWsNames.begin();
for(; vIt != childWsNames.end(); ++vIt)
{
// Call this function recursively, to delete each child workspace.
deleteWs(*vIt);
}
}
else
{
Mantid::API::IAlgorithm_sptr deleteAlg = createSubAlgorithm("DeleteWorkspace", 1);
deleteAlg->setPropertyValue("Workspace", wsName);
deleteAlg->execute();
}
}
/**
* Unhides a given workspace (by removing the "__" prefix from its name if present).
* If the given workspace is a group workspace, then this function calls itself
* recursively for each workspace in the group.
* @param wsName :: the name of the workspace to unhide.
void Load::unhideWs(const std::string & wsName)
std::set<std::string> adsContents1 = AnalysisDataService::Instance().getObjectNames();
Workspace_sptr ws = AnalysisDataService::Instance().retrieve(wsName);
if(WorkspaceGroup_sptr wsGrpSptr =
boost::dynamic_pointer_cast<WorkspaceGroup>(ws))
std::vector<std::string> childWsNames = wsGrpSptr->getNames();
std::vector<std::string>::iterator vIt = childWsNames.begin();
for(; vIt != childWsNames.end(); ++vIt)
// Call this function recursively, to unhide each child workspace.
unhideWs(*vIt);
}
else
{
if(boost::starts_with(wsName, "__"))
std::string newName = wsName.substr(2, (wsName.size() - 2));
renameWs(wsName, newName);
}
}
}
} // namespace DataHandling
} // namespace Mantid