Skip to content

Commit

Permalink
Re #5496. Added algorithm for recording algorithm calls
Browse files Browse the repository at this point in the history
  • Loading branch information
mantid-roman committed Jul 12, 2012
1 parent 7ed5a88 commit 1713814
Show file tree
Hide file tree
Showing 6 changed files with 271 additions and 1 deletion.
29 changes: 29 additions & 0 deletions Code/Mantid/Framework/API/inc/MantidAPI/AlgorithmObserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//----------------------------------------------------------------------
#include "MantidAPI/DllConfig.h"
#include "MantidAPI/Algorithm.h"
#include "MantidAPI/AlgorithmManager.h"

#include <boost/shared_ptr.hpp>
#include <Poco/ActiveMethod.h>
Expand Down Expand Up @@ -52,6 +53,7 @@ class MANTID_API_DLL AlgorithmObserver
/// Default constructor. Notification hanlders are not connected to any algorithm
AlgorithmObserver()
:m_progressObserver(*this,&AlgorithmObserver::_progressHandle),
m_startingObserver(*this,&AlgorithmObserver::_startingHandle),
m_startObserver(*this,&AlgorithmObserver::_startHandle),
m_finishObserver(*this,&AlgorithmObserver::_finishHandle),
m_errorObserver(*this,&AlgorithmObserver::_errorHandle)
Expand All @@ -62,6 +64,7 @@ class MANTID_API_DLL AlgorithmObserver
*/
AlgorithmObserver(IAlgorithm_const_sptr alg)
:m_progressObserver(*this,&AlgorithmObserver::_progressHandle),
m_startingObserver(*this,&AlgorithmObserver::_startingHandle),
m_startObserver(*this,&AlgorithmObserver::_startHandle),
m_finishObserver(*this,&AlgorithmObserver::_finishHandle),
m_errorObserver(*this,&AlgorithmObserver::_errorHandle)
Expand Down Expand Up @@ -91,6 +94,14 @@ class MANTID_API_DLL AlgorithmObserver
alg->addObserver(m_progressObserver);
}

/** Connect to AlgorithmManager and observe its starting notifications
@param alg :: Algorithm to be observed
*/
void observeStarting()
{
AlgorithmManager::Instance().notificationCenter.addObserver(m_startingObserver);
}

/** Connect to algorithm alg and observe its start notification
@param alg :: Algorithm to be observed
*/
Expand Down Expand Up @@ -144,6 +155,14 @@ class MANTID_API_DLL AlgorithmObserver
(void)msg;
}

/** Handler of the start notifications. Must be overriden in inherited classes.
The default handler is provided (doing nothing).
@param alg :: Shared Pointer to the algorithm sending the notification.
*/
virtual void startingHandle(IAlgorithm_sptr alg)
{
(void)alg;
}
/** Handler of the start notifications. Must be overriden in inherited classes.
The default handler is provided (doing nothing).
@param alg :: Pointer to the algorithm sending the notification. Note that this can
Expand Down Expand Up @@ -222,6 +241,16 @@ class MANTID_API_DLL AlgorithmObserver
/// Poco::NObserver for Algorithm::ErrorNotification.
Poco::NObserver<AlgorithmObserver, Algorithm::ErrorNotification> m_errorObserver;

/** Poco notification handler for API::AlgorithmStartingNotification.
@param pNf :: An pointer to the notification.
*/
void _startingHandle(const Poco::AutoPtr<Mantid::API::AlgorithmStartingNotification>& pNf)
{
this->startingHandle(pNf->getAlgorithm());
}
/// Poco::NObserver for API::AlgorithmStartingNotification
Poco::NObserver<AlgorithmObserver, Mantid::API::AlgorithmStartingNotification> m_startingObserver;

};

} // namespace API
Expand Down
2 changes: 2 additions & 0 deletions Code/Mantid/Framework/Algorithms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ set ( SRC_FILES
src/Rebin2D.cpp
src/RebinToWorkspace.cpp
src/Rebunch.cpp
src/RecordPythonScript.cpp
src/Regroup.cpp
src/RemoveBins.cpp
src/RemoveLowResTOF.cpp
Expand Down Expand Up @@ -344,6 +345,7 @@ set ( INC_FILES
inc/MantidAlgorithms/Rebin2D.h
inc/MantidAlgorithms/RebinToWorkspace.h
inc/MantidAlgorithms/Rebunch.h
inc/MantidAlgorithms/RecordPythonScript.h
inc/MantidAlgorithms/Regroup.h
inc/MantidAlgorithms/RemoveBins.h
inc/MantidAlgorithms/RemoveLowResTOF.h
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class DLLExport GeneratePythonScript : public API::Algorithm
/// Algorithm's category for identification
virtual const std::string category() const { return "Utility;PythonAlgorithms";}

private:
protected:
/// Sets documentation strings for this algorithm
virtual void initDocs();
/// Initialise the properties
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#ifndef MANTID_ALGORITHMS_RECORDPYTHONSCRIPT_H_
#define MANTID_ALGORITHMS_RECORDPYTHONSCRIPT_H_

#include "MantidKernel/System.h"
#include "MantidAlgorithms/GeneratePythonScript.h"
#include "MantidAPI/AlgorithmObserver.h"

namespace Mantid
{
namespace Algorithms
{

/** RecordPythonScript : TODO: DESCRIPTION
An Algorithm to generate a Python script file to reproduce the history of a workspace.
Properties:
<ul>
<li>Filename - the name of the file to write to. </li>
<li>InputWorkspace - the workspace name who's history is to be saved.</li>
</ul>
Copyright &copy; 2011 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
This file is part of Mantid.
Mantid is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
Mantid is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>
Code Documentation is available at: <http://doxygen.mantidproject.org>
*/
class DLLExport RecordPythonScript : public Algorithms::GeneratePythonScript, public API::AlgorithmObserver
{
public:
RecordPythonScript();
virtual ~RecordPythonScript() {}

/// Algorithm's name for identification
virtual const std::string name() const { return "RecordPythonScript";};
/// Algorithm's version for identification
virtual int version() const { return 1;};
/// Algorithm's category for identification
virtual const std::string category() const { return "Utility;PythonAlgorithms";}

private:
/// Sets documentation strings for this algorithm
virtual void initDocs();
/// Initialise the properties
void init();
/// Run the algorithm
void exec();
/** Handler of the start notifications. Must be overriden in inherited classes.
@param alg :: Shared Pointer to the algorithm sending the notification.
*/
void startingHandle(API::IAlgorithm_sptr alg);
/// buffer for the script
std::string m_generatedScript;
};


} // namespace Algorithms
} // namespace Mantid

#endif /* MANTID_ALGORITHMS_RECORDPYTHONSCRIPT_H_ */
126 changes: 126 additions & 0 deletions Code/Mantid/Framework/Algorithms/src/RecordPythonScript.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*WIKI*
*WIKI*/
#include "MantidAlgorithms/RecordPythonScript.h"
#include "MantidKernel/System.h"
#include "MantidAPI/FileProperty.h"
#include "MantidAPI/AlgorithmManager.h"
#include "MantidAPI/AlgorithmHistory.h"
#include "MantidAPI/AlgorithmProxy.h"

#include <fstream>

using namespace Mantid::Kernel;
using namespace Mantid::API;

namespace Mantid
{
namespace Algorithms
{

// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(RecordPythonScript)


//----------------------------------------------------------------------------------------------
/// Constructor
RecordPythonScript::RecordPythonScript() : Algorithms::GeneratePythonScript(), API::AlgorithmObserver()
{
}

//----------------------------------------------------------------------------------------------
/// Sets documentation strings for this algorithm
void RecordPythonScript::initDocs()
{
this->setWikiSummary("An Algorithm to generate a Python script file to reproduce the history of a workspace.");
this->setOptionalMessage("An Algorithm to generate a Python script file to reproduce the history of a workspace.");
}

//----------------------------------------------------------------------------------------------
/** Initialize the algorithm's properties.
*/
void RecordPythonScript::init()
{
std::vector<std::string> exts;
exts.push_back(".py");

declareProperty(new API::FileProperty("Filename","", API::FileProperty::Save, exts),
"The file into which the Python script will be generated.");
}

//----------------------------------------------------------------------------------------------
/** Execute the algorithm.
*/
void RecordPythonScript::exec()
{
observeStarting();
// Keep going until you get cancelled
while (true)
{
try
{
// Exit if the user presses cancel
interruption_point();
}
catch(...)
{
break;
}
progress( 0.0, "Recording..." );

// Sleep for 50 msec
Poco::Thread::sleep(50);
}

// save the script to a file
const std::string filename = getPropertyValue("Filename");
std::ofstream file(filename.c_str(), std::ofstream::trunc);

if (NULL == file)
{
throw Exception::FileError("Unable to create file: " , filename);
}

file << m_generatedScript;
file.flush();
file.close();
}

/** Handler of the start notifications. Adds an algorithm call to the script.
* @param alg :: Shared pointer to the starting algorithm.
*/
void RecordPythonScript::startingHandle(API::IAlgorithm_sptr alg)
{
std::cerr << "Started " << alg->name() << std::endl;
auto props= alg->getProperties();
for( auto p = props.begin(); p != props.end(); ++p)
{
std::cerr << (**p).name() << '=' << (**p).value() << std::endl;
}
// Get the details of this algorithm history.
const std::string name = alg->name();
const int version = alg->version();

std::string algString;
for(auto p = props.begin() ; p != props.end(); ++p)
{
std::string paramString = (**p).name() + "='" + (**p).value() + "'";

// Miss out parameters that are empty.
if(paramString.length() != 0)
{
if(algString.length() != 0)
{
algString += ",";
}
algString += paramString;
}
}

m_generatedScript += name + "(" + algString + ")\n";
}


} // namespace Algorithms
} // namespace Mantid
38 changes: 38 additions & 0 deletions Code/Mantid/Framework/Algorithms/test/DeleteWorkspaceTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//------------------------------------------------------------------------------
#include "MantidAlgorithms/DeleteWorkspace.h"
#include "MantidTestHelpers/WorkspaceCreationHelper.h"
#include "MantidAPI/WorkspaceGroup.h"

#include <cxxtest/TestSuite.h>

Expand Down Expand Up @@ -47,4 +48,41 @@ class DeleteWorkspaceTest : public CxxTest::TestSuite
dataStore.remove(testName2);
}

void test_deleting_group_deletes_its_members()
{
using namespace Mantid::API;
using namespace Mantid::DataObjects;

// Need a test workspace registered within the ADS
const int yLength1 = 10;
Workspace2D_sptr testWS1 = WorkspaceCreationHelper::Create2DWorkspace(yLength1, 10);
const int yLength2 = 20;
Workspace2D_sptr testWS2 = WorkspaceCreationHelper::Create2DWorkspace(yLength2, 10);
AnalysisDataServiceImpl & dataStore = AnalysisDataService::Instance();
dataStore.clear();

const std::string testName1 = "DeleteWorkspace_testWS1";
const std::string testName2 = "DeleteWorkspace_testWS2";
dataStore.add(testName1, testWS1);
dataStore.add(testName2, testWS2);

auto group = WorkspaceGroup_sptr( new WorkspaceGroup );
group->add( testName1 );
group->add( testName2 );
dataStore.add("group", group);

TS_ASSERT_EQUALS(dataStore.size(), 3);

Mantid::Algorithms::DeleteWorkspace alg;
alg.initialize();
alg.setPropertyValue("Workspace", "group");
alg.setRethrows(true);
TS_ASSERT_THROWS_NOTHING(alg.execute());
TS_ASSERT(alg.isExecuted());

TS_ASSERT_EQUALS(dataStore.size(), 0);

dataStore.clear();
}

};

0 comments on commit 1713814

Please sign in to comment.