Newer
Older
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/WorkspaceFactory.h"
Russell Taylor
committed
#include "MantidAPI/Workspace.h"
Russell Taylor
committed
#include "MantidAPI/WorkspaceOpOverloads.h"
#include "MantidAPI/MatrixWorkspace.h"
Roman Tolchenov
committed
#include "MantidAPI/MemoryManager.h"
Russell Taylor
committed
#include "MantidKernel/ConfigService.h"
Michael Whitty
committed
#include "MantidAPI/NumericAxis.h"
#include "MantidAPI/TextAxis.h"
#include "MantidAPI/ITableWorkspace.h"
#include "MantidAPI/IPeaksWorkspace.h"
Michael Whitty
committed
namespace Mantid {
namespace API {
namespace {
/// static logger object
Kernel::Logger g_log("WorkspaceFactory");
}
/// Private constructor for singleton class
WorkspaceFactoryImpl::WorkspaceFactoryImpl()
: Mantid::Kernel::DynamicFactory<Workspace>() {
Russell Taylor
committed
g_log.debug() << "WorkspaceFactory created." << std::endl;
Russell Taylor
committed
/** Private destructor
Russell Taylor
committed
* Prevents client from calling 'delete' on the pointer handed
Russell Taylor
committed
* out by Instance
*/
WorkspaceFactoryImpl::~WorkspaceFactoryImpl() {}
Russell Taylor
committed
/** Create a new instance of the same type of workspace as that given as
* argument.
* If the optional size parameters are given, the workspace will be initialised
* using
Russell Taylor
committed
* those; otherwise it will be initialised to the same size as the parent.
* This method should be used when you want to carry over the Workspace data
* members
* relating to the Instrument, Spectra-Detector Map, Sample & Axes to the new
* workspace.
* If the workspace is the same size as its parent, then the X data, axes and
* mask list are
Russell Taylor
committed
* copied. If its a different size then they are not.
Russell Taylor
committed
* @param parent A shared pointer to the parent workspace
* @param NVectors (Optional) The number of vectors/histograms/detectors in
* the workspace
* @param XLength (Optional) The number of X data points/bin boundaries in
* each vector (must all be the same)
* @param YLength (Optional) The number of data/error points in each vector
* (must all be the same)
Russell Taylor
committed
* @return A shared pointer to the newly created instance
Russell Taylor
committed
* @throw std::out_of_range If invalid (0 or less) size arguments are given
Russell Taylor
committed
* @throw NotFoundException If the class is not registered in the factory
*/
MatrixWorkspace_sptr
WorkspaceFactoryImpl::create(const MatrixWorkspace_const_sptr &parent,
size_t NVectors, size_t XLength,
size_t YLength) const {
bool differentSize(true);
// Use the parent sizes if new ones are not specified
if (NVectors == size_t(-1))
NVectors = parent->getNumberHistograms();
if (XLength == size_t(-1))
XLength = parent->dataX(0).size();
if (YLength == size_t(-1)) {
differentSize = false;
Russell Taylor
committed
YLength = parent->blocksize();
}
// If the parent is an EventWorkspace, we want it to spawn a Workspace2D (or
// managed variant) as a child
std::string id(parent->id());
if (id == "EventWorkspace")
id = "Workspace2D";
Russell Taylor
committed
// Create an 'empty' workspace of the appropriate type and size
MatrixWorkspace_sptr ws = create(id, NVectors, XLength, YLength);
Russell Taylor
committed
// Copy over certain parent data members
initializeFromParent(parent, ws, differentSize);
Russell Taylor
committed
return ws;
}
Janik Zikovsky
committed
/** Initialise a workspace from its parent
* This sets values such as title, instrument, units, sample, spectramap.
* This does NOT copy any data.
*
* @param parent :: the parent workspace
* @param child :: the child workspace
* @param differentSize :: A flag to indicate if the two workspace will be
*different sizes
Janik Zikovsky
committed
*/
void WorkspaceFactoryImpl::initializeFromParent(
const MatrixWorkspace_const_sptr parent, const MatrixWorkspace_sptr child,
const bool differentSize) const {
Russell Taylor
committed
child->setTitle(parent->getTitle());
child->setComment(parent->getComment());
child->setInstrument(parent->getInstrument()); // This call also copies the
// SHARED POINTER to the
// parameter map
// This call will (should) perform a COPY of the parameter map.
child->instrumentParameters();
Russell Taylor
committed
child->m_sample = parent->m_sample;
Gigg, Martyn Anthony
committed
child->m_run = parent->m_run;
Russell Taylor
committed
child->setYUnit(parent->m_YUnit);
child->setYUnitLabel(parent->m_YUnitLabel);
child->isDistribution(parent->isDistribution());
// Only copy the axes over if new sizes are not given
if (!differentSize) {
// Only copy mask map if same size for now. Later will need to check
// continued validity.
Russell Taylor
committed
child->m_masks = parent->m_masks;
Janik Zikovsky
committed
// Same number of histograms = copy over the spectra data
if (parent->getNumberHistograms() == child->getNumberHistograms()) {
for (size_t wi = 0; wi < parent->getNumberHistograms(); wi++) {
ISpectrum *childSpec = child->getSpectrum(wi);
const ISpectrum *parentSpec = parent->getSpectrum(wi);
Janik Zikovsky
committed
// Copy spectrum number and detector IDs
childSpec->copyInfoFrom(*parentSpec);
}
}
for (size_t i = 0; i < parent->m_axes.size(); ++i) {
const size_t newAxisLength = child->getAxis(i)->length();
const size_t oldAxisLength = parent->getAxis(i)->length();
Michael Whitty
committed
if (!differentSize || newAxisLength == oldAxisLength) {
// Need to delete the existing axis created in init above
Russell Taylor
committed
delete child->m_axes[i];
// Now set to a copy of the parent workspace's axis
Russell Taylor
committed
child->m_axes[i] = parent->m_axes[i]->clone(child.get());
} else {
if (!parent->getAxis(i)->isSpectra()) // WHY???
Russell Taylor
committed
delete child->m_axes[i];
// Call the 'different length' clone variant
child->m_axes[i] = parent->m_axes[i]->clone(newAxisLength, child.get());
Russell Taylor
committed
}
}
Russell Taylor
committed
Russell Taylor
committed
return;
Russell Taylor
committed
}
/** Creates a new instance of the class with the given name, and allocates
* memory for the arrays
Russell Taylor
committed
* @param className The name of the class you wish to create
* @param NVectors The number of vectors/histograms/detectors in the
* workspace
* @param XLength The number of X data points/bin boundaries in each vector
* (must all be the same)
* @param YLength The number of data/error points in each vector (must all
* be the same)
Russell Taylor
committed
* @return A shared pointer to the newly created instance
Russell Taylor
committed
* @throw std::out_of_range If invalid (0 or less) size arguments are given
Russell Taylor
committed
* @throw NotFoundException If the class is not registered in the factory
*/
MatrixWorkspace_sptr WorkspaceFactoryImpl::create(const std::string &className,
const size_t &NVectors,
const size_t &XLength,
const size_t &YLength) const {
MatrixWorkspace_sptr ws =
boost::dynamic_pointer_cast<MatrixWorkspace>(this->create(className));
if (!ws) {
g_log.error("Workspace was not created");
throw std::runtime_error("Workspace was not created");
Roman Tolchenov
committed
}
ws->initialize(NVectors, XLength, YLength);
Russell Taylor
committed
return ws;
}
Peterson, Peter
committed
/// Create a ITableWorkspace
ITableWorkspace_sptr
WorkspaceFactoryImpl::createTable(const std::string &className) const {
ITableWorkspace_sptr ws;
try {
ws = boost::dynamic_pointer_cast<ITableWorkspace>(this->create(className));
if (!ws) {
throw std::runtime_error("Class " + className +
" cannot be cast to ITableWorkspace");
Roman Tolchenov
committed
}
} catch (Kernel::Exception::NotFoundError &) {
throw;
}
return ws;
Peterson, Peter
committed
}
Roman Tolchenov
committed
/// Create a IPeaksWorkspace
IPeaksWorkspace_sptr
WorkspaceFactoryImpl::createPeaks(const std::string &className) const {
IPeaksWorkspace_sptr ws;
try {
ws = boost::dynamic_pointer_cast<IPeaksWorkspace>(this->create(className));
if (!ws) {
throw std::runtime_error("Class " + className +
" cannot be cast to IPeaksWorkspace");
Roman Tolchenov
committed
}
} catch (Kernel::Exception::NotFoundError &) {
throw;
}
return ws;
Roman Tolchenov
committed
}
Russell Taylor
committed
} // namespace API
} // Namespace Mantid