Skip to content

Commit

Permalink
More work on adding workspaces to groups. Re #6199.
Browse files Browse the repository at this point in the history
  • Loading branch information
mantid-roman committed May 13, 2013
1 parent e37fdb5 commit 5d9b994
Show file tree
Hide file tree
Showing 8 changed files with 255 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ class DLLExport AnalysisDataServiceImpl : public Kernel::DataService<API::Worksp
/// Overridden rename member to attach the new name to the workspace when a workspace object is renamed
virtual void rename( const std::string& oldName, const std::string& newName);
/// Get a shared pointer to a stored workspace
boost::shared_ptr<API::Workspace> retrieve( const std::string& name) const;
virtual boost::shared_ptr<API::Workspace> retrieve( const std::string& name) const;
/// Check to see if a data object exists in the store
virtual bool doesExist(const std::string& name) const;

/** Retrieve a workspace and cast it to the given WSTYPE
*
Expand All @@ -130,6 +132,10 @@ class DLLExport AnalysisDataServiceImpl : public Kernel::DataService<API::Worksp
return boost::dynamic_pointer_cast<WSTYPE>(workspace);
}

/// Remove a workspace if it is on the top level of the ADS, ie not a part of a workspace group.
void removeFromTopLevel(const std::string &name);
/// Count instances of a workspace in the ADS
size_t count(Workspace_const_sptr workspace) const;

private:
/// Checks the name is valid, throwing if not
Expand Down
5 changes: 4 additions & 1 deletion Code/Mantid/Framework/API/inc/MantidAPI/Workspace.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,12 @@ class MANTID_API_DLL Workspace : public Kernel::DataItem

void virtual setTitle(const std::string&);
void setComment(const std::string&);
void setName(const std::string&);
virtual void setName(const std::string&);
//virtual const std::string& getTitle() const;
virtual const std::string getTitle() const;
const std::string& getComment() const;
const std::string& getName() const;
const std::string& getUpperCaseName() const;
bool isDirty(const int n=1) const;
/// Get the footprint in memory in bytes.
virtual size_t getMemorySize() const = 0;
Expand All @@ -90,6 +91,8 @@ class MANTID_API_DLL Workspace : public Kernel::DataItem
std::string m_comment;
/// The name associated with the object within the ADS (This is required for workspace algebra
std::string m_name;
/// The upper case version of the name (for faster searching)
std::string m_upperCaseName;
/// The history of the workspace, algorithm and environment
WorkspaceHistory m_history;

Expand Down
10 changes: 9 additions & 1 deletion Code/Mantid/Framework/API/inc/MantidAPI/WorkspaceGroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ class MANTID_API_DLL WorkspaceGroup : public Workspace
~WorkspaceGroup();
/// Return a string ID of the class
virtual const std::string id() const { return "WorkspaceGroup"; }
/// Set the name
virtual void setName(const std::string &name);
/// The size of the group.
virtual size_t getMemorySize() const;
/// Adds a workspace to the group.
Expand All @@ -76,7 +78,9 @@ class MANTID_API_DLL WorkspaceGroup : public Workspace
/// Return the workspace by name
Workspace_sptr getItem(const std::string wsName) const;
/// Find a workspace by name
Workspace_sptr findItem(const std::string wsName) const;
Workspace_sptr findItem(const std::string wsName, bool convertToUpperCase = true, size_t nesting = 0) const;
/// Count number of instances of a workspace in the group.
size_t count(Workspace_const_sptr workspace, size_t nesting = 0)const;

/// Does a workspace exist within the group
bool contains(const std::string & wsName) const;
Expand Down Expand Up @@ -120,8 +124,12 @@ class MANTID_API_DLL WorkspaceGroup : public Workspace
bool m_observingADS;
/// Recursive mutex to avoid simultaneous access
mutable Poco::Mutex m_mutex;
/// Counter for creating unigue names
mutable size_t m_nameCounter;
/// Static reference to the logger
static Kernel::Logger& g_log;
/// Maximum nesting level allowed
static size_t g_maxNestingLevel;
};

/// Shared pointer to a workspace group class
Expand Down
97 changes: 65 additions & 32 deletions Code/Mantid/Framework/API/src/AnalysisDataService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,21 +67,6 @@ namespace Mantid
//Attach the name to the workspace
if( workspace ) workspace->setName(name);
Kernel::DataService<API::Workspace>::add(name, workspace);

// if a group is added add its members as well
auto group = boost::dynamic_pointer_cast<WorkspaceGroup>( workspace );
if ( !group ) return;
for(size_t i = 0; i < group->size(); ++i)
{
auto ws = group->getItem( i );
std::string wsName = ws->name();
// if anonymous make up a name and add
if ( wsName.empty() )
{
wsName = name + "_" + boost::lexical_cast<std::string>( i + 1 );
ws->setName( wsName );
}
}
}

/**
Expand All @@ -97,20 +82,6 @@ namespace Mantid
//Attach the name to the workspace
if( workspace ) workspace->setName(name);
Kernel::DataService<API::Workspace>::addOrReplace(name, workspace);

// if a group is added add its members as well
auto group = boost::dynamic_pointer_cast<WorkspaceGroup>( workspace );
if ( !group ) return;
for(size_t i = 0; i < group->size(); ++i)
{
auto ws = group->getItem( i );
std::string wsName = ws->name();
// make up a name for an anonymous workspace
if ( wsName.empty() )
{
wsName = name + "_" + boost::lexical_cast<std::string>( i + 1 );
}
}
}

/**
Expand All @@ -127,27 +98,89 @@ namespace Mantid
}

/**
* Extend the default behaviour by searching workspace groups recursively.
* Extend the default behaviour by searching workspace groups recursively. Search is case insensitive.
* @param name :: Name of the workspace.
*/
boost::shared_ptr<API::Workspace> AnalysisDataServiceImpl::retrieve(const std::string &name) const
{
std::string foundName = name;
std::transform(foundName.begin(), foundName.end(), foundName.begin(),toupper);
std::vector<Workspace_sptr> workspaces = getObjects();
for(auto it = workspaces.begin(); it != workspaces.end(); ++it)
{
Workspace *ws = it->get();
if ( ws->name() == name ) return *it;
if ( ws->getUpperCaseName() == foundName ) return *it;
WorkspaceGroup* wsg = dynamic_cast<WorkspaceGroup*>(ws);
if ( wsg )
{
// look in member groups recursively
auto res = wsg->findItem(name);
auto res = wsg->findItem(foundName, false);
if ( res ) return res;
}
}
throw Kernel::Exception::NotFoundError("Workspace",name);
}

/**
* Search recursively in the data store and workspace groups in it for a name.
* @param name :: Name to search for.
* @return True if name is found.
*/
bool AnalysisDataServiceImpl::doesExist(const std::string &name) const
{
try
{
auto it = retrieve(name);
if ( it ) return true;
}
catch(Kernel::Exception::NotFoundError)
{
return false;
}
return false;
}

/**
* A method to help with workspace group management.
* @param name :: Name of a workspace to emove.
*/
void AnalysisDataServiceImpl::removeFromTopLevel(const std::string &name)
{
std::string foundName = name;
std::transform(foundName.begin(), foundName.end(), foundName.begin(),toupper);
std::vector<Workspace_sptr> workspaces = getObjects();
for(auto it = workspaces.begin(); it != workspaces.end(); ++it)
{
if ( (**it).getUpperCaseName() == foundName )
{
Kernel::DataService<Workspace>::remove( name );
return;
}
}
}

/**
* Get number of copies of a workspace in the ADS.
* @param workspace :: A workspace to count.
* @return :: Number of copies.
*/
size_t AnalysisDataServiceImpl::count(Workspace_const_sptr workspace) const
{
size_t n = 0;
std::vector<Workspace_sptr> workspaces = getObjects();
for(auto it = workspaces.begin(); it != workspaces.end(); ++it)
{
if ( (*it) == workspace ) n += 1;
const Workspace *ws = it->get();
const WorkspaceGroup* wsg = dynamic_cast<const WorkspaceGroup*>(ws);
if ( wsg )
{
n += wsg->count( workspace );
}
}
return n;
}

//-------------------------------------------------------------------------
// Private methods
//-------------------------------------------------------------------------
Expand Down
15 changes: 14 additions & 1 deletion Code/Mantid/Framework/API/src/Workspace.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "MantidAPI/Workspace.h"
#include "MantidKernel/PropertyManager.h"

#include <algorithm>

namespace Mantid
{
namespace API
Expand Down Expand Up @@ -53,6 +55,8 @@ void Workspace::setComment(const std::string& c)
void Workspace::setName(const std::string& name)
{
m_name = name;
m_upperCaseName = name;
std::transform(m_upperCaseName.begin(), m_upperCaseName.end(), m_upperCaseName.begin(),toupper);
}

/** Get the workspace title
Expand All @@ -79,7 +83,16 @@ const std::string& Workspace::getComment() const
*/
const std::string& Workspace::getName() const
{
return m_name;
return m_name;
}

/**
* Get the workspace name converted to upper case. Uses a cached variable.
* @return The name in upper case.
*/
const std::string &Workspace::getUpperCaseName() const
{
return m_upperCaseName;
}

/**
Expand Down
93 changes: 87 additions & 6 deletions Code/Mantid/Framework/API/src/WorkspaceGroup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "MantidKernel/IPropertyManager.h"

#include <Poco/ScopedLock.h>
#include <boost/lexical_cast.hpp>

namespace Mantid
{
Expand All @@ -16,11 +17,13 @@ namespace API

Kernel::Logger& WorkspaceGroup::g_log = Kernel::Logger::get("WorkspaceGroup");

size_t WorkspaceGroup::g_maxNestingLevel = 100;

WorkspaceGroup::WorkspaceGroup(const bool observeADS) :
Workspace(),
m_deleteObserver(*this, &WorkspaceGroup::workspaceDeleteHandle),
m_replaceObserver(*this, &WorkspaceGroup::workspaceReplaceHandle),
m_workspaces(), m_observingADS(false)
m_workspaces(), m_observingADS(false), m_nameCounter(0)
{
observeADSNotifications(observeADS);
}
Expand All @@ -30,6 +33,25 @@ WorkspaceGroup::~WorkspaceGroup()
observeADSNotifications(false);
}

/**
* Override the base method to set names of member workspaces if they are empty.
* @param name :: The new name.
*/
void WorkspaceGroup::setName(const std::string &name)
{
Workspace::setName(name);
for (auto it = m_workspaces.begin(); it != m_workspaces.end(); ++it)
{
std::string wsName = (**it).name();
if ( wsName.empty() )
{
++m_nameCounter;
wsName = name + "_" + boost::lexical_cast<std::string>(m_nameCounter);
(**it).setName(wsName);
}
}
}

/**
* The size of the group is the sum of sizes of members.
*/
Expand Down Expand Up @@ -93,6 +115,23 @@ void WorkspaceGroup::addWorkspace(Workspace_sptr workspace)
if ( it == m_workspaces.end() )
{
m_workspaces.push_back( workspace );
if ( ! name().empty() )
{
// checking for non-empty name - a faster way of chacking for being in the ADS
if ( workspace->name().empty() )
{
++m_nameCounter;
std::string wsName = name() + "_" + boost::lexical_cast<std::string>(m_nameCounter);
workspace->setName(wsName);
}
else
{
bool observing = m_observingADS;
observeADSNotifications( false );
AnalysisDataService::Instance().removeFromTopLevel( workspace->name() );
observeADSNotifications( observing );
}
}
updated();
}
else
Expand Down Expand Up @@ -165,27 +204,69 @@ Workspace_sptr WorkspaceGroup::getItem(const std::string wsName) const

/**
* Find a workspace by name. Search recursively in any nseted groups.
* Return an empty pointer if the workspace isn't found.
* @param wsName The name of the workspace.
*
* @param wsName :: The name of the workspace.
* @param convertToUpperCase :: Set true if wsName needs to be converted to upper case before search.
* @param nesting :: Current nesting level. To detect cycles.
* @return :: Return a shared pointer to the workspace or an empty pointer if not found.
*/
Workspace_sptr WorkspaceGroup::findItem(const std::string wsName) const
Workspace_sptr WorkspaceGroup::findItem(const std::string wsName, bool convertToUpperCase, size_t nesting) const
{
if ( nesting >= g_maxNestingLevel )
{
// check for cycles
throw std::runtime_error("Workspace group nesting is too deep. Could be a cycle.");
}

std::string foundName = wsName;
if ( convertToUpperCase )
{
std::transform(foundName.begin(), foundName.end(), foundName.begin(),toupper);
}
Poco::Mutex::ScopedLock _lock(m_mutex);
for(auto it = m_workspaces.begin(); it != m_workspaces.end(); ++it)
{
Workspace *ws = it->get();
if ( ws->name() == wsName ) return *it;
if ( ws->getUpperCaseName() == foundName ) return *it;
WorkspaceGroup* wsg = dynamic_cast<WorkspaceGroup*>(ws);
if ( wsg )
{
// look in member groups recursively
auto res = wsg->findItem(wsName);
auto res = wsg->findItem(foundName, false, nesting + 1);
if ( res ) return res;
}
}
return Workspace_sptr();
}

/**
* Look recursively for a workspace and count its instances.
* @param workspace :: Workspace to look for.
* @param nesting :: Current nesting level. To detect cycles.
* @return :: Number of copies.
*/
size_t WorkspaceGroup::count(Workspace_const_sptr workspace, size_t nesting) const
{
if ( nesting >= g_maxNestingLevel )
{
// check for cycles
throw std::runtime_error("Workspace group nesting is too deep. Could be a cycle.");
}

size_t n = 0;
for(auto it = m_workspaces.begin(); it != m_workspaces.end(); ++it)
{
if ( (*it) == workspace ) n += 1;
const Workspace *ws = it->get();
const WorkspaceGroup* wsg = dynamic_cast<const WorkspaceGroup*>(ws);
if ( wsg )
{
n += wsg->count( workspace, nesting + 1 );
}
}
return n;
}

/// Empty all the entries out of the workspace group. Does not remove the workspaces from the ADS.
void WorkspaceGroup::removeAll()
{
Expand Down

0 comments on commit 5d9b994

Please sign in to comment.