Newer
Older
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/WorkspaceFactory.h"
Russell Taylor
committed
#include "MantidAPI/Workspace.h"
Roman Tolchenov
committed
#include "MantidAPI/MemoryManager.h"
Russell Taylor
committed
#include "MantidKernel/ConfigService.h"
Russell Taylor
committed
#include "MantidAPI/SpectraDetectorMap.h"
namespace Mantid
Russell Taylor
committed
namespace API
{
/// Private constructor for singleton class
Russell Taylor
committed
WorkspaceFactoryImpl::WorkspaceFactoryImpl() :
Roman Tolchenov
committed
Mantid::Kernel::DynamicFactory<MatrixWorkspace>(), g_log(Kernel::Logger::get("WorkspaceFactory"))
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()
{
// g_log.debug() << "WorkspaceFactory destroyed." << std::endl;
}
Russell Taylor
committed
Russell Taylor
committed
/** Create a new instance of the same type of workspace as that given as argument.
Russell Taylor
committed
* If the optional size parameters are given, the workspace will be initialised using
* 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.
* Note that the axes are NOT copied when the size parameters are given.
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
*/
Roman Tolchenov
committed
MatrixWorkspace_sptr WorkspaceFactoryImpl::create(const MatrixWorkspace_const_sptr& parent,
Russell Taylor
committed
int NVectors, int XLength, int YLength) const
Russell Taylor
committed
{
Russell Taylor
committed
// Flag to indicate whether this workspace is the same size as the parent
bool differentSize = true;
if ( YLength < 0 ) differentSize = false;
Russell Taylor
committed
// If the size parameters have not been specified, get them from the parent
if ( !differentSize )
Russell Taylor
committed
{
// Find out the size of the parent
XLength = parent->dataX(0).size();
YLength = parent->blocksize();
NVectors = parent->size() / YLength;
}
Roman Tolchenov
committed
MatrixWorkspace_sptr ws = create(parent->id(),NVectors,XLength,YLength);
Russell Taylor
committed
// Copy over certain parent data members
Russell Taylor
committed
ws->m_spectramap = parent->m_spectramap;
Russell Taylor
committed
ws->setSample(parent->getSample());
Russell Taylor
committed
ws->setYUnit(parent->m_YUnit);
Russell Taylor
committed
ws->isDistribution(parent->isDistribution());
// Only copy the axes over if new sizes are not given
if ( !differentSize )
Russell Taylor
committed
{
// Only copy mask map if same size for now. Later will need to check continued validity.
ws->m_masks = parent->m_masks;
for (unsigned int i = 0; i < parent->m_axes.size(); ++i)
{
// Need to delete the existing axis created in init above
delete ws->m_axes[i];
// Now set to a copy of the parent workspace's axis
ws->m_axes[i] = parent->m_axes[i]->clone(ws.get());
}
Russell Taylor
committed
}
Russell Taylor
committed
else
{
// Just copy the unit and title
for (unsigned int i = 0; i < ws->m_axes.size(); ++i)
{
ws->getAxis(i)->unit() = parent->getAxis(i)->unit();
ws->getAxis(i)->title() = parent->getAxis(i)->title();
}
}
Russell Taylor
committed
Russell Taylor
committed
return ws;
}
Russell Taylor
committed
/** Creates a new instance of the class with the given name, and allocates memory for the arrays
* where it creates and initialises either a Workspace1D, Workspace2D or a ManagedWorkspace2D
Russell Taylor
committed
* according to the size requested and the value of the configuration parameter
* ManagedWorkspace.LowerMemoryLimit (default 40% of available physical memory) Workspace2D only.
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)
* @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
*/
Roman Tolchenov
committed
MatrixWorkspace_sptr WorkspaceFactoryImpl::create(const std::string& className, const int& NVectors,
Russell Taylor
committed
const int& XLength, const int& YLength) const
{
Roman Tolchenov
committed
MatrixWorkspace_sptr ws;
Russell Taylor
committed
// Creates a managed workspace if over the trigger size and a 2D workspace is being requested.
// Otherwise calls the vanilla create method.
bool is2D = className.find("2D") != std::string::npos;
if ( MemoryManager::Instance().goForManagedWorkspace(NVectors,XLength,YLength) && is2D )
Russell Taylor
committed
{
Roman Tolchenov
committed
// check if there is enough memory for 100 data blocks
int blockMemory;
if ( ! Kernel::ConfigService::Instance().getValue("ManagedWorkspace.DataBlockSize", blockMemory)
|| blockMemory <= 0 )
{
// default to 1MB if property not found
blockMemory = 1024*1024;
}
Roman Tolchenov
committed
MemoryInfo mi = MemoryManager::Instance().getMemoryInfo();
Roman Tolchenov
committed
if ( blockMemory*100/1024 > mi.availMemory )
{
g_log.error("There is not enough memory to allocate the workspace");
throw std::runtime_error("There is not enough memory to allocate the workspace");
}
ws = this->create("ManagedWorkspace2D");
g_log.information("Created a ManagedWorkspace2D");
Russell Taylor
committed
}
else
{
// No need for a Managed Workspace
if ( is2D && className.substr(0,7) == "Managed" )
ws = this->create("Workspace2D");
else
ws = this->create(className);
Russell Taylor
committed
}
Russell Taylor
committed
Russell Taylor
committed
ws->initialize(NVectors,XLength,YLength);
Russell Taylor
committed
return ws;
}
Russell Taylor
committed
} // namespace API
} // Namespace Mantid