Skip to content
Snippets Groups Projects
Algorithm.cpp 72.5 KiB
Newer Older
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
//     NScD Oak Ridge National Laboratory, European Spallation Source
//     & Institut Laue - Langevin
// SPDX - License - Identifier: GPL - 3.0 +
#include "MantidAPI/ADSValidator.h"
#include "MantidAPI/AlgorithmHistory.h"
#include "MantidAPI/AlgorithmManager.h"
#include "MantidAPI/AlgorithmProxy.h"
#include "MantidAPI/AnalysisDataService.h"
#include "MantidAPI/DeprecatedAlgorithm.h"
#include "MantidAPI/IWorkspaceProperty.h"
#include "MantidAPI/WorkspaceGroup.h"
#include "MantidAPI/WorkspaceHistory.h"
#include "MantidKernel/CompositeValidator.h"
Nick Draper's avatar
Nick Draper committed
#include "MantidKernel/ConfigService.h"
#include "MantidKernel/DateAndTime.h"
#include "MantidKernel/EmptyValues.h"
#include "MantidKernel/MultiThreaded.h"
#include "MantidKernel/PropertyWithValue.h"
#include "MantidKernel/Strings.h"
#include "MantidKernel/Timer.h"
Nick Draper's avatar
Nick Draper committed
#include "MantidKernel/UsageService.h"
#include "MantidParallel/Communicator.h"

#include <boost/weak_ptr.hpp>
#include "MantidKernel/StringTokenizer.h"
#include <Poco/ActiveMethod.h>
#include <Poco/ActiveResult.h>
#include <Poco/NotificationCenter.h>
#include <Poco/RWLock.h>
#include <Poco/Void.h>
Nick Draper's avatar
Nick Draper committed

#include <json/json.h>
// Index property handling template definitions
#include "MantidAPI/Algorithm.tcc"

namespace Mantid {
namespace API {
namespace {
/// Separator for workspace types in workspaceMethodOnTypes member
const std::string WORKSPACE_TYPES_SEPARATOR = ";";

class WorkspacePropertyValueIs {
public:
  explicit WorkspacePropertyValueIs(const std::string &value)
  bool operator()(IWorkspaceProperty *property) {
    auto *prop = dynamic_cast<Property *>(property);
    if (!prop)
      return false;
    return prop->value() == m_value;
  }

private:
  const std::string &m_value;

// Doxygen can't handle member specialization at the moment:
// https://bugzilla.gnome.org/show_bug.cgi?id=406027
// so we have to ignore them
///@cond
template <typename NumT> bool Algorithm::isEmpty(const NumT toCheck) {
  return static_cast<int>(toCheck) == EMPTY_INT();
}

template <> MANTID_API_DLL bool Algorithm::isEmpty(const double toCheck) {
  return std::abs((toCheck - EMPTY_DBL()) / (EMPTY_DBL())) < 1e-8;
}

// concrete instantiations
template MANTID_API_DLL bool Algorithm::isEmpty<int>(const int);
template MANTID_API_DLL bool Algorithm::isEmpty<int64_t>(const int64_t);
template MANTID_API_DLL bool Algorithm::isEmpty<std::size_t>(const std::size_t);
///@endcond

//=============================================================================================
//================================== Constructors/Destructors
//=================================
//=============================================================================================

/// Initialize static algorithm counter
size_t Algorithm::g_execCount = 0;

/// Constructor
Algorithm::Algorithm()
    : PropertyManagerOwner(), m_cancel(false), m_parallelException(false),
      m_log("Algorithm"), g_log(m_log), m_groupSize(0), m_executeAsync(nullptr),
      m_notificationCenter(nullptr), m_progressObserver(nullptr),
      m_executionState(ExecutionState::Uninitialized),
      m_resultState(ResultState::NotFinished), m_isExecuted(false),
      m_isChildAlgorithm(false), m_recordHistoryForChild(false),
      m_alwaysStoreInADS(true), m_runningAsync(false), m_rethrow(false),
      m_isAlgStartupLoggingEnabled(true), m_startChildProgress(0.),
      m_endChildProgress(0.), m_algorithmID(this), m_singleGroup(-1),
      m_groupsHaveSimilarNames(false), m_inputWorkspaceHistories(),
      m_communicator(std::make_unique<Parallel::Communicator>()) {}

/// Virtual destructor

//=============================================================================================
//================================== Simple Getters/Setters
//===================================
//=============================================================================================

/// Gets the current execution state
ExecutionState Algorithm::executionState() const { return m_executionState; }

/// Sets the current execution state
void Algorithm::setExecutionState(const ExecutionState state) {
  m_executionState = state;
}

/// Gets the current result State
ResultState Algorithm::resultState() const { return m_resultState; }

/// Sets the result execution state
/// if set to Success or Failed will also set the execution state to finished
void Algorithm::setResultState(const ResultState state) {
  if (state != ResultState::NotFinished) {
    setExecutionState(ExecutionState::Finished);
  }
//---------------------------------------------------------------------------------------------
/// Has the Algorithm already been initialized
bool Algorithm::isInitialized() const {
  return (m_executionState != ExecutionState::Uninitialized);

/// Has the Algorithm already been executed
bool Algorithm::isExecuted() const {
  return ((executionState() == ExecutionState::Finished) &&
          (resultState() == ResultState::Success));

//---------------------------------------------------------------------------------------------
/** To query whether algorithm is a child.
 *  @returns true - the algorithm is a child algorithm.  False - this is a full
 * managed algorithm.
 */
bool Algorithm::isChild() const { return m_isChildAlgorithm; }

/** To set whether algorithm is a child.
 *  @param isChild :: True - the algorithm is a child algorithm.  False - this
 * is a full managed algorithm.
 */
void Algorithm::setChild(const bool isChild) {
  m_isChildAlgorithm = isChild;
  this->setAlwaysStoreInADS(!isChild);

/**
 * Change the state of the history recording flag. Only applicable for
 * child algorithms.
 * @param on :: The new state of the flag
 */
void Algorithm::enableHistoryRecordingForChild(const bool on) {
  m_recordHistoryForChild = on;
}

/** Do we ALWAYS store in the AnalysisDataService? This is set to true
 * for python algorithms' child algorithms
 *
 * @param doStore :: always store in ADS
 */
void Algorithm::setAlwaysStoreInADS(const bool doStore) {
  m_alwaysStoreInADS = doStore;
}

/** Returns true if we always store in the AnalysisDataService.
 *  @return true if output is saved to the AnalysisDataService.
 */
bool Algorithm::getAlwaysStoreInADS() const { return m_alwaysStoreInADS; }

/** Set whether the algorithm will rethrow exceptions
 * @param rethrow :: true if you want to rethrow exception.
 */
void Algorithm::setRethrows(const bool rethrow) { this->m_rethrow = rethrow; }

/// True if the algorithm is running.
bool Algorithm::isRunning() const {
  return (executionState() == ExecutionState::Running);
}

//---------------------------------------------------------------------------------------------
/**  Add an observer to a notification
Loading
Loading full blame...