Skip to content

Commit

Permalink
Refs #4244 AlgorithmRunner object for code reuse...
Browse files Browse the repository at this point in the history
of running an algorithm in the background and waiting for it to finish.
Will reuse in LineViewer
  • Loading branch information
Janik Zikovsky committed Apr 23, 2012
1 parent 2a0947e commit f54a326
Show file tree
Hide file tree
Showing 6 changed files with 276 additions and 94 deletions.
9 changes: 8 additions & 1 deletion Code/Mantid/MantidQt/API/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ set ( SRC_FILES
src/AlgorithmDialog.cpp
src/AlgorithmInputHistory.cpp
src/AlgorithmPropertiesWidget.cpp
src/AlgorithmRunner.cpp
src/BoolPropertyWidget.cpp
src/FilePropertyWidget.cpp
src/GenericDialog.cpp
Expand All @@ -26,6 +27,7 @@ set ( SRC_FILES

set ( MOC_FILES
inc/MantidQtAPI/AlgorithmDialog.h
inc/MantidQtAPI/AlgorithmRunner.h
inc/MantidQtAPI/AlgorithmPropertiesWidget.h
inc/MantidQtAPI/BoolPropertyWidget.h
inc/MantidQtAPI/FilePropertyWidget.h
Expand All @@ -47,8 +49,9 @@ set ( MOC_FILES

# Include files aren't required, but this makes them appear in Visual Studio
set ( INC_FILES
${MOC_FILES}
${MOC_FILES}
inc/MantidQtAPI/AlgorithmInputHistory.h
inc/MantidQtAPI/AlgorithmRunner.h
inc/MantidQtAPI/DllOption.h
inc/MantidQtAPI/FileDialogHandler.h
inc/MantidQtAPI/GraphOptions.h
Expand Down Expand Up @@ -141,3 +144,7 @@ endif () # (not for windows)
###########################################################################

install ( TARGETS MantidQtAPI DESTINATION ${LIB_DIR} )

set ( TEST_FILES
test/AlgorithmRunnerTest.h
)
94 changes: 94 additions & 0 deletions Code/Mantid/MantidQt/API/inc/MantidQtAPI/AlgorithmRunner.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#ifndef MANTID_API_ALGORITHMRUNNER_H_
#define MANTID_API_ALGORITHMRUNNER_H_

#include "MantidKernel/System.h"
#include "DllOption.h"
#include <QtCore/qobject.h>
#include <Poco/NObserver.h>
#include "MantidAPI/Algorithm.h"
#include "MantidAPI/IAlgorithm.h"

namespace MantidQt
{
namespace API
{

/** The AlgorithmRunner is a QObject that encapsulates
* methods for running an algorithm asynchronously (in the background)
* and feeds-back to a GUI widget.
*
* The QObject keeps track of a running algorithm.
* Any already-running algorithm is cancelled if it gets started again.
* Signals are emitted when the algorithm progresses or finishes.
*
* TO USE:
* - Create the AlgorithmRunner object.
* - Connect the desired signal(s) to slots on your GUI.
* - Call cancelRunningAlgorithm() then startAlgorithm() to start.
@date 2012-04-23
Copyright &copy; 2012 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 EXPORT_OPT_MANTIDQT_API AlgorithmRunner : public QObject
{
Q_OBJECT

public:
AlgorithmRunner();
virtual ~AlgorithmRunner();

void cancelRunningAlgorithm();

void startAlgorithm(Mantid::API::IAlgorithm_sptr alg);

signals:
/// Signal emitted when the algorithm has completed execution/encountered an error
void algorithmComplete(bool error);

/// Signal emitted when the algorithm reports progress
void algorithmProgress(double p,const std::string& msg);

protected:

/// Algorithm notification handlers
void handleAlgorithmFinishedNotification(const Poco::AutoPtr<Mantid::API::Algorithm::FinishedNotification>& pNf);
Poco::NObserver<AlgorithmRunner, Mantid::API::Algorithm::FinishedNotification> m_finishedObserver;

void handleAlgorithmProgressNotification(const Poco::AutoPtr<Mantid::API::Algorithm::ProgressNotification>& pNf);
Poco::NObserver<AlgorithmRunner, Mantid::API::Algorithm::ProgressNotification> m_progressObserver;

void handleAlgorithmErrorNotification(const Poco::AutoPtr<Mantid::API::Algorithm::ErrorNotification>& pNf);
Poco::NObserver<AlgorithmRunner, Mantid::API::Algorithm::ErrorNotification> m_errorObserver;

/// For the asynchronous call in dynamic rebinning. Holds the result of asyncExecute() algorithm call
Poco::ActiveResult<bool> * m_asyncRebinResult;

/// Reference to the algorithm executing asynchronously.
Mantid::API::IAlgorithm_sptr m_asyncRebinAlg;

};


} // namespace API
} // namespace Mantid

#endif /* MANTID_API_ALGORITHMRUNNER_H_ */
113 changes: 113 additions & 0 deletions Code/Mantid/MantidQt/API/src/AlgorithmRunner.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#include "MantidQtAPI/AlgorithmRunner.h"
#include "MantidKernel/System.h"

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

namespace MantidQt
{
namespace API
{


//----------------------------------------------------------------------------------------------
/** Constructor
*/
AlgorithmRunner::AlgorithmRunner() :
m_finishedObserver(*this, &AlgorithmRunner::handleAlgorithmFinishedNotification),
m_progressObserver(*this, &AlgorithmRunner::handleAlgorithmProgressNotification),
m_errorObserver(*this, &AlgorithmRunner::handleAlgorithmErrorNotification)
{
}

//----------------------------------------------------------------------------------------------
/** Destructor
*/
AlgorithmRunner::~AlgorithmRunner()
{
}


//--------------------------------------------------------------------------------------
/** If an algorithm is already running, cancel it.
* Does nothing if no algorithm is running. This blocks
* for up to 1 second to wait for the algorithm to finish cancelling.
*/
void AlgorithmRunner::cancelRunningAlgorithm()
{
// Cancel any currently running rebinning algorithms
if (m_asyncRebinAlg)
{
if (m_asyncRebinAlg->isRunning())
m_asyncRebinAlg->cancel();
if (m_asyncRebinResult)
{
m_asyncRebinResult->tryWait(1000);
delete m_asyncRebinResult;
}
}
}

//--------------------------------------------------------------------------------------
/** Begin asynchronous execution of an algorithm and observe its execution
*
* @param alg :: algorithm to execute. All properties should have been set properly.
*/
void AlgorithmRunner::startAlgorithm(Mantid::API::IAlgorithm_sptr alg)
{
if (!alg)
throw std::invalid_argument("AlgorithmRunner::startAlgorithm() given a NULL Algorithm");
if (!alg->isInitialized())
throw std::invalid_argument("AlgorithmRunner::startAlgorithm() given an uninitialized Algorithm");

// Start asynchronous execution
m_asyncRebinAlg = alg;
m_asyncRebinResult = new Poco::ActiveResult<bool>(m_asyncRebinAlg->executeAsync());

// Observe the algorithm
alg->addObserver(m_finishedObserver);
alg->addObserver(m_errorObserver);
alg->addObserver(m_progressObserver);
}

//--------------------------------------------------------------------------------------
/** Observer called when the asynchronous algorithm has completed.
*
* Emits a signal for the GUI widget
*
* This is called in a separate (non-GUI) thread and so
* CANNOT directly change the gui.
*
* @param pNf :: finished notification object.
*/
void AlgorithmRunner::handleAlgorithmFinishedNotification(const Poco::AutoPtr<Algorithm::FinishedNotification>& pNf)
{
UNUSED_ARG(pNf);
emit algorithmComplete(false);
}

//--------------------------------------------------------------------------------------
/** Observer called when the async algorithm has progress to report
*
* @param pNf :: notification object
*/
void AlgorithmRunner::handleAlgorithmProgressNotification(const Poco::AutoPtr<Algorithm::ProgressNotification>& pNf)
{
emit algorithmProgress(pNf->progress, pNf->message);
}

//--------------------------------------------------------------------------------------
/** Observer called when the async algorithm has encountered an error.
* Emits a signal for the GUI widget
*
* @param pNf :: notification object
*/
void AlgorithmRunner::handleAlgorithmErrorNotification(const Poco::AutoPtr<Algorithm::ErrorNotification>& pNf)
{
UNUSED_ARG(pNf);
emit algorithmComplete(true);
}


} // namespace Mantid
} // namespace API
34 changes: 34 additions & 0 deletions Code/Mantid/MantidQt/API/test/AlgorithmRunnerTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef MANTID_API_ALGORITHMRUNNERTEST_H_
#define MANTID_API_ALGORITHMRUNNERTEST_H_

#include <cxxtest/TestSuite.h>
#include "MantidKernel/Timer.h"
#include "MantidKernel/System.h"
#include <iostream>
#include <iomanip>

#include "MantidAPI/AlgorithmRunner.h"

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

class AlgorithmRunnerTest : public CxxTest::TestSuite
{
public:
// This pair of boilerplate methods prevent the suite being created statically
// This means the constructor isn't called when running other tests
static AlgorithmRunnerTest *createSuite() { return new AlgorithmRunnerTest(); }
static void destroySuite( AlgorithmRunnerTest *suite ) { delete suite; }


void test_Something()
{
TSM_ASSERT( "You forgot to write a test!", 0);
}


};


#endif /* MANTID_API_ALGORITHMRUNNERTEST_H_ */
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <vector>
#include <Poco/NObserver.h>
#include "MantidAPI/Algorithm.h"
#include "MantidQtAPI/AlgorithmRunner.h"

namespace MantidQt
{
Expand Down Expand Up @@ -98,8 +99,6 @@ class EXPORT_OPT_MANTIDQT_SLICEVIEWER SliceViewer : public QWidget
void showLineViewer(bool);
/// Signal emitted when someone uses setWorkspace() on SliceViewer
void workspaceChanged();
/// Signal emitted when the dynamic rebinning call is complete.
void dynamicRebinComplete();

public slots:
void helpSliceViewer();
Expand Down Expand Up @@ -138,7 +137,7 @@ public slots:

// Dynamic rebinning
void rebinParamsChanged();
void dynamicRebinCompleteSlot();
void dynamicRebinComplete(bool error);


private:
Expand All @@ -156,17 +155,6 @@ public slots:
void findRangeFull();
void findRangeSlice();

protected:

/// Algorithm notification handlers
void handleAlgorithmFinishedNotification(const Poco::AutoPtr<Mantid::API::Algorithm::FinishedNotification>& pNf);
Poco::NObserver<SliceViewer, Mantid::API::Algorithm::FinishedNotification> m_finishedObserver;

void handleAlgorithmProgressNotification(const Poco::AutoPtr<Mantid::API::Algorithm::ProgressNotification>& pNf);
Poco::NObserver<SliceViewer, Mantid::API::Algorithm::ProgressNotification> m_progressObserver;

void handleAlgorithmErrorNotification(const Poco::AutoPtr<Mantid::API::Algorithm::ErrorNotification>& pNf);
Poco::NObserver<SliceViewer, Mantid::API::Algorithm::ErrorNotification> m_errorObserver;

private:
// -------------------------- Widgets ----------------------------
Expand Down Expand Up @@ -195,7 +183,8 @@ public slots:
/// The LineOverlay widget for drawing the outline of the rebinned workspace
LineOverlay * m_overlayWSOutline;


/// Object for running algorithms in the background
MantidQt::API::AlgorithmRunner * m_algoRunner;

// -------------------------- Data Members ----------------------------

Expand Down Expand Up @@ -260,12 +249,6 @@ public slots:
/// Last path that was saved using saveImage()
QString m_lastSavedFile;

/// For the asynchronous call in dynamic rebinning. Holds the result of the async BinMD call
Poco::ActiveResult<bool> * m_asyncRebinResult;

/// Reference to the BinMD algorithm executing asynchronously.
Mantid::API::IAlgorithm_sptr m_asyncRebinAlg;

/// Name of the workspace generated by the dynamic rebinning BinMD call
std::string m_overlayWSName;

Expand Down

0 comments on commit f54a326

Please sign in to comment.