Mantid
Loading...
Searching...
No Matches
Algorithm.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
17
18#include "MantidJson/Json.h"
25#include "MantidKernel/Timer.h"
27
28#include "MantidParallel/Communicator.h"
29
31#include <Poco/ActiveMethod.h>
32#include <Poco/ActiveResult.h>
33#include <Poco/NotificationCenter.h>
34#include <Poco/RWLock.h>
35#include <Poco/Void.h>
36
37#include <json/json.h>
38
39#include <algorithm>
40#include <iterator>
41#include <map>
42#include <memory>
43#include <utility>
44
45// Index property handling template definitions
46#include "MantidAPI/Algorithm.tcc"
47
48using namespace Mantid::Kernel;
49
50namespace Mantid {
51namespace API {
52namespace {
54const std::string WORKSPACE_TYPES_SEPARATOR = ";";
55
58const size_t DELAY_BEFORE_GC = 5;
59
60class WorkspacePropertyValueIs {
61public:
62 explicit WorkspacePropertyValueIs(const std::string &value) : m_value(value) {}
63 bool operator()(IWorkspaceProperty *property) {
64 auto *prop = dynamic_cast<Property *>(property);
65 if (!prop)
66 return false;
67 return prop->value() == m_value;
68 }
69
70private:
71 const std::string &m_value;
72};
73
74template <typename T> struct RunOnFinish {
75 RunOnFinish(T &&task) : m_onfinsh(std::move(task)) {}
76 ~RunOnFinish() { m_onfinsh(); }
77
78private:
80};
81
82} // namespace
83
84// Doxygen can't handle member specialization at the moment:
85// https://bugzilla.gnome.org/show_bug.cgi?id=406027
86// so we have to ignore them
88template <typename NumT> bool Algorithm::isEmpty(const NumT toCheck) {
89 return static_cast<int>(toCheck) == EMPTY_INT();
90}
91
92template <> MANTID_API_DLL bool Algorithm::isEmpty(const double toCheck) {
93 return std::abs((toCheck - EMPTY_DBL()) / (EMPTY_DBL())) < 1e-8;
94}
95
96// concrete instantiations
97template MANTID_API_DLL bool Algorithm::isEmpty<int>(const int);
98template MANTID_API_DLL bool Algorithm::isEmpty<int64_t>(const int64_t);
99template MANTID_API_DLL bool Algorithm::isEmpty<std::size_t>(const std::size_t);
101
102//=============================================================================================
103//================================== Constructors/Destructors
104//=================================
105//=============================================================================================
106
108size_t Algorithm::g_execCount = 0;
109
112 : m_cancel(false), m_parallelException(false), m_log("Algorithm"), g_log(m_log), m_groupSize(0),
113 m_executeAsync(nullptr), m_notificationCenter(nullptr), m_progressObserver(nullptr),
114 m_executionState(ExecutionState::Uninitialized), m_resultState(ResultState::NotFinished),
115 m_isChildAlgorithm(false), m_recordHistoryForChild(false), m_alwaysStoreInADS(true), m_runningAsync(false),
116 m_rethrow(false), m_isAlgStartupLoggingEnabled(true), m_startChildProgress(0.), m_endChildProgress(0.),
117 m_algorithmID(this), m_singleGroup(-1), m_groupsHaveSimilarNames(false), m_inputWorkspaceHistories(),
118 m_communicator(std::make_unique<Parallel::Communicator>()), m_properties() {}
119
121Algorithm::~Algorithm() = default;
122
123//=============================================================================================
124//================================== Simple Getters/Setters
125//===================================
126//=============================================================================================
127
130
133
136
140 if (state != ResultState::NotFinished) {
142 }
143 m_resultState = state;
144}
145
146//---------------------------------------------------------------------------------------------
149
153}
154
155//---------------------------------------------------------------------------------------------
161
166void Algorithm::setChild(const bool isChild) {
168 this->setAlwaysStoreInADS(!isChild);
169}
170
177
183void Algorithm::setAlwaysStoreInADS(const bool doStore) { m_alwaysStoreInADS = doStore; }
184
189
193void Algorithm::setRethrows(const bool rethrow) { this->m_rethrow = rethrow; }
194
197
201 (Mantid::Types::Core::DateAndTime::getCurrentTime() > m_gcTime)) {
202 return true;
203 }
204 return false;
205}
206
207//---------------------------------------------------------------------------------------------
211void Algorithm::addObserver(const Poco::AbstractObserver &observer) const {
212 notificationCenter().addObserver(observer);
213}
214
218void Algorithm::removeObserver(const Poco::AbstractObserver &observer) const {
219 notificationCenter().removeObserver(observer);
220}
221
222//---------------------------------------------------------------------------------------------
231void Algorithm::progress(double p, const std::string &msg, double estimatedTime, int progressPrecision) {
232 notificationCenter().postNotification(new ProgressNotification(this, p, msg, estimatedTime, progressPrecision));
233}
234
235//---------------------------------------------------------------------------------------------
237const std::vector<std::string> Algorithm::categories() const {
241
242 auto res = tokenizer.asVector();
243
244 const auto *depo = dynamic_cast<const DeprecatedAlgorithm *>(this);
245 if (depo != nullptr) {
246 res.emplace_back("Deprecated");
247 }
248 return res;
249}
250
255const std::string Algorithm::workspaceMethodName() const { return ""; }
256
262const std::vector<std::string> Algorithm::workspaceMethodOn() const {
263 Mantid::Kernel::StringTokenizer tokenizer(this->workspaceMethodOnTypes(), WORKSPACE_TYPES_SEPARATOR,
266 return tokenizer.asVector();
267}
268
272const std::string Algorithm::workspaceMethodInputProperty() const { return ""; }
273
274//---------------------------------------------------------------------------------------------
284 // Bypass the initialization if the algorithm has already been initialized.
285 if (isInitialized())
286 return;
287
288 g_log.setName(this->name());
290 try {
291 try {
292 this->init();
294 } catch (std::runtime_error &) {
295 throw;
296 }
297
298 // Indicate that this Algorithm has been initialized to prevent duplicate
299 // attempts.
301 } catch (std::runtime_error &) {
302 throw;
303 }
304 // Unpleasant catch-all! Along with this, Gaudi version catches GaudiException
305 // & std::exception
306 // but doesn't really do anything except (print fatal) messages.
307 catch (...) {
308 // Gaudi: A call to the auditor service is here
309 // (1) perform the printout
310 getLogger().fatal("UNKNOWN Exception is caught in initialize()");
311 throw;
312 }
313}
314
315//---------------------------------------------------------------------------------------------
324std::map<std::string, std::string> Algorithm::validateInputs() { return std::map<std::string, std::string>(); }
325
326//---------------------------------------------------------------------------------------------
332 m_inputWorkspaceProps.clear();
335 const auto &props = this->getProperties();
336 for (const auto &prop : props) {
337 auto wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
338 if (!wsProp)
339 continue;
340 switch (prop->direction()) {
342 m_inputWorkspaceProps.emplace_back(wsProp);
343 break;
345 m_inputWorkspaceProps.emplace_back(wsProp);
346 m_outputWorkspaceProps.emplace_back(wsProp);
347 break;
349 m_outputWorkspaceProps.emplace_back(wsProp);
350 m_pureOutputWorkspaceProps.emplace_back(wsProp);
351 break;
352 default:
353 throw std::logic_error("Unexpected property direction found for property " + prop->name() + " of algorithm " +
354 this->name());
355 }
356 }
357}
358
364 if (!trackingHistory())
365 return;
366
367 auto cacheHistories = [this](const Workspace_sptr &ws) {
368 if (auto group = dynamic_cast<const WorkspaceGroup *>(ws.get())) {
369 m_inputWorkspaceHistories.reserve(m_inputWorkspaceHistories.size() + group->size());
370 std::copy(group->begin(), group->end(), std::back_inserter(m_inputWorkspaceHistories));
371 } else {
372 m_inputWorkspaceHistories.emplace_back(ws);
373 }
374 };
375 using ArrayPropertyString = ArrayProperty<std::string>;
376 auto isADSValidator = [](const IValidator_sptr &validator) -> bool {
377 if (!validator)
378 return false;
379 if (dynamic_cast<ADSValidator *>(validator.get()))
380 return true;
381 if (const auto compValidator = dynamic_cast<CompositeValidator *>(validator.get()))
382 return compValidator->contains<ADSValidator>();
383
384 return false;
385 };
386
387 // Look over all properties so we can catch an string array properties
388 // with an ADSValidator. ADSValidator indicates that the strings
389 // point to workspace names so we want to pick up the history from these too.
390 const auto &ads = AnalysisDataService::Instance();
392 const auto &props = this->getProperties();
393 for (const auto &prop : props) {
394 if (prop->direction() != Direction::Input && prop->direction() != Direction::InOut)
395 continue;
396
397 if (auto wsProp = dynamic_cast<IWorkspaceProperty *>(prop)) {
398 if (auto ws = wsProp->getWorkspace()) {
399 cacheHistories(ws);
400 } else {
401 Workspace_sptr wsFromADS;
402 try {
403 wsFromADS = ads.retrieve(prop->value());
404 } catch (Exception::NotFoundError &) {
405 continue;
406 }
407 cacheHistories(wsFromADS);
408 }
409 } else if (auto strArrayProp = dynamic_cast<ArrayPropertyString *>(prop)) {
410 if (!isADSValidator(strArrayProp->getValidator()))
411 continue;
412 const auto &wsNames((*strArrayProp)());
413 for (const auto &name : wsNames) {
414 cacheHistories(ads.retrieve(name));
415 }
416 }
417 }
418} // namespace API
419
420//---------------------------------------------------------------------------------------------
426 // Do not lock workspace for child algos
427 if (this->isChild())
428 return;
429
430 if (!m_readLockedWorkspaces.empty() || !m_writeLockedWorkspaces.empty())
431 throw std::logic_error("Algorithm::lockWorkspaces(): The workspaces have "
432 "already been locked!");
433
434 // First, Write-lock the output workspaces
435 auto &debugLog = g_log.debug();
436 for (auto &outputWorkspaceProp : m_outputWorkspaceProps) {
437 Workspace_sptr ws = outputWorkspaceProp->getWorkspace();
438 if (ws) {
439 // The workspace property says to do locking,
440 // AND it has NOT already been write-locked
441 if (outputWorkspaceProp->isLocking() && std::find(m_writeLockedWorkspaces.begin(), m_writeLockedWorkspaces.end(),
442 ws) == m_writeLockedWorkspaces.end()) {
443 // Write-lock it if not already
444 debugLog << "Write-locking " << ws->getName() << '\n';
445 ws->getLock()->writeLock();
446 m_writeLockedWorkspaces.emplace_back(ws);
447 }
448 }
449 }
450
451 // Next read-lock the input workspaces
452 for (auto &inputWorkspaceProp : m_inputWorkspaceProps) {
453 Workspace_sptr ws = inputWorkspaceProp->getWorkspace();
454 if (ws) {
455 // The workspace property says to do locking,
456 // AND it has NOT already been write-locked
457 if (inputWorkspaceProp->isLocking() && std::find(m_writeLockedWorkspaces.begin(), m_writeLockedWorkspaces.end(),
458 ws) == m_writeLockedWorkspaces.end()) {
459 // Read-lock it if not already write-locked
460 debugLog << "Read-locking " << ws->getName() << '\n';
461 ws->getLock()->readLock();
462 m_readLockedWorkspaces.emplace_back(ws);
463 }
464 }
465 }
466}
467
468//---------------------------------------------------------------------------------------------
473 // Do not lock workspace for child algos
474 if (this->isChild())
475 return;
476 auto &debugLog = g_log.debug();
477 for (auto &ws : m_writeLockedWorkspaces) {
478 if (ws) {
479 debugLog << "Unlocking " << ws->getName() << '\n';
480 ws->getLock()->unlock();
481 }
482 }
483 for (auto &ws : m_readLockedWorkspaces) {
484 if (ws) {
485 debugLog << "Unlocking " << ws->getName() << '\n';
486 ws->getLock()->unlock();
487 }
488 }
489
490 // Don't double-unlock workspaces
493}
494
500 m_groupWorkspaces.clear();
502 m_inputWorkspaceProps.clear();
506}
507
508//---------------------------------------------------------------------------------------------
513 Timer timer;
514 bool algIsExecuted = false;
515 AlgorithmManager::Instance().notifyAlgorithmStarting(this->getAlgorithmID());
516
517 // runtime check for deprecation warning
518 {
519 auto *depo = dynamic_cast<DeprecatedAlgorithm *>(this);
520 if (depo != nullptr)
521 getLogger().error(depo->deprecationMsg(this));
522 }
523
524 // runtime check for deprecated alias warning
525 {
526 auto *da_alg = dynamic_cast<DeprecatedAlias *>(this);
527 if ((da_alg != nullptr) && (this->calledByAlias))
528 getLogger().warning(da_alg->deprecationMessage(this));
529 }
530
531 // Register clean up tasks that should happen regardless of the route
532 // out of the algorithm. These tasks will get run after this method
533 // finishes.
534 RunOnFinish onFinish([this]() { this->clearWorkspaceCaches(); });
535
536 notificationCenter().postNotification(new StartedNotification(this));
537 Mantid::Types::Core::DateAndTime startTime;
538
539 // Return a failure if the algorithm hasn't been initialized
540 if (!isInitialized()) {
541 throw std::runtime_error("Algorithm is not initialised:" + this->name());
542 }
543
544 // no logging of input if a child algorithm (except for python child algos)
547
548 // Check all properties for validity
549 constexpr bool resetTimer{true};
550 float timingInit = timer.elapsed(resetTimer);
551 if (!validateProperties()) {
552 // Reset name on input workspaces to trigger attempt at collection from ADS
553 const auto &props = getProperties();
554 for (auto &prop : props) {
555 auto wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
556 if (wsProp && !(wsProp->getWorkspace())) {
557 // Setting it's name to the same one it already had
558 prop->setValue(prop->value());
559 }
560 }
561 // Try the validation again
562 if (!validateProperties()) {
563 notificationCenter().postNotification(new ErrorNotification(this, "Some invalid Properties found"));
564 throw std::runtime_error("Some invalid Properties found");
565 }
566 }
567 const float timingPropertyValidation = timer.elapsed(resetTimer);
568
569 // All properties are now valid - cache workspace properties and histories
572
573 // ----- Check for processing groups -------------
574 // default true so that it has the right value at the check below the catch
575 // block should checkGroups throw
576 bool callProcessGroups = true;
577 try {
578 // Checking the input is a group. Throws if the sizes are wrong
579 callProcessGroups = this->checkGroups();
580 } catch (std::exception &ex) {
581 getLogger().error() << "Error in execution of algorithm " << this->name() << "\n" << ex.what() << "\n";
582 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
585 m_runningAsync = false;
586 throw;
587 }
588 return false;
589 }
590
591 const auto executionMode = getExecutionMode();
592
593 timingInit += timer.elapsed(resetTimer);
594 // ----- Perform validation of the whole set of properties -------------
595 if ((!callProcessGroups) && (executionMode != Parallel::ExecutionMode::MasterOnly ||
596 communicator().rank() == 0)) // for groups this is called on each
597 // workspace separately
598 {
599 std::map<std::string, std::string> errors = this->validateInputs();
600 if (!errors.empty()) {
601 size_t numErrors = errors.size();
602 // Log each issue
603 auto &errorLog = getLogger().error();
604 auto &warnLog = getLogger().warning();
605 for (auto &error : errors) {
606 if (this->existsProperty(error.first))
607 errorLog << "Invalid value for " << error.first << ": " << error.second << "\n";
608 else {
609 numErrors -= 1; // don't count it as an error
610 warnLog << "validateInputs() references non-existant property \"" << error.first << "\"\n";
611 }
612 }
613 // Throw because something was invalid
614 if (numErrors > 0) {
615 std::stringstream msg;
616 msg << "Some invalid Properties found: ";
617 for (auto &error : errors) {
618 msg << "\n " << error.first << ": " << error.second;
619 }
620 notificationCenter().postNotification(new ErrorNotification(this, "Some invalid Properties found"));
621 throw std::runtime_error(msg.str());
622 }
623 }
624 }
625 const float timingInputValidation = timer.elapsed(resetTimer);
626
627 if (trackingHistory()) {
628 // count used for defining the algorithm execution order
629 // If history is being recorded we need to count this as a separate
630 // algorithm
631 // as the history compares histories by their execution number
633
634 // populate history record before execution so we can record child
635 // algorithms in it
636 AlgorithmHistory algHist;
637 m_history = std::make_shared<AlgorithmHistory>(algHist);
638 }
639
640 // ----- Process groups -------------
641 // If checkGroups() threw an exception but there ARE group workspaces
642 // (means that the group sizes were incompatible)
643 if (callProcessGroups) {
644 return doCallProcessGroups(startTime);
645 }
646
647 // Read or write locks every input/output workspace
648 this->lockWorkspaces();
649 timingInit += timer.elapsed(resetTimer);
650
651 // Invoke exec() method of derived class and catch all uncaught exceptions
652 try {
653 try {
655
656 startTime = Mantid::Types::Core::DateAndTime::getCurrentTime();
657 // Call the concrete algorithm's exec method
658 this->exec(executionMode);
660 // Check for a cancellation request in case the concrete algorithm doesn't
662 const float timingExec = timer.elapsed(resetTimer);
663 // The total runtime including all init steps is used for general logging.
664 const float duration = timingInit + timingPropertyValidation + timingInputValidation + timingExec;
665 // need it to throw before trying to run fillhistory() on an algorithm
666 // which has failed
667 if (trackingHistory() && m_history) {
668 m_history->fillAlgorithmHistory(this, startTime, duration, Algorithm::g_execCount);
669 fillHistory();
671 }
672
673 // Put the output workspaces into the AnalysisDataService - if requested
675 this->store();
676
677 // just cache the value internally, it is set at the very end of this
678 // method
679 algIsExecuted = true;
680
681 // Log that execution has completed.
682 getLogger().debug("Time to validate properties: " + std::to_string(timingPropertyValidation) + " seconds\n" +
683 "Time for other input validation: " + std::to_string(timingInputValidation) + " seconds\n" +
684 "Time for other initialization: " + std::to_string(timingInit) + " seconds\n" +
685 "Time to run exec: " + std::to_string(timingExec) + " seconds\n");
686 reportCompleted(duration);
687 } catch (std::runtime_error &ex) {
688 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
689 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
691 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
692 this->unlockWorkspaces();
694 throw;
695 else {
696 getLogger().error() << "Error in execution of algorithm " << this->name() << '\n' << ex.what() << '\n';
697 }
698
699 } catch (std::logic_error &ex) {
700 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
701 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
702 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
704 this->unlockWorkspaces();
706 throw;
707 else {
708 getLogger().error() << "Logic Error in execution of algorithm " << this->name() << '\n' << ex.what() << '\n';
709 }
710 }
711 } catch (CancelException &ex) {
712 m_runningAsync = false;
713 getLogger().warning() << this->name() << ": Execution cancelled by user.\n";
714 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
715 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
717 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
718 this->unlockWorkspaces();
719
720 throw;
721 }
722 // Gaudi also specifically catches GaudiException & std:exception.
723 catch (std::exception &ex) {
724 m_runningAsync = false;
725 getLogger().error() << "Error in execution of algorithm " << this->name() << ":\n" << ex.what() << "\n";
726 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
727 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
729 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
730 this->unlockWorkspaces();
731
732 throw;
733 }
734
735 catch (...) {
736 // Execution failed with an unknown exception object
737 m_runningAsync = false;
738
739 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
740 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
742 notificationCenter().postNotification(new ErrorNotification(this, "UNKNOWN Exception is caught in exec()"));
743 getLogger().error() << this->name() << ": UNKNOWN Exception is caught in exec()\n";
744 this->unlockWorkspaces();
745
746 throw;
747 }
748
749 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
750 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
751 if (algIsExecuted) {
753 }
754
755 // Only gets to here if algorithm ended normally
756 notificationCenter().postNotification(new FinishedNotification(this, isExecuted()));
757
758 // Unlock the workspaces once the notification has been sent, to prevent too early deletion
759 this->unlockWorkspaces();
760
761 return isExecuted();
762}
763
764//---------------------------------------------------------------------------------------------
770 bool executed = false;
771 try {
772 executed = execute();
773 } catch (std::runtime_error &) {
774 throw;
775 }
776
777 if (!executed) {
778 throw std::runtime_error("Unable to successfully run ChildAlgorithm " + this->name());
779 }
780}
781
782//---------------------------------------------------------------------------------------------
788 const std::vector<Property *> &props = getProperties();
789 std::vector<int> groupWsIndicies;
790
791 // add any regular/child workspaces first, then add the groups
792 for (unsigned int i = 0; i < props.size(); ++i) {
793 auto *wsProp = dynamic_cast<IWorkspaceProperty *>(props[i]);
794 if (wsProp) {
795 // check if the workspace is a group, if so remember where it is and add
796 // it later
797 auto group = std::dynamic_pointer_cast<WorkspaceGroup>(wsProp->getWorkspace());
798 if (!group) {
799 try {
800 wsProp->store();
801 } catch (std::runtime_error &) {
802 throw;
803 }
804 } else {
805 groupWsIndicies.emplace_back(i);
806 }
807 }
808 }
809
810 // now store workspace groups once their members have been added
811 std::vector<int>::const_iterator wsIndex;
812 for (wsIndex = groupWsIndicies.begin(); wsIndex != groupWsIndicies.end(); ++wsIndex) {
813 auto *wsProp = dynamic_cast<IWorkspaceProperty *>(props[*wsIndex]);
814 if (wsProp) {
815 try {
816 wsProp->store();
817 } catch (std::runtime_error &) {
818 throw;
819 }
820 }
821 }
822}
823
824//---------------------------------------------------------------------------------------------
842Algorithm_sptr Algorithm::createChildAlgorithm(const std::string &name, const double startProgress,
843 const double endProgress, const bool enableLogging, const int &version) {
844 Algorithm_sptr alg = AlgorithmManager::Instance().createUnmanaged(name, version);
845 setupAsChildAlgorithm(alg, startProgress, endProgress, enableLogging);
846 return alg;
847}
848
855void Algorithm::setupAsChildAlgorithm(const Algorithm_sptr &alg, const double startProgress, const double endProgress,
856 const bool enableLogging) {
857 // set as a child
858 alg->setChild(true);
859 alg->setLogging(enableLogging);
860
861 // Initialise the Child Algorithm
862 try {
863 alg->initialize();
864 } catch (std::runtime_error &) {
865 throw std::runtime_error("Unable to initialise Child Algorithm '" + alg->name() + "'");
866 }
867
868 // If output workspaces are nameless, give them a temporary name to satisfy
869 // validator
870 const std::vector<Property *> &props = alg->getProperties();
871 for (auto prop : props) {
872 auto wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
873 if (prop->direction() == Mantid::Kernel::Direction::Output && wsProp) {
874 if (prop->value().empty() && !wsProp->isOptional()) {
875 prop->createTemporaryValue();
876 }
877 }
878 }
879
880 if (startProgress >= 0.0 && endProgress > startProgress && endProgress <= 1.0) {
881 alg->addObserver(this->progressObserver());
882 m_startChildProgress = startProgress;
883 m_endChildProgress = endProgress;
884 }
885
886 // Before we return the shared pointer, use it to create a weak pointer and
887 // keep that in a vector.
888 // It will be used this to pass on cancellation requests
889 // It must be protected by a critical block so that Child Algorithms can run
890 // in parallel safely.
891 std::weak_ptr<IAlgorithm> weakPtr(alg);
892 PARALLEL_CRITICAL(Algorithm_StoreWeakPtr) { m_ChildAlgorithms.emplace_back(weakPtr); }
893}
894
895//=============================================================================================
896//================================== Algorithm History
897//========================================
898//=============================================================================================
899
905std::string Algorithm::toString() const { return Mantid::JsonHelpers::jsonToString(toJson()); }
906
911::Json::Value Algorithm::toJson() const {
912 ::Json::Value root;
913
914 root["name"] = name();
915 root["version"] = this->version();
916 root["properties"] = m_properties.asJson(false);
917
918 return root;
919}
920
921//--------------------------------------------------------------------------------------------
930 ::Json::Value root;
931 ::Json::Value jsonMap;
932
933 auto props = history.getProperties();
934 const size_t numProps(props.size());
935 for (size_t i = 0; i < numProps; ++i) {
936 PropertyHistory_sptr prop = props[i];
937 if (!prop->isDefault()) {
938 jsonMap[prop->name()] = prop->value();
939 }
940 }
941
942 root["name"] = history.name();
943 root["version"] = history.version();
944 root["properties"] = jsonMap;
945
946 const std::string output = Mantid::JsonHelpers::jsonToString(root);
947 IAlgorithm_sptr alg;
948
949 try {
950 alg = Algorithm::fromString(output);
951 } catch (std::invalid_argument &) {
952 throw std::runtime_error("Could not create algorithm from history. "
953 "Is this a child algorithm whose workspaces are not in the ADS?");
954 }
955 return alg;
956}
957
958//--------------------------------------------------------------------------------------------
967IAlgorithm_sptr Algorithm::fromString(const std::string &input) {
968 ::Json::Value root;
969 if (Mantid::JsonHelpers::parse(input, &root)) {
970 return fromJson(root);
971 } else {
972 throw std::runtime_error("Cannot create algorithm, invalid string format.");
973 }
974}
975
983IAlgorithm_sptr Algorithm::fromJson(const Json::Value &serialized) {
984 const std::string algName = serialized["name"].asString();
985 const int version = serialized.get("version", -1).asInt();
986 auto alg = AlgorithmManager::Instance().createUnmanaged(algName, version);
987 alg->initialize();
988 alg->setProperties(serialized["properties"]);
989 return alg;
990}
991
995 WorkspaceVector outputWorkspaces;
996 if (!isChild()) {
997 findWorkspaces(outputWorkspaces, Direction::Output);
998 }
999 fillHistory(outputWorkspaces);
1000}
1001
1012 return;
1013
1014 // iterate over the algorithms output workspaces
1015 const auto &algProperties = getProperties();
1016 for (const auto &prop : algProperties) {
1017 if (prop->direction() != Kernel::Direction::Output && prop->direction() != Kernel::Direction::InOut)
1018 continue;
1019 const auto *wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
1020 if (!wsProp)
1021 continue;
1022 // Check we actually have a workspace, it may have been optional
1023 Workspace_sptr workspace = wsProp->getWorkspace();
1024 if (!workspace)
1025 continue;
1026
1027 bool linked = false;
1028 // find child histories with anonymous output workspaces
1029 const auto &childHistories = m_history->getChildHistories();
1030 auto childIter = childHistories.rbegin();
1031 for (; childIter != childHistories.rend() && !linked; ++childIter) {
1032 const auto &props = (*childIter)->getProperties();
1033 auto propIter = props.begin();
1034 for (; propIter != props.end() && !linked; ++propIter) {
1035 // check we have a workspace property
1036 if ((*propIter)->direction() == Kernel::Direction::Output ||
1037 (*propIter)->direction() == Kernel::Direction::InOut) {
1038 // if the workspaces are equal, then rename the history
1039 std::ostringstream os;
1040 os << "__TMP" << wsProp->getWorkspace().get();
1041 if (os.str() == (*propIter)->value()) {
1042 (*propIter)->setValue(prop->value());
1043 linked = true;
1044 }
1045 }
1046 }
1047 }
1048 }
1049}
1050
1055void Algorithm::trackAlgorithmHistory(std::shared_ptr<AlgorithmHistory> parentHist) {
1057 m_parentHistory = std::move(parentHist);
1058}
1059
1064
1073void Algorithm::findWorkspaces(WorkspaceVector &workspaces, unsigned int direction, bool checkADS) const {
1074 auto workspaceFromWSProperty = [](const IWorkspaceProperty &prop, const AnalysisDataServiceImpl &ads,
1075 const std::string &strValue, bool checkADS) {
1076 auto workspace = prop.getWorkspace();
1077 if (workspace)
1078 return workspace;
1079
1080 // Empty string indicates optional workspace
1081 if (checkADS && !strValue.empty()) {
1082 return ads.retrieve(strValue);
1083 }
1084 return Workspace_sptr();
1085 };
1086 auto appendWS = [&workspaces](const Workspace_sptr &workspace) {
1087 if (!workspace)
1088 return false;
1089 workspaces.emplace_back(workspace);
1090 return true;
1091 };
1092
1093 // Additional output properties can be declared on the fly
1094 // so we need a fresh loop over the properties
1095 const auto &algProperties = getProperties();
1096 const auto &ads = AnalysisDataService::Instance();
1097 for (const auto &prop : algProperties) {
1098 const unsigned int propDirection = prop->direction();
1099 if (propDirection != direction && propDirection != Direction::InOut)
1100 continue;
1101 if (const auto wsProp = dynamic_cast<IWorkspaceProperty *>(prop)) {
1102 appendWS(workspaceFromWSProperty(*wsProp, ads, prop->value(), checkADS));
1103 }
1104 }
1105}
1106
1109 auto &logger = getLogger();
1110
1112 logger.notice() << name() << " started";
1113 if (this->isChild())
1114 logger.notice() << " (child)";
1115 logger.notice() << '\n';
1116 // Make use of the AlgorithmHistory class, which holds all the info we
1117 // want here
1118 AlgorithmHistory algHistory(this);
1119 size_t maxPropertyLength = 40;
1120 if (logger.is(Logger::Priority::PRIO_DEBUG)) {
1121 // include the full property value when logging in debug
1122 maxPropertyLength = 0;
1123 }
1124 algHistory.printSelf(logger.information(), 0, maxPropertyLength);
1125 }
1126}
1127
1128//=============================================================================================
1129//================================== WorkspaceGroup-related
1130//===================================
1131//=============================================================================================
1132
1155 size_t numGroups = 0;
1156 bool processGroups = false;
1157
1158 // Unroll the groups or single inputs into vectors of workspaces
1159 const auto &ads = AnalysisDataService::Instance();
1161 m_groupWorkspaces.clear();
1162 for (auto inputWorkspaceProp : m_inputWorkspaceProps) {
1163 auto prop = dynamic_cast<Property *>(inputWorkspaceProp);
1164 auto wsGroupProp = dynamic_cast<WorkspaceProperty<WorkspaceGroup> *>(prop);
1165 auto ws = inputWorkspaceProp->getWorkspace();
1166 auto wsGroup = std::dynamic_pointer_cast<WorkspaceGroup>(ws);
1167
1168 // Workspace groups are NOT returned by IWP->getWorkspace() most of the
1169 // time because WorkspaceProperty is templated by <MatrixWorkspace> and
1170 // WorkspaceGroup does not subclass <MatrixWorkspace>
1171 if (!wsGroup && prop && !prop->value().empty()) {
1172 // So try to use the name in the AnalysisDataService
1173 try {
1174 wsGroup = ads.retrieveWS<WorkspaceGroup>(prop->value());
1175 } catch (Exception::NotFoundError &) { /* Do nothing */
1176 }
1177 }
1178
1179 // Found the group either directly or by name?
1180 // If the property is of type WorkspaceGroup then don't unroll
1181 if (wsGroup && !wsGroupProp) {
1182 numGroups++;
1183 processGroups = true;
1184 m_unrolledInputWorkspaces.emplace_back(wsGroup->getAllItems());
1185 } else {
1186 // Single Workspace. Treat it as a "group" with only one member
1187 if (ws)
1189 else
1191 }
1192
1193 // Add to the list of groups
1194 m_groupWorkspaces.emplace_back(wsGroup);
1195 }
1196
1197 // No groups? Get out.
1198 if (numGroups == 0)
1199 return processGroups;
1200
1201 // ---- Confirm that all the groups are the same size -----
1202 // Index of the single group
1203 m_singleGroup = -1;
1204 // Size of the single or of all the groups
1205 m_groupSize = 1;
1207 for (size_t i = 0; i < m_unrolledInputWorkspaces.size(); i++) {
1208 const auto &thisGroup = m_unrolledInputWorkspaces[i];
1209 // We're ok with empty groups if the workspace property is optional
1210 if (thisGroup.empty() && !m_inputWorkspaceProps[i]->isOptional())
1211 throw std::invalid_argument("Empty group passed as input");
1212 if (!thisGroup.empty()) {
1213 // Record the index of the single group.
1215 if (wsGroup && (numGroups == 1))
1216 m_singleGroup = int(i);
1217
1218 // For actual groups (>1 members)
1219 if (thisGroup.size() > 1) {
1220 // Check for matching group size
1221 if (m_groupSize > 1)
1222 if (thisGroup.size() != m_groupSize)
1223 throw std::invalid_argument("Input WorkspaceGroups are not of the same size.");
1224
1225 // Are ALL the names similar?
1226 if (wsGroup)
1227 m_groupsHaveSimilarNames = m_groupsHaveSimilarNames && wsGroup->areNamesSimilar();
1228
1229 // Save the size for the next group
1230 m_groupSize = thisGroup.size();
1231 }
1232 }
1233 } // end for each group
1234
1235 // If you get here, then the groups are compatible
1236 return processGroups;
1237}
1238
1247bool Algorithm::doCallProcessGroups(Mantid::Types::Core::DateAndTime &startTime) {
1248 // In the base implementation of processGroups, this normally calls
1249 // this->execute() again on each member of the group. Other algorithms may
1250 // choose to override that behavior (examples: CompareWorkspaces,
1251 // CheckWorkspacesMatch, RenameWorkspace)
1252
1253 startTime = Mantid::Types::Core::DateAndTime::getCurrentTime();
1254 // Start a timer
1255 Timer timer;
1256 bool completed = false;
1257 try {
1258 // Call the concrete algorithm's processGroups method
1259 completed = processGroups();
1260 } catch (std::exception &ex) {
1261 // The child algorithm will already have logged the error etc.,
1262 // but we also need to update flags in the parent algorithm and
1263 // send an ErrorNotification (because the child isn't registered with the
1264 // AlgorithmMonitor).
1266 m_runningAsync = false;
1267 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
1268 throw;
1269 } catch (...) {
1271 m_runningAsync = false;
1272 notificationCenter().postNotification(new ErrorNotification(this, "UNKNOWN Exception caught from processGroups"));
1273 throw;
1274 }
1275
1276 // Check for a cancellation request in case the concrete algorithm doesn't
1278
1279 if (completed) {
1280 // Get how long this algorithm took to run
1281 const float duration = timer.elapsed();
1282
1283 m_history = std::make_shared<AlgorithmHistory>(this, startTime, duration, ++g_execCount);
1284 if (trackingHistory() && m_history) {
1285 // find any further outputs created by the execution
1286 WorkspaceVector outputWorkspaces;
1287 const bool checkADS{true};
1288 findWorkspaces(outputWorkspaces, Direction::Output, checkADS);
1289 fillHistory(outputWorkspaces);
1290 }
1291
1292 // in the base processGroups each individual exec stores its outputs
1294 this->store();
1295
1296 // Log that execution has completed.
1297 reportCompleted(duration, true /* this is for group processing*/);
1299 } else {
1301 }
1302
1303 notificationCenter().postNotification(new FinishedNotification(this, isExecuted()));
1304
1305 return completed;
1306}
1307
1315void Algorithm::fillHistory(const std::vector<Workspace_sptr> &outputWorkspaces) {
1316 // this is not a child algorithm. Add the history algorithm to the
1317 // WorkspaceHistory object.
1318 if (!isChild()) {
1319 auto copyHistoryToGroup = [](const Workspace &in, WorkspaceGroup &out) {
1320 for (auto &outGroupItem : out) {
1321 outGroupItem->history().addHistory(in.getHistory());
1322 }
1323 };
1324
1325 for (auto &outWS : outputWorkspaces) {
1326 auto outWSGroup = std::dynamic_pointer_cast<WorkspaceGroup>(outWS);
1327 // Copy the history from the cached input workspaces to the output ones
1328 for (const auto &inputWS : m_inputWorkspaceHistories) {
1329 if (outWSGroup) {
1330 copyHistoryToGroup(*inputWS, *outWSGroup);
1331 } else {
1332 outWS->history().addHistory(inputWS->getHistory());
1333 }
1334 }
1335 // Add history for this operation
1336 if (outWSGroup) {
1337 for (auto &outGroupItem : *outWSGroup) {
1338 outGroupItem->history().addHistory(m_history);
1339 }
1340 } else {
1341 // Add the history for the current algorithm to all the output
1342 // workspaces
1343 outWS->history().addHistory(m_history);
1344 }
1345 }
1346 }
1347 // this is a child algorithm, but we still want to keep the history.
1349 m_parentHistory->addChildHistory(m_history);
1350 }
1351}
1352
1353//--------------------------------------------------------------------------------------------
1367
1368 std::vector<WorkspaceGroup_sptr> outGroups;
1369
1370 // ---------- Create all the output workspaces ----------------------------
1371 for (auto &pureOutputWorkspaceProp : m_pureOutputWorkspaceProps) {
1372 auto *prop = dynamic_cast<Property *>(pureOutputWorkspaceProp);
1373 if (prop && !prop->value().empty()) {
1374 auto outWSGrp = std::make_shared<WorkspaceGroup>();
1375 outGroups.emplace_back(outWSGrp);
1376 // Put the GROUP in the ADS
1377 AnalysisDataService::Instance().addOrReplace(prop->value(), outWSGrp);
1378 outWSGrp->observeADSNotifications(false);
1379 }
1380 }
1381
1382 double progress_proportion = 1.0 / static_cast<double>(m_groupSize);
1383 // Go through each entry in the input group(s)
1384 for (size_t entry = 0; entry < m_groupSize; entry++) {
1385 // use create Child Algorithm that look like this one
1386 Algorithm_sptr alg_sptr = this->createChildAlgorithm(this->name(), progress_proportion * static_cast<double>(entry),
1387 progress_proportion * (1 + static_cast<double>(entry)),
1388 this->isLogging(), this->version());
1389 // Make a child algorithm and turn off history recording for it, but always
1390 // store result in the ADS
1391 alg_sptr->setChild(true);
1392 alg_sptr->setAlwaysStoreInADS(true);
1393 alg_sptr->enableHistoryRecordingForChild(false);
1394 alg_sptr->setRethrows(true);
1395
1396 Algorithm *alg = alg_sptr.get();
1397 // Set all non-workspace properties
1398 this->copyNonWorkspaceProperties(alg, int(entry) + 1);
1399
1400 std::string outputBaseName;
1401
1402 // ---------- Set all the input workspaces ----------------------------
1403 for (size_t iwp = 0; iwp < m_unrolledInputWorkspaces.size(); iwp++) {
1404 std::vector<Workspace_sptr> &thisGroup = m_unrolledInputWorkspaces[iwp];
1405 if (!thisGroup.empty()) {
1406 // By default (for a single group) point to the first/only workspace
1407 Workspace_sptr ws = thisGroup[0];
1408
1409 if ((m_singleGroup == int(iwp)) || m_singleGroup < 0) {
1410 // Either: this is the single group
1411 // OR: all inputs are groups
1412 // ... so get then entry^th workspace in this group
1413 if (entry < thisGroup.size()) {
1414 ws = thisGroup[entry];
1415 } else {
1416 // This can happen when one has more than one input group
1417 // workspaces, having different sizes. For example one workspace
1418 // group is the corrections which has N parts (e.g. weights for
1419 // polarized measurement) while the other one is the actual input
1420 // workspace group, where each item needs to be corrected together
1421 // with all N inputs of the second group. In this case processGroup
1422 // needs to be overridden, which is currently not possible in
1423 // python.
1424 throw std::runtime_error("Unable to process over groups; consider passing workspaces "
1425 "one-by-one or override processGroup method of the algorithm.");
1426 }
1427 }
1428 // Append the names together
1429 if (!outputBaseName.empty())
1430 outputBaseName += "_";
1431 outputBaseName += ws->getName();
1432
1433 // Set the property using the name of that workspace
1434 if (auto *prop = dynamic_cast<Property *>(m_inputWorkspaceProps[iwp])) {
1435 if (ws->getName().empty()) {
1436 alg->setProperty(prop->name(), ws);
1437 } else {
1438 alg->setPropertyValue(prop->name(), ws->getName());
1439 }
1440 } else {
1441 throw std::logic_error("Found a Workspace property which doesn't "
1442 "inherit from Property.");
1443 }
1444 } // not an empty (i.e. optional) input
1445 } // for each InputWorkspace property
1446
1447 std::vector<std::string> outputWSNames(m_pureOutputWorkspaceProps.size());
1448 // ---------- Set all the output workspaces ----------------------------
1449 for (size_t owp = 0; owp < m_pureOutputWorkspaceProps.size(); owp++) {
1450 if (auto *prop = dynamic_cast<Property *>(m_pureOutputWorkspaceProps[owp])) {
1451 // Default name = "in1_in2_out"
1452 const std::string inName = prop->value();
1453 if (inName.empty())
1454 continue;
1455 std::string outName;
1457 outName.append(inName).append("_").append(Strings::toString(entry + 1));
1458 } else {
1459 outName.append(outputBaseName).append("_").append(inName);
1460 }
1461
1462 auto inputProp =
1463 std::find_if(m_inputWorkspaceProps.begin(), m_inputWorkspaceProps.end(), WorkspacePropertyValueIs(inName));
1464
1465 // Overwrite workspaces in any input property if they have the same
1466 // name as an output (i.e. copy name button in algorithm dialog used)
1467 // (only need to do this for a single input, multiple will be handled
1468 // by ADS)
1469 if (inputProp != m_inputWorkspaceProps.end()) {
1470 const auto &inputGroup = m_unrolledInputWorkspaces[inputProp - m_inputWorkspaceProps.begin()];
1471 if (!inputGroup.empty())
1472 outName = inputGroup[entry]->getName();
1473 }
1474 // Except if all inputs had similar names, then the name is "out_1"
1475
1476 // Set in the output
1477 alg->setPropertyValue(prop->name(), outName);
1478
1479 outputWSNames[owp] = outName;
1480 } else {
1481 throw std::logic_error("Found a Workspace property which doesn't "
1482 "inherit from Property.");
1483 }
1484 } // for each OutputWorkspace property
1485
1486 // ------------ Execute the algo --------------
1487 try {
1488 alg->execute();
1489 } catch (std::exception &e) {
1490 std::ostringstream msg;
1491 msg << "Execution of " << this->name() << " for group entry " << (entry + 1) << " failed: ";
1492 msg << e.what(); // Add original message
1493 throw std::runtime_error(msg.str());
1494 }
1495
1496 // ------------ Fill in the output workspace group ------------------
1497 // this has to be done after execute() because a workspace must exist
1498 // when it is added to a group
1499 for (size_t owp = 0; owp < m_pureOutputWorkspaceProps.size(); owp++) {
1500 auto *prop = dynamic_cast<Property *>(m_pureOutputWorkspaceProps[owp]);
1501 if (prop && prop->value().empty())
1502 continue;
1503 // And add it to the output group
1504 outGroups[owp]->add(outputWSNames[owp]);
1505 }
1506
1507 } // for each entry in each group
1508
1509 // restore group notifications
1510 for (auto &outGroup : outGroups) {
1511 outGroup->observeADSNotifications(true);
1512 }
1513
1514 return true;
1515}
1516
1517//--------------------------------------------------------------------------------------------
1524 if (!alg)
1525 throw std::runtime_error("Algorithm not created!");
1526 const auto &props = this->getProperties();
1527 for (const auto &prop : props) {
1528 if (prop) {
1529
1530 auto *wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
1531 // Copy the property using the string
1532 if (!wsProp)
1533 this->setOtherProperties(alg, prop->name(), prop->value(), periodNum);
1534 }
1535 }
1536}
1537
1538//--------------------------------------------------------------------------------------------
1547void Algorithm::setOtherProperties(IAlgorithm *alg, const std::string &propertyName, const std::string &propertyValue,
1548 int periodNum) {
1549 (void)periodNum; // Avoid compiler warning
1550 if (alg)
1551 alg->setPropertyValue(propertyName, propertyValue);
1552}
1553
1554//--------------------------------------------------------------------------------------------
1560 if (!prop) {
1561 return false;
1562 }
1563 const auto *const wsProp = dynamic_cast<const IWorkspaceProperty *>(prop);
1564 return (wsProp != nullptr);
1565}
1566
1567//=============================================================================================
1568//================================== Asynchronous Execution
1569//===================================
1570//=============================================================================================
1571namespace {
1575struct AsyncFlagHolder {
1579 explicit AsyncFlagHolder(bool &running_flag) : m_running_flag(running_flag) { m_running_flag = true; }
1581 ~AsyncFlagHolder() { m_running_flag = false; }
1582
1583private:
1585 AsyncFlagHolder() = delete;
1588};
1589} // namespace
1590
1591//--------------------------------------------------------------------------------------------
1597 std::make_unique<Poco::ActiveMethod<bool, Poco::Void, Algorithm>>(this, &Algorithm::executeAsyncImpl);
1598 return (*m_executeAsync)(Poco::Void());
1599}
1600
1605bool Algorithm::executeAsyncImpl(const Poco::Void & /*unused*/) {
1606 AsyncFlagHolder running(m_runningAsync);
1607 return this->execute();
1608}
1609
1614Poco::NotificationCenter &Algorithm::notificationCenter() const {
1616 m_notificationCenter = std::make_unique<Poco::NotificationCenter>();
1617 return *m_notificationCenter;
1618}
1619
1623void Algorithm::handleChildProgressNotification(const Poco::AutoPtr<ProgressNotification> &pNf) {
1624 double p = m_startChildProgress + (m_endChildProgress - m_startChildProgress) * pNf->progress;
1625
1626 progress(p, pNf->message);
1627}
1628
1632const Poco::AbstractObserver &Algorithm::progressObserver() const {
1633 if (!m_progressObserver)
1634 m_progressObserver = std::make_unique<Poco::NObserver<Algorithm, ProgressNotification>>(
1636
1637 return *m_progressObserver;
1638}
1639
1640//--------------------------------------------------------------------------------------------
1645 // set myself to be cancelled
1646 m_cancel = true;
1647
1648 // Loop over the output workspaces and try to cancel them
1649 for (auto &weakPtr : m_ChildAlgorithms) {
1650 if (IAlgorithm_sptr sharedPtr = weakPtr.lock()) {
1651 sharedPtr->cancel();
1652 }
1653 }
1654}
1655
1657bool Algorithm::getCancel() const { return m_cancel; }
1658
1664bool Algorithm::isLogging() const { return g_log.getEnabled(); }
1665
1666/* Sets the logging priority offset. Values are subtracted from the log level.
1667 *
1668 * Example value=1 will turn warning into notice
1669 * Example value=-1 will turn notice into warning
1670 */
1672 if (m_communicator->rank() == 0)
1674 else {
1675 auto offset = ConfigService::Instance().getValue<int>("mpi.loggingOffset");
1676 g_log.setLevelOffset(value + offset.get_value_or(1));
1677 }
1678}
1679
1682
1683//--------------------------------------------------------------------------------------------
1688 // only throw exceptions if the code is not multi threaded otherwise you
1689 // contravene the OpenMP standard
1690 // that defines that all loops must complete, and no exception can leave an
1691 // OpenMP section
1692 // openmp cancel handling is performed using the ??, ?? and ?? macros in
1693 // each algrothim
1695 if (m_cancel)
1696 throw CancelException();
1697}
1698
1704void Algorithm::reportCompleted(const double &duration, const bool groupProcessing) {
1705 std::string optionalMessage;
1706 if (groupProcessing) {
1707 optionalMessage = ". Processed as a workspace group";
1708 }
1709
1712
1713 std::stringstream msg;
1714 msg << name() << " successful, Duration ";
1715 double seconds = duration;
1716 if (seconds > 60.) {
1717 auto minutes = static_cast<int>(seconds / 60.);
1718 msg << minutes << " minutes ";
1719 seconds = seconds - static_cast<double>(minutes) * 60.;
1720 }
1721 msg << std::fixed << std::setprecision(2) << seconds << " seconds" << optionalMessage;
1722 getLogger().notice(msg.str());
1723 }
1724 }
1725
1726 else {
1727 getLogger().debug() << name() << " finished with isChild = " << isChild() << '\n';
1728 }
1730}
1731
1735 if (UsageService::Instance().isEnabled()) {
1736 std::ostringstream oss;
1737 oss << this->name() << ".v" << this->version();
1738 UsageService::Instance().registerFeatureUsage(FeatureType::Algorithm, oss.str(), isChild());
1739 }
1740}
1741
1746
1751
1752bool Algorithm::isCompoundProperty(const std::string &name) const {
1753 return std::find(m_reservedList.cbegin(), m_reservedList.cend(), name) != m_reservedList.cend();
1754}
1755
1757void Algorithm::exec(Parallel::ExecutionMode executionMode) {
1758 switch (executionMode) {
1759 case Parallel::ExecutionMode::Serial:
1760 case Parallel::ExecutionMode::Identical:
1761 return exec();
1762 case Parallel::ExecutionMode::Distributed:
1763 return execDistributed();
1764 case Parallel::ExecutionMode::MasterOnly:
1765 return execMasterOnly();
1766 default:
1767 throw(std::runtime_error("Algorithm " + name() + " does not support execution mode " +
1768 Parallel::toString(executionMode)));
1769 }
1770}
1771
1779
1789 if (communicator().rank() == 0)
1790 exec();
1791}
1792
1799Parallel::ExecutionMode Algorithm::getExecutionMode() const {
1800 if (communicator().size() == 1)
1801 return Parallel::ExecutionMode::Serial;
1802
1803 const auto storageModes = getInputWorkspaceStorageModes();
1804 const auto executionMode = getParallelExecutionMode(storageModes);
1805 if (executionMode == Parallel::ExecutionMode::Invalid) {
1806 std::string error("Algorithm does not support execution with input "
1807 "workspaces of the following storage types: " +
1808 Parallel::toString(storageModes) + ".");
1809 getLogger().error() << error << "\n";
1810 throw(std::runtime_error(error));
1811 }
1812 if (executionMode == Parallel::ExecutionMode::Serial) {
1813 std::string error(Parallel::toString(executionMode) + " is not a valid *parallel* execution mode.");
1814 getLogger().error() << error << "\n";
1815 throw(std::runtime_error(error));
1816 }
1817 getLogger().information() << "MPI Rank " << communicator().rank() << " running with "
1818 << Parallel::toString(executionMode) << '\n';
1819 return executionMode;
1820}
1821
1825std::map<std::string, Parallel::StorageMode> Algorithm::getInputWorkspaceStorageModes() const {
1826 std::map<std::string, Parallel::StorageMode> map;
1827 for (const auto &wsProp : m_inputWorkspaceProps) {
1828 // This is the reverse cast of what is done in cacheWorkspaceProperties(),
1829 // so it should never fail.
1830 const Property &prop = dynamic_cast<Property &>(*wsProp);
1831 // Check if we actually have that input workspace
1832 if (wsProp->getWorkspace())
1833 map.emplace(prop.name(), wsProp->getWorkspace()->storageMode());
1834 else if (!wsProp->isOptional())
1835 map.emplace(prop.name(), Parallel::StorageMode::MasterOnly);
1836 }
1837 getLogger().information() << "Input workspaces for determining execution mode:\n";
1838 for (const auto &item : map)
1839 getLogger().information() << " " << item.first << " --- " << Parallel::toString(item.second) << '\n';
1840 return map;
1841}
1842
1849Parallel::ExecutionMode
1850Algorithm::getParallelExecutionMode(const std::map<std::string, Parallel::StorageMode> &storageModes) const {
1851 UNUSED_ARG(storageModes)
1852 // By default no parallel execution is possible.
1853 return Parallel::ExecutionMode::Invalid;
1854}
1855
1859 // If workspaces have StorageMode::MasterOnly, validation on non-master
1860 // ranks would usually fail. Therefore, WorkspaceProperty needs to skip
1861 // validation. Thus, we must notify it whether or not it is on the master
1862 // rank or not.
1863 if (communicator().rank() != 0)
1864 for (auto *prop : getProperties())
1865 if (auto *wsProp = dynamic_cast<IWorkspaceProperty *>(prop))
1866 wsProp->setIsMasterRank(false);
1867}
1868
1870const Parallel::Communicator &Algorithm::communicator() const { return *m_communicator; }
1871
1873void Algorithm::setCommunicator(const Parallel::Communicator &communicator) {
1874 m_communicator = std::make_unique<Parallel::Communicator>(communicator);
1875}
1876
1877//---------------------------------------------------------------------------
1878// Algorithm's inner classes
1879//---------------------------------------------------------------------------
1880
1882 : Poco::Notification(), m_algorithm(alg) {}
1883
1884const IAlgorithm *Algorithm::AlgorithmNotification::algorithm() const { return m_algorithm; }
1885
1887std::string Algorithm::StartedNotification::name() const { return "StartedNotification"; }
1888
1890 : AlgorithmNotification(alg), success(res) {}
1891std::string Algorithm::FinishedNotification::name() const { return "FinishedNotification"; }
1892
1893Algorithm::ProgressNotification::ProgressNotification(const Algorithm *const alg, double p, std::string msg,
1894 double estimatedTime, int progressPrecision)
1895 : AlgorithmNotification(alg), progress(p), message(std::move(msg)), estimatedTime(estimatedTime),
1896 progressPrecision(progressPrecision) {}
1897
1898std::string Algorithm::ProgressNotification::name() const { return "ProgressNotification"; }
1899
1901 : AlgorithmNotification(alg), what(std::move(str)) {}
1902
1903std::string Algorithm::ErrorNotification::name() const { return "ErrorNotification"; }
1904
1905const char *Algorithm::CancelException::what() const noexcept { return "Algorithm terminated"; }
1906
1913void Algorithm::declareProperty(std::unique_ptr<Property> p, const std::string &doc) {
1914 m_properties.declareProperty(std::move(p), doc);
1915}
1916
1921void Algorithm::declareOrReplaceProperty(std::unique_ptr<Property> p, const std::string &doc) {
1922 m_properties.declareOrReplaceProperty(std::move(p), doc);
1923}
1924
1928
1940void Algorithm::setProperties(const std::string &propertiesJson,
1941 const std::unordered_set<std::string> &ignoreProperties, bool createMissing) {
1942 m_properties.setProperties(propertiesJson, ignoreProperties, createMissing);
1943}
1944
1951void Algorithm::setProperties(const ::Json::Value &jsonValue, const std::unordered_set<std::string> &ignoreProperties,
1952 bool createMissing) {
1953 m_properties.setProperties(jsonValue, ignoreProperties, createMissing);
1954}
1955
1962void Algorithm::setPropertiesWithString(const std::string &propertiesString,
1963 const std::unordered_set<std::string> &ignoreProperties) {
1964 m_properties.setPropertiesWithString(propertiesString, ignoreProperties);
1965}
1966
1975void Algorithm::setPropertyValue(const std::string &name, const std::string &value) {
1977 this->afterPropertySet(name);
1978}
1979
1987void Algorithm::setPropertyValueFromJson(const std::string &name, const Json::Value &value) {
1989 this->afterPropertySet(name);
1990}
1991
1998void Algorithm::setPropertyOrdinal(const int &index, const std::string &value) {
2001}
2002
2008bool Algorithm::existsProperty(const std::string &name) const { return m_properties.existsProperty(name); }
2009
2014
2020
2026std::string Algorithm::getPropertyValue(const std::string &name) const { return m_properties.getPropertyValue(name); }
2027
2035}
2036
2044}
2045
2050const std::vector<Property *> &Algorithm::getProperties() const { return m_properties.getProperties(); }
2051
2056std::vector<std::string> Algorithm::getDeclaredPropertyNames() const noexcept {
2058}
2059
2078}
2079
2084bool Algorithm::isDefault(const std::string &name) const {
2086}
2087
2095std::string Algorithm::asString(bool withDefaultValues) const { return m_properties.asString(withDefaultValues); }
2102::Json::Value Algorithm::asJson(bool withDefaultValues) const { return m_properties.asJson(withDefaultValues); }
2103
2109void Algorithm::removeProperty(const std::string &name, const bool delproperty) {
2110 m_properties.removeProperty(name, delproperty);
2111}
2112
2118std::unique_ptr<Kernel::Property> Algorithm::takeProperty(const size_t index) {
2120}
2121
2126
2134
2135} // namespace API
2136
2137//---------------------------------------------------------------------------
2138// Specialized templated PropertyManager getValue definitions for Algorithm
2139// types
2140//---------------------------------------------------------------------------
2141namespace Kernel {
2147template <>
2148MANTID_API_DLL API::IAlgorithm_sptr IPropertyManager::getValue<API::IAlgorithm_sptr>(const std::string &name) const {
2149 auto *prop = dynamic_cast<PropertyWithValue<API::IAlgorithm_sptr> *>(getPointerToProperty(name));
2150 if (prop) {
2151 return *prop;
2152 } else {
2153 std::string message = "Attempt to assign property " + name + " to incorrect type. Expected shared_ptr<IAlgorithm>";
2154 throw std::runtime_error(message);
2155 }
2156}
2157
2164template <>
2166IPropertyManager::getValue<API::IAlgorithm_const_sptr>(const std::string &name) const {
2167 auto *prop = dynamic_cast<PropertyWithValue<API::IAlgorithm_sptr> *>(getPointerToProperty(name));
2168 if (prop) {
2169 return prop->operator()();
2170 } else {
2171 std::string message =
2172 "Attempt to assign property " + name + " to incorrect type. Expected const shared_ptr<IAlgorithm>";
2173 throw std::runtime_error(message);
2174 }
2175}
2176
2177} // namespace Kernel
2178
2179} // namespace Mantid
const std::string & m_value
Definition: Algorithm.cpp:71
bool & m_running_flag
Running flag.
Definition: Algorithm.cpp:1587
T m_onfinsh
Definition: Algorithm.cpp:79
double value
The value of the point.
Definition: FitMW.cpp:51
double error
Definition: IndexPeaks.cpp:133
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
#define PARALLEL_CRITICAL(name)
#define IF_NOT_PARALLEL
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition: System.h:64
std::vector< history_type > history
history information
ADSValidator : a validator that requires the value of a property to be present in the ADS.
Definition: ADSValidator.h:21
This class stores information about the Command History used by algorithms on a workspace.
void printSelf(std::ostream &, const int indent=0, const size_t maxPropertyLength=0) const
print contents of object
Base class for algorithm notifications.
Definition: Algorithm.h:88
AlgorithmNotification(const Algorithm *const alg)
Definition: Algorithm.cpp:1881
CancelException is thrown to cancel execution of the algorithm.
Definition: Algorithm.h:145
const char * what() const noexcept override
Returns the message string.
Definition: Algorithm.cpp:1905
ErrorNotification is sent when an exception is caught during execution of the algorithm.
Definition: Algorithm.h:130
std::string name() const override
Definition: Algorithm.cpp:1903
ErrorNotification(const Algorithm *const alg, std::string str)
Constructor.
Definition: Algorithm.cpp:1900
FinishedNotification is sent after the algorithm finishes its execution.
Definition: Algorithm.h:105
FinishedNotification(const Algorithm *const alg, bool res)
Definition: Algorithm.cpp:1889
An algorithm can report its progress by sending ProgressNotification.
Definition: Algorithm.h:115
ProgressNotification(const Algorithm *const alg, double p, std::string msg, double estimatedTime, int progressPrecision)
Constructor.
Definition: Algorithm.cpp:1893
StartedNotification is sent when the algorithm begins execution.
Definition: Algorithm.h:98
StartedNotification(const Algorithm *const alg)
Definition: Algorithm.cpp:1886
std::string name() const override
class name
Definition: Algorithm.cpp:1887
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:85
void clearWorkspaceCaches()
Clear any internal workspace handles so that workspaces will be deleted promptly after a managed algo...
Definition: Algorithm.cpp:499
void setRethrows(const bool rethrow) override
Set whether the algorithm will rethrow exceptions.
Definition: Algorithm.cpp:193
const std::string categorySeparator() const override
Function to return the separator token for the category string.
Definition: Algorithm.h:174
std::vector< std::shared_ptr< WorkspaceGroup > > m_groupWorkspaces
Pointer to the WorkspaceGroup (if any) for each input workspace property.
Definition: Algorithm.h:547
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
void store()
Stores any output workspaces into the AnalysisDataService.
Definition: Algorithm.cpp:787
std::vector< Workspace_sptr > m_inputWorkspaceHistories
Store a pointer to the input workspace histories so they can be copied to the outputs to avoid anythi...
Definition: Algorithm.h:554
bool isRunning() const override
True if the algorithm is running.
Definition: Algorithm.cpp:196
void setExecutionState(const ExecutionState state)
Sets the current execution state.
Definition: Algorithm.cpp:132
virtual const std::string workspaceMethodOnTypes() const
Returns a semi-colon separated list of workspace types to attach this algorithm.
Definition: Algorithm.h:395
Kernel::Property * getPointerToProperty(const std::string &name) const override
Get a property by name.
Definition: Algorithm.cpp:2033
const std::string workspaceMethodName() const override
Definition: Algorithm.cpp:255
bool calledByAlias
Flag to indicate if the algorithm is called by its alias.
Definition: Algorithm.h:181
std::vector< std::string > getDeclaredPropertyNames() const noexcept override
Return the list of declared property names.
Definition: Algorithm.cpp:2056
std::unique_ptr< Poco::NObserver< Algorithm, ProgressNotification > > m_progressObserver
Child algorithm progress observer.
Definition: Algorithm.h:512
std::vector< std::string > m_reservedList
Reserved property names.
Definition: Algorithm.h:557
AlgorithmID getAlgorithmID() const override
Algorithm ID.
Definition: Algorithm.h:213
int m_singleGroup
If only one input is a group, this is its index. -1 if they are all groups.
Definition: Algorithm.h:549
void setCommunicator(const Parallel::Communicator &communicator)
Sets the (MPI) communicator of the algorithm.
Definition: Algorithm.cpp:1873
void clear() override
Clears all properties under management.
Definition: Algorithm.cpp:2125
std::vector< IWorkspaceProperty * > m_inputWorkspaceProps
All the WorkspaceProperties that are Input or InOut. Set in execute()
Definition: Algorithm.h:445
bool isExecuted() const override
Has the Algorithm already been executed successfully.
Definition: Algorithm.cpp:151
::Json::Value asJson(bool withDefaultValues=false) const override
Return the property manager serialized as a json object.
Definition: Algorithm.cpp:2102
void registerFeatureUsage() const
Registers the usage of the algorithm with the UsageService.
Definition: Algorithm.cpp:1734
virtual void execDistributed()
Runs the algorithm in distributed execution mode.
Definition: Algorithm.cpp:1778
bool existsProperty(const std::string &name) const override
Checks whether the named property is already in the list of managed property.
Definition: Algorithm.cpp:2008
WorkspaceVector m_writeLockedWorkspaces
Vector of all the workspaces that have been write-locked.
Definition: Algorithm.h:539
bool m_rethrow
Algorithm should rethrow exceptions while executing.
Definition: Algorithm.h:521
bool validateProperties() const override
Validates all the properties in the collection.
Definition: Algorithm.cpp:2013
double m_startChildProgress
Whether to log alg startup and closedown messages from the base class (default = true)
Definition: Algorithm.h:525
void setPropertyOrdinal(const int &index, const std::string &value) override
Set the value of a property by an index N.B.
Definition: Algorithm.cpp:1998
void setupSkipValidationMasterOnly()
Sets up skipping workspace validation on non-master ranks for StorageMode::MasterOnly.
Definition: Algorithm.cpp:1858
void afterPropertySet(const std::string &) override
Override this method to perform a custom action right after a property was set.
Definition: Algorithm.cpp:2133
bool m_usingBaseProcessGroups
distinguish between base processGroups() and overriden/algorithm specific versions
Definition: Algorithm.h:463
void setAlgStartupLogging(const bool enabled) override
disable Logging of start and end messages
Definition: Algorithm.cpp:1745
void removeProperty(const std::string &name, const bool delproperty=true) override
Removes the property from management.
Definition: Algorithm.cpp:2109
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
std::vector< std::weak_ptr< IAlgorithm > > m_ChildAlgorithms
A list of weak pointers to any child algorithms created.
Definition: Algorithm.h:530
Kernel::Property * getPointerToPropertyOrdinal(const int &index) const override
Get a property by an index.
Definition: Algorithm.cpp:2042
std::unique_ptr< Kernel::Property > takeProperty(const size_t index) override
Removes the property from management and returns a pointer to it.
Definition: Algorithm.cpp:2118
void copyNonWorkspaceProperties(IAlgorithm *alg, int periodNum)
Copy all the non-workspace properties from this to alg.
Definition: Algorithm.cpp:1523
std::atomic< bool > m_cancel
Set to true to stop execution.
Definition: Algorithm.h:433
void setLogging(const bool value) override
Logging can be disabled by passing a value of false.
Definition: Algorithm.cpp:1662
std::shared_ptr< AlgorithmHistory > m_parentHistory
Pointer to the parent history object (if set)
Definition: Algorithm.h:454
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
virtual void fillHistory()
Copy workspace history for input workspaces to output workspaces and record the history for ths algor...
Definition: Algorithm.cpp:994
void setResultState(const ResultState state)
Sets the result execution state.
Definition: Algorithm.cpp:139
void handleChildProgressNotification(const Poco::AutoPtr< ProgressNotification > &pNf)
Observation slot for child algorithm progress notification messages, these are scaled and then signal...
Definition: Algorithm.cpp:1623
void addObserver(const Poco::AbstractObserver &observer) const override
Add an observer for a notification.
Definition: Algorithm.cpp:211
std::string toString() const override
Serialize an object to a string.
Definition: Algorithm.cpp:905
std::shared_ptr< AlgorithmHistory > m_history
Pointer to the history for the algorithm being executed.
Definition: Algorithm.h:447
std::vector< IWorkspaceProperty * > m_outputWorkspaceProps
All the WorkspaceProperties that are Output or InOut. Set in execute()
Definition: Algorithm.h:542
void initialize() override
Initialization method invoked by the framework.
Definition: Algorithm.cpp:283
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
Definition: Algorithm.cpp:842
virtual Parallel::ExecutionMode getParallelExecutionMode(const std::map< std::string, Parallel::StorageMode > &storageModes) const
Get correct execution mode based on input storage modes for an MPI run.
Definition: Algorithm.cpp:1850
std::vector< IWorkspaceProperty * > m_pureOutputWorkspaceProps
All the WorkspaceProperties that are Output (not inOut). Set in execute()
Definition: Algorithm.h:544
size_t propertyCount() const override
Count the number of properties under management.
Definition: Algorithm.cpp:2019
Parallel::ExecutionMode getExecutionMode() const
Get a (valid) execution mode for this algorithm.
Definition: Algorithm.cpp:1799
virtual void execMasterOnly()
Runs the algorithm in master-only execution mode.
Definition: Algorithm.cpp:1788
bool isChild() const override
To query whether algorithm is a child.
Definition: Algorithm.cpp:160
void setLoggingOffset(const int value) override
gets the logging priority offset
Definition: Algorithm.cpp:1671
size_t m_groupSize
Size of the group(s) being processed.
Definition: Algorithm.h:460
static IAlgorithm_sptr fromString(const std::string &input)
De-serialize an object from a string.
Definition: Algorithm.cpp:967
WorkspaceVector m_readLockedWorkspaces
Vector of all the workspaces that have been read-locked.
Definition: Algorithm.h:537
virtual void init()=0
Virtual method - must be overridden by concrete algorithm.
Kernel::Logger & g_log
Definition: Algorithm.h:451
std::vector< std::shared_ptr< Workspace > > WorkspaceVector
Definition: Algorithm.h:291
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Definition: Algorithm.cpp:231
virtual void setOtherProperties(IAlgorithm *alg, const std::string &propertyName, const std::string &propertyValue, int periodNum)
Virtual method to set the non workspace properties for this algorithm.
Definition: Algorithm.cpp:1547
bool isInitialized() const override
Has the Algorithm already been initialized.
Definition: Algorithm.cpp:148
bool m_alwaysStoreInADS
Always store in the ADS, even for child algos.
Definition: Algorithm.h:519
ExecutionState executionState() const override
Gets the current execution state.
Definition: Algorithm.cpp:129
bool m_isAlgStartupLoggingEnabled
Definition: Algorithm.h:522
bool trackingHistory()
get whether we are tracking the history for this algorithm,
Definition: Algorithm.cpp:1063
bool execute() override final
The actions to be performed by the algorithm on a dataset.
void setAlwaysStoreInADS(const bool doStore) override
Do we ALWAYS store in the AnalysisDataService? This is set to true for python algorithms' child algor...
Definition: Algorithm.cpp:183
void linkHistoryWithLastChild()
Link the name of the output workspaces on this parent algorithm.
Definition: Algorithm.cpp:1010
bool isLogging() const override
returns the status of logging, True = enabled
Definition: Algorithm.cpp:1664
bool getAlgStartupLogging() const override
get the state of Logging of start and end messages
Definition: Algorithm.cpp:1750
bool isWorkspaceProperty(const Kernel::Property *const prop) const
checks the property is a workspace property
Definition: Algorithm.cpp:1559
void setProperties(const std::string &propertiesJson, const std::unordered_set< std::string > &ignoreProperties=std::unordered_set< std::string >(), bool createMissing=false) override
Set the ordered list of properties by one string of values, separated by semicolons.
Definition: Algorithm.cpp:1940
std::atomic< ResultState > m_resultState
the current result State
Definition: Algorithm.h:515
bool isReadyForGarbageCollection() const override
True if the algorithm is ready for garbage collection.
Definition: Algorithm.cpp:199
Poco::NotificationCenter & notificationCenter() const
Return a reference to the algorithm's notification dispatcher.
Definition: Algorithm.cpp:1614
int getLoggingOffset() const override
returns the logging priority offset
Definition: Algorithm.cpp:1681
std::unique_ptr< Poco::ActiveMethod< bool, Poco::Void, Algorithm, Poco::ActiveStarter< Algorithm > > > m_executeAsync
Poco::ActiveMethod used to implement asynchronous execution.
Definition: Algorithm.h:505
std::vector< WorkspaceVector > m_unrolledInputWorkspaces
One vector of workspaces for each input workspace property.
Definition: Algorithm.h:458
void resetProperties() override
Reset property values back to initial values (blank or default values)
Definition: Algorithm.cpp:1927
void removeObserver(const Poco::AbstractObserver &observer) const override
Remove an observer.
Definition: Algorithm.cpp:218
void logAlgorithmInfo() const
Sends out algorithm parameter information to the logger.
Definition: Algorithm.cpp:1108
void reportCompleted(const double &duration, const bool groupProcessing=false)
Report that the algorithm has completed.
Definition: Algorithm.cpp:1704
bool m_isChildAlgorithm
Algorithm is a child algorithm.
Definition: Algorithm.h:516
bool getAlwaysStoreInADS() const override
Returns true if we always store in the AnalysisDataService.
Definition: Algorithm.cpp:188
void setPropertiesWithString(const std::string &propertiesString, const std::unordered_set< std::string > &ignoreProperties=std::unordered_set< std::string >()) override
Sets all the declared properties from a string.
Definition: Algorithm.cpp:1962
bool executeInternal()
Invoced internally in execute()
Definition: Algorithm.cpp:512
Mantid::Kernel::PropertyManagerOwner m_properties
Definition: Algorithm.h:565
ResultState resultState() const override
Gets the current result State.
Definition: Algorithm.cpp:135
const std::string category() const override
function to return a category of the algorithm.
Definition: Algorithm.h:169
virtual void exec()=0
Virtual method - must be overridden by concrete algorithm.
void executeAsChildAlg() override
Execute as a Child Algorithm.
Definition: Algorithm.cpp:769
bool isDefault(const std::string &name) const
Definition: Algorithm.cpp:2084
void trackAlgorithmHistory(std::shared_ptr< AlgorithmHistory > parentHist)
set whether we wish to track the child algorithm's history and pass it the parent object to fill.
Definition: Algorithm.cpp:1055
const std::string workspaceMethodInputProperty() const override
Definition: Algorithm.cpp:272
std::string asString(bool withDefaultValues=false) const override
Return the property manager serialized as a string.
Definition: Algorithm.cpp:2095
void declareOrReplaceProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add or replace property in the list of managed properties.
Definition: Algorithm.cpp:1921
void interruption_point()
This is called during long-running operations, and check if the algorithm has requested that it be ca...
Definition: Algorithm.cpp:1687
const std::vector< std::string > categories() const override
Function to return all of the categories that contain this algorithm.
Definition: Algorithm.cpp:237
void cancel() override
Raises the cancel flag.
Definition: Algorithm.cpp:1644
const std::vector< std::string > workspaceMethodOn() const override
Definition: Algorithm.cpp:262
void setPropertyValue(const std::string &name, const std::string &value) override
Set the value of a property by string N.B.
Definition: Algorithm.cpp:1975
~Algorithm() override
Virtual destructor.
void enableHistoryRecordingForChild(const bool on) override
Change the state of the history recording flag.
Definition: Algorithm.cpp:176
bool m_runningAsync
Algorithm is running asynchronously.
Definition: Algorithm.h:520
int version() const override=0
function to return a version of the algorithm, must be overridden in all algorithms
std::atomic< ExecutionState > m_executionState
the current execution state
Definition: Algorithm.h:514
static bool isEmpty(const NumT toCheck)
checks that the value was not set by users, uses the value in empty double/int.
bool m_groupsHaveSimilarNames
All the groups have similar names (group_1, group_2 etc.)
Definition: Algorithm.h:551
Poco::ActiveResult< bool > executeAsync() override
Asynchronous execution.
Definition: Algorithm.cpp:1595
std::map< std::string, std::string > validateInputs() override
Perform validation of ALL the input properties of the algorithm.
Definition: Algorithm.cpp:324
void lockWorkspaces()
Go through the workspace properties of this algorithm and lock the workspaces for reading or writing.
Definition: Algorithm.cpp:425
void setupAsChildAlgorithm(const Algorithm_sptr &algorithm, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true)
Setup algorithm as child algorithm.
Definition: Algorithm.cpp:855
bool getCancel() const
Returns the cancellation state.
Definition: Algorithm.cpp:1657
bool doCallProcessGroups(Mantid::Types::Core::DateAndTime &start_time)
Calls process groups with the required timing checks and algorithm execution finalization steps.
Definition: Algorithm.cpp:1247
const Parallel::Communicator & communicator() const
Returns a const reference to the (MPI) communicator of the algorithm.
Definition: Algorithm.cpp:1870
void cacheWorkspaceProperties()
Go through the properties and cache the input/output workspace properties for later use.
Definition: Algorithm.cpp:331
::Json::Value toJson() const override
Serialize an object to a json object.
Definition: Algorithm.cpp:911
void findWorkspaces(WorkspaceVector &workspaces, unsigned int direction, bool checkADS=false) const
Populate lists of the workspace properties for a given direction (InOut workspaces are included in bo...
Definition: Algorithm.cpp:1073
std::unique_ptr< Parallel::Communicator > m_communicator
(MPI) communicator used when executing the algorithm.
Definition: Algorithm.h:560
std::map< std::string, Parallel::StorageMode > getInputWorkspaceStorageModes() const
Get map of storage modes of all input workspaces.
Definition: Algorithm.cpp:1825
Kernel::Logger & getLogger() const
Returns a reference to the logger.
Definition: Algorithm.cpp:1660
void cacheInputWorkspaceHistories()
Cache the histories of any input workspaces so they can be copied over after algorithm completion.
Definition: Algorithm.cpp:363
double m_endChildProgress
Keeps value for algorithm's progress at Child Algorithm's finish.
Definition: Algorithm.h:527
virtual bool checkGroups()
Check the input workspace properties for groups.
Definition: Algorithm.cpp:1154
bool isCompoundProperty(const std::string &name) const
Definition: Algorithm.cpp:1752
Algorithm()
Constructor.
Definition: Algorithm.cpp:111
Mantid::Types::Core::DateAndTime m_gcTime
The earliest this class should be considered for garbage collection.
Definition: Algorithm.h:563
std::unique_ptr< Poco::NotificationCenter > m_notificationCenter
Sends notifications to observers.
Definition: Algorithm.h:510
void setChild(const bool isChild) override
To set whether algorithm is a child.
Definition: Algorithm.cpp:166
void setPropertyValueFromJson(const std::string &name, const Json::Value &value) override
Set the value of a property by Json::Value object.
Definition: Algorithm.cpp:1987
static size_t g_execCount
Counter to keep track of algorithm execution order.
Definition: Algorithm.h:439
bool m_recordHistoryForChild
Flag to indicate whether history should be recorded.
Definition: Algorithm.h:517
static IAlgorithm_sptr fromHistory(const AlgorithmHistory &history)
Construct an object from a history entry.
Definition: Algorithm.cpp:929
static IAlgorithm_sptr fromJson(const Json::Value &input)
De-serialize an object from a Json.
Definition: Algorithm.cpp:983
void unlockWorkspaces()
Unlock any previously locked workspaces.
Definition: Algorithm.cpp:472
const std::vector< Kernel::Property * > & getProperties() const override
Get the list of managed properties.
Definition: Algorithm.cpp:2050
virtual bool processGroups()
Process WorkspaceGroup inputs.
Definition: Algorithm.cpp:1365
const std::string name() const override=0
function to return a name of the algorithm, must be overridden in all algorithms
bool executeAsyncImpl(const Poco::Void &i)
Callback when an algorithm is executed asynchronously.
Definition: Algorithm.cpp:1605
const Poco::AbstractObserver & progressObserver() const
Return a reference to the algorithm's object that is reporting progress.
Definition: Algorithm.cpp:1632
The Analysis data service stores instances of the Workspace objects and anything that derives from te...
Class for marking algorithms as deprecated.
DeprecatedAlias : Class for making algorithm with deprecated names (aliases).
IAlgorithm is the interface implemented by the Algorithm base class.
Definition: IAlgorithm.h:45
virtual const std::string name() const =0
function to return a name of the algorithm, must be overridden in all algorithms
An interface that is implemented by WorkspaceProperty.
virtual bool store()=0
Store a workspace into the AnalysisDataService.
virtual Workspace_sptr getWorkspace() const =0
Get a pointer to the workspace.
Class to hold a set of workspaces.
A property class for workspaces.
Workspace_sptr getWorkspace() const override
Get a pointer to the workspace.
Base Workspace Abstract Class.
Definition: Workspace.h:30
const WorkspaceHistory & getHistory() const
Returns a reference to the WorkspaceHistory const.
Definition: Workspace.h:84
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
Exception for when an item is not found in a collection.
Definition: Exception.h:145
virtual void setPropertyValue(const std::string &name, const std::string &value)=0
Sets property value from a string.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition: Logger.h:52
void debug(const std::string &msg)
Logs at debug level.
Definition: Logger.cpp:114
void notice(const std::string &msg)
Logs at notice level.
Definition: Logger.cpp:95
void setName(const std::string &name)
Update the name of the logger.
Definition: Logger.cpp:38
int getLevelOffset() const
Gets the Logger's log offset level.
Definition: Logger.cpp:414
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
void setEnabled(const bool enabled)
set if the logging is enabled
Definition: Logger.cpp:59
bool getEnabled() const
returns true if the log is enabled
Definition: Logger.cpp:52
void fatal(const std::string &msg)
Logs at Fatal level.
Definition: Logger.cpp:68
void setLevelOffset(int level)
Sets the Logger's log offset level.
Definition: Logger.cpp:408
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
Property * getPointerToProperty(const std::string &name) const override
Get a property by name.
bool validateProperties() const override
Validates all the properties in the collection.
void afterPropertySet(const std::string &) override
Override this method to perform a custom action right after a property was set.
void setProperties(const std::string &propertiesJson, const std::unordered_set< std::string > &ignoreProperties=std::unordered_set< std::string >(), bool createMissing=false) override
Set the ordered list of properties by one string of values, separated by semicolons.
void setPropertyValue(const std::string &name, const std::string &value) override
Set the value of a property by string N.B.
void declareOrReplaceProperty(std::unique_ptr< Property > p, const std::string &doc="") override
Add or replace property in the list of managed properties.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
void clear() override
Clears all properties under management.
void setPropertyOrdinal(const int &index, const std::string &value) override
Set the value of a property by an index N.B.
void declareProperty(std::unique_ptr< Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
::Json::Value asJson(bool withDefaultValues=false) const override
Return the property manager serialized as a json object.
void setPropertyValueFromJson(const std::string &name, const Json::Value &value) override
Set the value of a property by Json::Value object.
const std::vector< Property * > & getProperties() const override
Get the list of managed properties.
std::vector< std::string > getDeclaredPropertyNames() const noexcept override
Return the list of declared property names.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
void setPropertiesWithString(const std::string &propertiesString, const std::unordered_set< std::string > &ignoreProperties=std::unordered_set< std::string >()) override
Sets all the declared properties from a string.
bool existsProperty(const std::string &name) const override
Checks whether the named property is already in the list of managed property.
Property * getPointerToPropertyOrdinal(const int &index) const override
Get a property by an index.
size_t propertyCount() const override
Count the number of properties under management.
void removeProperty(const std::string &name, const bool delproperty=true) override
Removes the property from management.
void resetProperties() override
Reset property values back to initial values (blank or default values)
std::unique_ptr< Property > takeProperty(const size_t index) override
Removes the property from management returning a pointer to it.
std::string asString(bool withDefaultValues=false) const override
Return the property manager serialized as a string.
The concrete, templated class for properties.
Base class for properties.
Definition: Property.h:94
virtual bool isDefault() const =0
Overriden function that returns if property has the same value that it was initialised with,...
const std::string & name() const
Get the property's name.
Definition: Property.cpp:60
virtual std::string value() const =0
Returns the value of the property as a string.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
@ TOK_IGNORE_EMPTY
ignore empty tokens
@ TOK_TRIM
remove leading and trailing whitespace from tokens
const TokenVec & asVector()
Returns a vector of tokenized strings.
A simple class that provides a wall-clock (not processor time) timer.
Definition: Timer.h:27
float elapsed(bool reset=true)
Returns the wall-clock time elapsed in seconds since the Timer object's creation, or the last call to...
Definition: Timer.cpp:28
std::shared_ptr< IAlgorithm > IAlgorithm_sptr
shared pointer to Mantid::API::IAlgorithm
std::shared_ptr< WorkspaceGroup > WorkspaceGroup_sptr
shared pointer to Mantid::API::WorkspaceGroup
std::shared_ptr< const IAlgorithm > IAlgorithm_const_sptr
shared pointer to Mantid::API::IAlgorithm (const version)
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
Definition: Workspace_fwd.h:20
Kernel::Logger g_log("ExperimentInfo")
static logger object
ResultState
The validity of the results of the algorithm object.
Definition: IAlgorithm.h:33
ExecutionState
The current state of the algorithm object.
Definition: IAlgorithm.h:31
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
Definition: Algorithm.h:61
Mantid::Kernel::StringTokenizer tokenizer
Definition: Expression.cpp:17
std::string toString(const T &value)
Convert a number to a string.
Definition: Strings.cpp:703
std::shared_ptr< PropertyHistory > PropertyHistory_sptr
std::shared_ptr< IValidator > IValidator_sptr
A shared_ptr to an IValidator.
Definition: IValidator.h:26
Helper class which provides the Collimation Length for SANS instruments.
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
Definition: EmptyValues.h:25
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition: EmptyValues.h:43
Definition: Algorithm.h:30
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)
@ InOut
Both an input & output workspace.
Definition: Property.h:55
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54
Utility class that enables the getProperty() method to effectively be templated on the return type.