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 +
18
19#include "MantidJson/Json.h"
26#include "MantidKernel/Timer.h"
28
30#include <Poco/ActiveMethod.h>
31#include <Poco/ActiveResult.h>
32#include <Poco/NotificationCenter.h>
33#include <Poco/RWLock.h>
34#include <Poco/Void.h>
35
36#include <H5Cpp.h>
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
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_properties() {}
119
121Algorithm::~Algorithm() = default;
122
123//=============================================================================================
124//================================== Simple Getters/Setters
125//===================================
126//=============================================================================================
127
130
133
136
145
146//---------------------------------------------------------------------------------------------
149
154
155//---------------------------------------------------------------------------------------------
161
166void Algorithm::setChild(const bool isChild) {
168 this->setAlwaysStoreInADS(!isChild);
169}
170
177
182
188void Algorithm::setAlwaysStoreInADS(const bool doStore) {
189 m_alwaysStoreInADS = doStore;
190
191 // Set OutputWorkspace as an optional property in the case where alwaysStoreInADS is false. In
192 // this case, the output workspace name is not always required.
193 if (!m_alwaysStoreInADS && m_properties.existsProperty("OutputWorkspace")) {
194 Property *property = m_properties.getPointerToProperty("OutputWorkspace");
196 }
197}
198
203
207void Algorithm::setRethrows(const bool rethrow) { this->m_rethrow = rethrow; }
208
211
215 (Mantid::Types::Core::DateAndTime::getCurrentTime() > m_gcTime)) {
216 return true;
217 }
218 return false;
219}
220
221//---------------------------------------------------------------------------------------------
225void Algorithm::addObserver(const Poco::AbstractObserver &observer) const {
226 notificationCenter().addObserver(observer);
227}
228
232void Algorithm::removeObserver(const Poco::AbstractObserver &observer) const {
233 notificationCenter().removeObserver(observer);
234}
235
236//---------------------------------------------------------------------------------------------
245void Algorithm::progress(double p, const std::string &msg, double estimatedTime, int progressPrecision) {
246 notificationCenter().postNotification(new ProgressNotification(this, p, msg, estimatedTime, progressPrecision));
247}
248
249//---------------------------------------------------------------------------------------------
251const std::vector<std::string> Algorithm::categories() const {
255
256 auto res = tokenizer.asVector();
257
258 const auto *depo = dynamic_cast<const DeprecatedAlgorithm *>(this);
259 if (depo != nullptr) {
260 res.emplace_back("Deprecated");
261 }
262 return res;
263}
264
269const std::string Algorithm::workspaceMethodName() const { return ""; }
270
282
286const std::string Algorithm::workspaceMethodInputProperty() const { return ""; }
287
288//---------------------------------------------------------------------------------------------
298 // Bypass the initialization if the algorithm has already been initialized.
299 if (isInitialized())
300 return;
301
302 g_log.setName(this->name());
304 try {
305 try {
306 this->init();
307 } catch (std::runtime_error &) {
308 throw;
309 }
310
311 // Indicate that this Algorithm has been initialized to prevent duplicate
312 // attempts.
314 } catch (std::runtime_error &) {
315 throw;
316 }
317 // Unpleasant catch-all! Along with this, Gaudi version catches GaudiException
318 // & std::exception
319 // but doesn't really do anything except (print fatal) messages.
320 catch (...) {
321 // Gaudi: A call to the auditor service is here
322 // (1) perform the printout
323 getLogger().fatal("UNKNOWN Exception is caught in initialize()");
324 throw;
325 }
326}
327
328//---------------------------------------------------------------------------------------------
337std::map<std::string, std::string> Algorithm::validateInputs() { return std::map<std::string, std::string>(); }
338
339//---------------------------------------------------------------------------------------------
345 m_inputWorkspaceProps.clear();
348 const auto &props = this->getProperties();
349 for (const auto &prop : props) {
350 auto wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
351 if (!wsProp)
352 continue;
353 switch (prop->direction()) {
355 m_inputWorkspaceProps.emplace_back(wsProp);
356 break;
358 m_inputWorkspaceProps.emplace_back(wsProp);
359 m_outputWorkspaceProps.emplace_back(wsProp);
360 break;
362 m_outputWorkspaceProps.emplace_back(wsProp);
363 m_pureOutputWorkspaceProps.emplace_back(wsProp);
364 break;
365 default:
366 throw std::logic_error("Unexpected property direction found for property " + prop->name() + " of algorithm " +
367 this->name());
368 }
369 }
370}
371
377 if (!trackingHistory())
378 return;
379
380 auto cacheHistories = [this](const Workspace_sptr &ws) {
381 if (auto group = dynamic_cast<const WorkspaceGroup *>(ws.get())) {
383 std::copy(group->begin(), group->end(), std::back_inserter(m_inputWorkspaceHistories));
384 } else {
385 m_inputWorkspaceHistories.emplace_back(ws);
386 }
387 };
388 using ArrayPropertyString = ArrayProperty<std::string>;
389 auto isADSValidator = [](const IValidator_sptr &validator) -> bool {
390 if (!validator)
391 return false;
392 if (dynamic_cast<ADSValidator *>(validator.get()))
393 return true;
394 if (const auto compValidator = dynamic_cast<CompositeValidator *>(validator.get()))
395 return compValidator->contains<ADSValidator>();
396
397 return false;
398 };
399
400 // Look over all properties so we can catch an string array properties
401 // with an ADSValidator. ADSValidator indicates that the strings
402 // point to workspace names so we want to pick up the history from these too.
403 const auto &ads = AnalysisDataService::Instance();
405 const auto &props = this->getProperties();
406 for (const auto &prop : props) {
407 if (prop->direction() != Direction::Input && prop->direction() != Direction::InOut)
408 continue;
409
410 if (auto wsProp = dynamic_cast<IWorkspaceProperty const *>(prop)) {
411 if (auto ws = wsProp->getWorkspace()) {
412 cacheHistories(ws);
413 } else {
414 Workspace_sptr wsFromADS;
415 try {
416 wsFromADS = ads.retrieve(prop->value());
417 } catch (Exception::NotFoundError &) {
418 continue;
419 }
420 cacheHistories(wsFromADS);
421 }
422 } else if (auto strArrayProp = dynamic_cast<ArrayPropertyString *>(prop)) {
423 if (!isADSValidator(strArrayProp->getValidator()))
424 continue;
425 const auto &wsNames((*strArrayProp)());
426 for (const auto &wsName : wsNames) {
427 cacheHistories(ads.retrieve(wsName));
428 }
429 }
430 }
431} // namespace API
432
433//---------------------------------------------------------------------------------------------
439 // Do not lock workspace for child algos
440 if (this->isChild())
441 return;
442
443 if (!m_readLockedWorkspaces.empty() || !m_writeLockedWorkspaces.empty())
444 throw std::logic_error("Algorithm::lockWorkspaces(): The workspaces have "
445 "already been locked!");
446
447 // First, Write-lock the output workspaces
448 auto &debugLog = g_log.debug();
449 for (auto &outputWorkspaceProp : m_outputWorkspaceProps) {
450 Workspace_sptr ws = outputWorkspaceProp->getWorkspace();
451 if (ws) {
452 // The workspace property says to do locking,
453 // AND it has NOT already been write-locked
454 if (outputWorkspaceProp->isLocking() && std::find(m_writeLockedWorkspaces.begin(), m_writeLockedWorkspaces.end(),
455 ws) == m_writeLockedWorkspaces.end()) {
456 // Write-lock it if not already
457 debugLog << "Write-locking " << ws->getName() << '\n';
458 ws->getLock()->writeLock();
459 m_writeLockedWorkspaces.emplace_back(ws);
460 }
461 }
462 }
463
464 // Next read-lock the input workspaces
465 for (auto &inputWorkspaceProp : m_inputWorkspaceProps) {
466 Workspace_sptr ws = inputWorkspaceProp->getWorkspace();
467 if (ws) {
468 // The workspace property says to do locking,
469 // AND it has NOT already been write-locked
470 if (inputWorkspaceProp->isLocking() && std::find(m_writeLockedWorkspaces.begin(), m_writeLockedWorkspaces.end(),
471 ws) == m_writeLockedWorkspaces.end()) {
472 // Read-lock it if not already write-locked
473 debugLog << "Read-locking " << ws->getName() << '\n';
474 ws->getLock()->readLock();
475 m_readLockedWorkspaces.emplace_back(ws);
476 }
477 }
478 }
479}
480
481//---------------------------------------------------------------------------------------------
486 // Do not lock workspace for child algos
487 if (this->isChild())
488 return;
489 auto &debugLog = g_log.debug();
490 for (auto &ws : m_writeLockedWorkspaces) {
491 if (ws) {
492 debugLog << "Unlocking " << ws->getName() << '\n';
493 ws->getLock()->unlock();
494 }
495 }
496 for (auto &ws : m_readLockedWorkspaces) {
497 if (ws) {
498 debugLog << "Unlocking " << ws->getName() << '\n';
499 ws->getLock()->unlock();
500 }
501 }
502
503 // Don't double-unlock workspaces
506}
507
520
521//---------------------------------------------------------------------------------------------
526 Timer timer;
527 bool algIsExecuted = false;
528 AlgorithmManager::Instance().notifyAlgorithmStarting(this->getAlgorithmID());
529
530 // runtime check for deprecation warning
531 {
532 auto *depo = dynamic_cast<DeprecatedAlgorithm *>(this);
533 if (depo != nullptr)
534 getLogger().error(depo->deprecationMsg(this));
535 }
536
537 // runtime check for deprecated alias warning
538 {
539 auto *da_alg = dynamic_cast<DeprecatedAlias *>(this);
540 if ((da_alg != nullptr) && (this->calledByAlias))
541 getLogger().warning(da_alg->deprecationMessage(this));
542 }
543
544 // Register clean up tasks that should happen regardless of the route
545 // out of the algorithm. These tasks will get run after this method
546 // finishes.
547 RunOnFinish onFinish([this]() { this->clearWorkspaceCaches(); });
548
549 notificationCenter().postNotification(new StartedNotification(this));
550 Mantid::Types::Core::DateAndTime startTime;
551
552 // Return a failure if the algorithm hasn't been initialized
553 if (!isInitialized()) {
554 throw std::runtime_error("Algorithm is not initialised:" + this->name());
555 }
556
557 // no logging of input if a child algorithm (except for python child algos)
560
561 // Check all properties for validity
562 constexpr bool resetTimer{true};
563 float timingInit = timer.elapsed(resetTimer);
564 if (!validateProperties()) {
565 // Reset name on input workspaces to trigger attempt at collection from ADS
566 const auto &props = getProperties();
567 for (auto &prop : props) {
568 const auto *wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
569 if (wsProp && !(wsProp->getWorkspace())) {
570 // Setting it's name to the same one it already had
571 prop->setValue(prop->value());
572 }
573 }
574 // Try the validation again
575 if (!validateProperties()) {
576 notificationCenter().postNotification(new ErrorNotification(this, "Some invalid Properties found"));
577 throw std::runtime_error("Some invalid Properties found");
578 }
579 }
580 const float timingPropertyValidation = timer.elapsed(resetTimer);
581
582 // All properties are now valid - cache workspace properties and histories
585
586 // ----- Check for processing groups -------------
587 // default true so that it has the right value at the check below the catch
588 // block should checkGroups throw
589 bool callProcessGroups = true;
590 try {
591 // Checking the input is a group. Throws if the sizes are wrong
592 callProcessGroups = this->checkGroups();
593 } catch (std::exception &ex) {
594 getLogger().error() << "Error in execution of algorithm " << this->name() << "\n" << ex.what() << "\n";
595 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
598 m_runningAsync = false;
599 throw;
600 }
601 return false;
602 }
603
604 timingInit += timer.elapsed(resetTimer);
605 // ----- Perform validation of the whole set of properties -------------
606 if ((!callProcessGroups)) // for groups this is called on each workspace separately
607 {
608 std::map<std::string, std::string> errors = this->validateInputs();
609 if (!errors.empty()) {
610 size_t numErrors = errors.size();
611 // Log each issue
612 auto &errorLog = getLogger().error();
613 auto &warnLog = getLogger().warning();
614 for (auto &error : errors) {
615 if (this->existsProperty(error.first))
616 errorLog << "Invalid value for " << error.first << ": " << error.second << "\n";
617 else {
618 numErrors -= 1; // don't count it as an error
619 warnLog << "validateInputs() references non-existant property \"" << error.first << "\"\n";
620 }
621 }
622 // Throw because something was invalid
623 if (numErrors > 0) {
624 std::stringstream msg;
625 msg << "Some invalid Properties found: ";
626 for (const auto &error : errors) {
627 msg << "\n " << error.first << ": " << error.second;
628 }
629 notificationCenter().postNotification(new ErrorNotification(this, "Some invalid Properties found"));
630 throw std::runtime_error(msg.str());
631 }
632 }
633 }
634 const float timingInputValidation = timer.elapsed(resetTimer);
635
636 if (trackingHistory()) {
637 // count used for defining the algorithm execution order
638 // If history is being recorded we need to count this as a separate
639 // algorithm
640 // as the history compares histories by their execution number
642
643 // populate history record before execution so we can record child
644 // algorithms in it
645 AlgorithmHistory algHist;
646 m_history = std::make_shared<AlgorithmHistory>(algHist);
647 }
648
649 // ----- Process groups -------------
650 // If checkGroups() threw an exception but there ARE group workspaces
651 // (means that the group sizes were incompatible)
652 if (callProcessGroups) {
653 return doCallProcessGroups(startTime);
654 }
655
656 // Read or write locks every input/output workspace
657 this->lockWorkspaces();
658 timingInit += timer.elapsed(resetTimer);
659
660 // Invoke exec() method of derived class and catch all uncaught exceptions
661 try {
662 try {
664
665 startTime = Mantid::Types::Core::DateAndTime::getCurrentTime();
666 // Call the concrete algorithm's exec method
667 this->exec();
669 // Check for a cancellation request in case the concrete algorithm doesn't
671 const float timingExec = timer.elapsed(resetTimer);
672 // The total runtime including all init steps is used for general logging.
673 const float duration = timingInit + timingPropertyValidation + timingInputValidation + timingExec;
674 // need it to throw before trying to run fillhistory() on an algorithm
675 // which has failed
676 if (trackingHistory() && m_history) {
677 m_history->fillAlgorithmHistory(this, startTime, duration, Algorithm::g_execCount);
678 fillHistory();
680 }
681
682 // Put the output workspaces into the AnalysisDataService - if requested
684 this->store();
685
686 // just cache the value internally, it is set at the very end of this
687 // method
688 algIsExecuted = true;
689
690 // Log that execution has completed.
691 getLogger().debug("Time to validate properties: " + std::to_string(timingPropertyValidation) + " seconds\n" +
692 "Time for other input validation: " + std::to_string(timingInputValidation) + " seconds\n" +
693 "Time for other initialization: " + std::to_string(timingInit) + " seconds\n" +
694 "Time to run exec: " + std::to_string(timingExec) + " seconds\n");
695 reportCompleted(duration);
696 } catch (std::runtime_error &ex) {
697 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
698 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
700 this->unlockWorkspaces();
702 throw;
703 else {
704 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
705 getLogger().error() << "Error in execution of algorithm " << this->name() << '\n' << ex.what() << '\n';
706 }
707
708 } catch (std::logic_error &ex) {
709 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
710 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
711 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
713 this->unlockWorkspaces();
715 throw;
716 else {
717 getLogger().error() << "Logic Error in execution of algorithm " << this->name() << '\n' << ex.what() << '\n';
718 }
719 }
720 } catch (CancelException &ex) {
721 m_runningAsync = false;
722 getLogger().warning() << this->name() << ": Execution cancelled by user.\n";
723 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
724 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
726 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
727 this->unlockWorkspaces();
728
729 throw;
730 }
731 // Gaudi also specifically catches GaudiException & std:exception.
732 catch (std::exception &ex) {
733 m_runningAsync = false;
734 getLogger().error() << "Error in execution of algorithm " << this->name() << ":\n" << ex.what() << "\n";
735 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
736 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
738 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
739 this->unlockWorkspaces();
740
741 throw;
742 }
743
744 catch (H5::Exception &ex) {
745 m_runningAsync = false;
746 std::string errmsg;
747 errmsg.append(ex.getCFuncName()).append(": ").append(ex.getCDetailMsg());
748 getLogger().error() << "H5 Exception in execution of algorithm " << this->name() << ":\n" << errmsg << "\n";
749 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
750 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
752 notificationCenter().postNotification(new ErrorNotification(this, errmsg));
753 this->unlockWorkspaces();
754
755 throw;
756 }
757
758 catch (...) {
759 // Execution failed with an unknown exception object
760 m_runningAsync = false;
761
762 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
763 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
765 notificationCenter().postNotification(new ErrorNotification(this, "UNKNOWN Exception is caught in exec()"));
766 getLogger().error() << this->name() << ": UNKNOWN Exception is caught in exec()\n";
767 this->unlockWorkspaces();
768
769 throw;
770 }
771
772 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
773 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
774 if (algIsExecuted) {
776 }
777
778 // Only gets to here if algorithm ended normally
779 notificationCenter().postNotification(new FinishedNotification(this, isExecuted()));
780
781 // Unlock the workspaces once the notification has been sent, to prevent too early deletion
782 this->unlockWorkspaces();
783
784 return isExecuted();
785}
786
787//---------------------------------------------------------------------------------------------
793 bool executed = false;
794 try {
795 executed = execute();
796 } catch (std::runtime_error &) {
797 throw;
798 }
799
800 if (!executed) {
801 throw std::runtime_error("Unable to successfully run ChildAlgorithm " + this->name());
802 }
803}
804
805//---------------------------------------------------------------------------------------------
811 const std::vector<Property *> &props = getProperties();
812 std::vector<int> groupWsIndicies;
813
814 // add any regular/child workspaces first, then add the groups
815 for (unsigned int i = 0; i < props.size(); ++i) {
816 auto *wsProp = dynamic_cast<IWorkspaceProperty *>(props[i]);
817 if (wsProp) {
818 // check if the workspace is a group, if so remember where it is and add
819 // it later
820 auto group = std::dynamic_pointer_cast<WorkspaceGroup>(wsProp->getWorkspace());
821 if (!group) {
822 try {
823 wsProp->store();
824 } catch (std::runtime_error &) {
825 throw;
826 }
827 } else {
828 groupWsIndicies.emplace_back(i);
829 }
830 }
831 }
832
833 // now store workspace groups once their members have been added
834 std::vector<int>::const_iterator wsIndex;
835 for (wsIndex = groupWsIndicies.begin(); wsIndex != groupWsIndicies.end(); ++wsIndex) {
836 auto *wsProp = dynamic_cast<IWorkspaceProperty *>(props[*wsIndex]);
837 if (wsProp) {
838 try {
839 wsProp->store();
840 } catch (std::runtime_error &) {
841 throw;
842 }
843 }
844 }
845}
846
847//---------------------------------------------------------------------------------------------
865Algorithm_sptr Algorithm::createChildAlgorithm(const std::string &name, const double startProgress,
866 const double endProgress, const bool enableLogging, const int &version) {
867 Algorithm_sptr alg = AlgorithmManager::Instance().createUnmanaged(name, version);
868 setupAsChildAlgorithm(alg, startProgress, endProgress, enableLogging);
869 return alg;
870}
871
878void Algorithm::setupAsChildAlgorithm(const Algorithm_sptr &alg, const double startProgress, const double endProgress,
879 const bool enableLogging) {
880 // set as a child
881 alg->setChild(true);
882 alg->setLogging(enableLogging);
883
884 // Initialise the Child Algorithm
885 try {
886 alg->initialize();
887 } catch (std::runtime_error &) {
888 throw std::runtime_error("Unable to initialise Child Algorithm '" + alg->name() + "'");
889 }
890
891 // If output workspaces are nameless, give them a temporary name to satisfy
892 // validator
893 const std::vector<Property *> &props = alg->getProperties();
894 for (auto prop : props) {
895 const auto *wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
896 if (prop->direction() == Mantid::Kernel::Direction::Output && wsProp) {
897 if (prop->value().empty() && !wsProp->isOptional()) {
898 prop->createTemporaryValue();
899 }
900 }
901 }
902
903 if (startProgress >= 0.0 && endProgress > startProgress && endProgress <= 1.0) {
904 alg->addObserver(this->progressObserver());
905 m_startChildProgress = startProgress;
906 m_endChildProgress = endProgress;
907 }
908
909 // Before we return the shared pointer, use it to create a weak pointer and
910 // keep that in a vector.
911 // It will be used this to pass on cancellation requests
912 // It must be protected by a critical block so that Child Algorithms can run
913 // in parallel safely.
914 std::weak_ptr<IAlgorithm> weakPtr(alg);
915 PARALLEL_CRITICAL(Algorithm_StoreWeakPtr) { m_ChildAlgorithms.emplace_back(weakPtr); }
916}
917
918//=============================================================================================
919//================================== Algorithm History
920//========================================
921//=============================================================================================
922
928std::string Algorithm::toString() const { return Mantid::JsonHelpers::jsonToString(toJson()); }
929
934::Json::Value Algorithm::toJson() const {
935 ::Json::Value root;
936
937 root["name"] = name();
938 root["version"] = this->version();
939 root["properties"] = m_properties.asJson(false);
940
941 return root;
942}
943
944//--------------------------------------------------------------------------------------------
953 ::Json::Value root;
954 ::Json::Value jsonMap;
955
956 auto props = history.getProperties();
957 const size_t numProps(props.size());
958 for (size_t i = 0; i < numProps; ++i) {
959 PropertyHistory_sptr prop = props[i];
960 if (!prop->isDefault()) {
961 jsonMap[prop->name()] = prop->value();
962 }
963 }
964
965 root["name"] = history.name();
966 root["version"] = history.version();
967 root["properties"] = jsonMap;
968
969 const std::string output = Mantid::JsonHelpers::jsonToString(root);
970 IAlgorithm_sptr alg;
971
972 try {
973 alg = Algorithm::fromString(output);
974 } catch (std::invalid_argument &) {
975 throw std::runtime_error("Could not create algorithm from history. "
976 "Is this a child algorithm whose workspaces are not in the ADS?");
977 }
978 return alg;
979}
980
981//--------------------------------------------------------------------------------------------
990IAlgorithm_sptr Algorithm::fromString(const std::string &input) {
991 ::Json::Value root;
992 if (Mantid::JsonHelpers::parse(input, &root)) {
993 return fromJson(root);
994 } else {
995 throw std::runtime_error("Cannot create algorithm, invalid string format.");
996 }
997}
998
1006IAlgorithm_sptr Algorithm::fromJson(const Json::Value &serialized) {
1007 const std::string algName = serialized["name"].asString();
1008 const int versionNumber = serialized.get("version", -1).asInt();
1009 auto alg = AlgorithmManager::Instance().createUnmanaged(algName, versionNumber);
1010 alg->initialize();
1011 alg->setProperties(serialized["properties"]);
1012 return alg;
1013}
1014
1018 WorkspaceVector outputWorkspaces;
1019 if (!isChild()) {
1020 findWorkspaces(outputWorkspaces, Direction::Output);
1021 }
1022 fillHistory(outputWorkspaces);
1023}
1024
1035 return;
1036
1037 // iterate over the algorithms output workspaces
1038 const auto &algProperties = getProperties();
1039 for (const auto &prop : algProperties) {
1040 if (prop->direction() != Kernel::Direction::Output && prop->direction() != Kernel::Direction::InOut)
1041 continue;
1042 const auto *wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
1043 if (!wsProp)
1044 continue;
1045 // Check we actually have a workspace, it may have been optional
1047 if (!workspace)
1048 continue;
1049
1050 bool linked = false;
1051 // find child histories with anonymous output workspaces
1052 const auto &childHistories = m_history->getChildHistories();
1053 auto childIter = childHistories.rbegin();
1054 for (; childIter != childHistories.rend() && !linked; ++childIter) {
1055 const auto &props = (*childIter)->getProperties();
1056 auto propIter = props.begin();
1057 for (; propIter != props.end() && !linked; ++propIter) {
1058 // check we have a workspace property
1059 if ((*propIter)->direction() == Kernel::Direction::Output ||
1060 (*propIter)->direction() == Kernel::Direction::InOut) {
1061 // if the workspaces are equal, then rename the history
1062 std::ostringstream os;
1063 os << "__TMP" << wsProp->getWorkspace().get();
1064 if (os.str() == (*propIter)->value()) {
1065 (*propIter)->setValue(prop->value());
1066 linked = true;
1067 }
1068 }
1069 }
1070 }
1071 }
1072}
1073
1078void Algorithm::trackAlgorithmHistory(std::shared_ptr<AlgorithmHistory> parentHist) {
1080 m_parentHistory = std::move(parentHist);
1081}
1082
1087
1096void Algorithm::findWorkspaces(WorkspaceVector &workspaces, unsigned int direction, bool checkADS) const {
1097 auto workspaceFromWSProperty = [](const IWorkspaceProperty &prop, const AnalysisDataServiceImpl &ads,
1098 const std::string &strValue, bool checkADS) {
1099 auto workspace = prop.getWorkspace();
1100 if (workspace)
1101 return workspace;
1102
1103 // Empty string indicates optional workspace
1104 if (checkADS && !strValue.empty()) {
1105 return ads.retrieve(strValue);
1106 }
1107 return Workspace_sptr();
1108 };
1109 auto appendWS = [&workspaces](const Workspace_sptr &workspace) {
1110 if (!workspace)
1111 return false;
1112 workspaces.emplace_back(workspace);
1113 return true;
1114 };
1115
1116 // Additional output properties can be declared on the fly
1117 // so we need a fresh loop over the properties
1118 const auto &algProperties = getProperties();
1119 const auto &ads = AnalysisDataService::Instance();
1120 for (const auto &prop : algProperties) {
1121 const unsigned int propDirection = prop->direction();
1122 if (propDirection != direction && propDirection != Direction::InOut)
1123 continue;
1124 if (const auto wsProp = dynamic_cast<IWorkspaceProperty *>(prop)) {
1125 appendWS(workspaceFromWSProperty(*wsProp, ads, prop->value(), checkADS));
1126 }
1127 }
1128}
1129
1132 auto &logger = getLogger();
1133
1135 logger.notice() << name() << " started";
1136 if (this->isChild())
1137 logger.notice() << " (child)";
1138 logger.notice() << '\n';
1139 // Make use of the AlgorithmHistory class, which holds all the info we
1140 // want here
1141 AlgorithmHistory algHistory(this);
1142 size_t maxPropertyLength = 40;
1143 if (logger.is(Logger::Priority::PRIO_DEBUG)) {
1144 // include the full property value when logging in debug
1145 maxPropertyLength = 0;
1146 }
1147 algHistory.printSelf(logger.information(), 0, maxPropertyLength);
1148 }
1149}
1150
1151//=============================================================================================
1152//================================== WorkspaceGroup-related
1153//===================================
1154//=============================================================================================
1155
1178 size_t numGroups = 0;
1179 bool doProcessGroups = false;
1180
1181 // Unroll the groups or single inputs into vectors of workspaces
1182 const auto &ads = AnalysisDataService::Instance();
1184 m_groupWorkspaces.clear();
1185 for (auto inputWorkspaceProp : m_inputWorkspaceProps) {
1186 auto const prop = dynamic_cast<Property *>(inputWorkspaceProp);
1187 auto wsGroupProp = dynamic_cast<WorkspaceProperty<WorkspaceGroup> const *>(prop);
1188 auto ws = inputWorkspaceProp->getWorkspace();
1189 auto wsGroup = std::dynamic_pointer_cast<WorkspaceGroup>(ws);
1190
1191 // Workspace groups are NOT returned by IWP->getWorkspace() most of the
1192 // time because WorkspaceProperty is templated by <MatrixWorkspace> and
1193 // WorkspaceGroup does not subclass <MatrixWorkspace>
1194 if (!wsGroup && prop && !prop->value().empty()) {
1195 // So try to use the name in the AnalysisDataService
1196 try {
1197 wsGroup = ads.retrieveWS<WorkspaceGroup>(prop->value());
1198 } catch (Exception::NotFoundError &) { /* Do nothing */
1199 }
1200 }
1201
1202 // Found the group either directly or by name?
1203 // If the property is of type WorkspaceGroup then don't unroll
1204 if (wsGroup && !wsGroupProp) {
1205 numGroups++;
1206 doProcessGroups = true;
1207 m_unrolledInputWorkspaces.emplace_back(wsGroup->getAllItems());
1208 } else {
1209 // Single Workspace. Treat it as a "group" with only one member
1210 if (ws)
1212 else
1214 }
1215
1216 // Add to the list of groups
1217 m_groupWorkspaces.emplace_back(wsGroup);
1218 }
1219
1220 // No groups? Get out.
1221 if (numGroups == 0)
1222 return doProcessGroups;
1223
1224 // ---- Confirm that all the groups are the same size -----
1225 // Index of the single group
1226 m_singleGroup = -1;
1227 // Size of the single or of all the groups
1228 m_groupSize = 1;
1230 for (size_t i = 0; i < m_unrolledInputWorkspaces.size(); i++) {
1231 const auto &thisGroup = m_unrolledInputWorkspaces[i];
1232 // We're ok with empty groups if the workspace property is optional
1233 if (thisGroup.empty() && !m_inputWorkspaceProps[i]->isOptional())
1234 throw std::invalid_argument("Empty group passed as input");
1235 if (!thisGroup.empty()) {
1236 // Record the index of the single group.
1238 if (wsGroup && (numGroups == 1))
1239 m_singleGroup = int(i);
1240
1241 // For actual groups (>1 members)
1242 if (thisGroup.size() > 1) {
1243 // Check for matching group size
1244 if (m_groupSize > 1)
1245 if (thisGroup.size() != m_groupSize)
1246 throw std::invalid_argument("Input WorkspaceGroups are not of the same size.");
1247
1248 // Are ALL the names similar?
1249 if (wsGroup)
1251
1252 // Save the size for the next group
1253 m_groupSize = thisGroup.size();
1254 }
1255 }
1256 } // end for each group
1257
1258 // If you get here, then the groups are compatible
1259 return doProcessGroups;
1260}
1261
1270bool Algorithm::doCallProcessGroups(Mantid::Types::Core::DateAndTime &startTime) {
1271 // In the base implementation of processGroups, this normally calls
1272 // this->execute() again on each member of the group. Other algorithms may
1273 // choose to override that behavior (examples: CompareWorkspaces,
1274 // RenameWorkspace)
1275
1276 startTime = Mantid::Types::Core::DateAndTime::getCurrentTime();
1277 // Start a timer
1278 Timer timer;
1279 bool completed = false;
1280 try {
1281 // Call the concrete algorithm's processGroups method
1282 completed = processGroups();
1283 } catch (std::exception &ex) {
1284 // The child algorithm will already have logged the error etc.,
1285 // but we also need to update flags in the parent algorithm and
1286 // send an ErrorNotification (because the child isn't registered with the
1287 // AlgorithmMonitor).
1289 m_runningAsync = false;
1290 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
1291 throw;
1292 } catch (...) {
1294 m_runningAsync = false;
1295 notificationCenter().postNotification(new ErrorNotification(this, "UNKNOWN Exception caught from processGroups"));
1296 throw;
1297 }
1298
1299 // Check for a cancellation request in case the concrete algorithm doesn't
1301
1302 if (completed) {
1303 // Get how long this algorithm took to run
1304 const float duration = timer.elapsed();
1305
1306 if (trackingHistory()) {
1308 m_history->fillAlgorithmHistory(this, startTime, duration, g_execCount);
1309 } else {
1310 m_history = std::make_shared<AlgorithmHistory>(this, startTime, duration, ++g_execCount);
1311 }
1312 // find any further outputs created by the execution
1313 WorkspaceVector outputWorkspaces;
1314 const bool checkADS{true};
1315 findWorkspaces(outputWorkspaces, Direction::Output, checkADS);
1316 fillHistory(outputWorkspaces);
1319 }
1320 }
1321
1322 // in the base processGroups each individual exec stores its outputs
1324 this->store();
1325
1326 // Log that execution has completed.
1327 reportCompleted(duration, true /* this is for group processing*/);
1329 } else {
1331 }
1332
1333 notificationCenter().postNotification(new FinishedNotification(this, isExecuted()));
1334
1335 return completed;
1336}
1337
1345void Algorithm::fillHistory(const std::vector<Workspace_sptr> &outputWorkspaces) {
1346 // this is not a child algorithm. Add the history algorithm to the
1347 // WorkspaceHistory object.
1348 if (!isChild()) {
1349 auto copyHistoryToGroup = [](const Workspace &in, WorkspaceGroup &out) {
1350 for (auto &outGroupItem : out) {
1351 outGroupItem->history().addHistory(in.getHistory());
1352 }
1353 };
1354
1355 for (auto &outWS : outputWorkspaces) {
1356 auto outWSGroup = std::dynamic_pointer_cast<WorkspaceGroup>(outWS);
1357 // Copy the history from the cached input workspaces to the output ones
1358 for (const auto &inputWS : m_inputWorkspaceHistories) {
1359 if (outWSGroup) {
1360 copyHistoryToGroup(*inputWS, *outWSGroup);
1361 } else {
1362 outWS->history().addHistory(inputWS->getHistory());
1363 }
1364 }
1365 // Add history for this operation
1366 if (outWSGroup) {
1367 for (auto &outGroupItem : *outWSGroup) {
1368 outGroupItem->history().addHistory(m_history);
1369 }
1370 } else {
1371 // Add the history for the current algorithm to all the output
1372 // workspaces
1373 outWS->history().addHistory(m_history);
1374 }
1375 }
1376 }
1377 // this is a child algorithm, but we still want to keep the history.
1379 m_parentHistory->addChildHistory(m_history);
1380 }
1381}
1382
1383//--------------------------------------------------------------------------------------------
1397
1398 std::vector<WorkspaceGroup_sptr> outGroups;
1399
1400 // ---------- Create all the output workspaces ----------------------------
1401 for (auto &pureOutputWorkspaceProp : m_pureOutputWorkspaceProps) {
1402 auto *prop = dynamic_cast<Property *>(pureOutputWorkspaceProp);
1403 if (prop && !prop->value().empty()) {
1404 auto outWSGrp = std::make_shared<WorkspaceGroup>();
1405 outGroups.emplace_back(outWSGrp);
1406 // Put the GROUP in the ADS
1407 AnalysisDataService::Instance().addOrReplace(prop->value(), outWSGrp);
1408 outWSGrp->observeADSNotifications(false);
1409 }
1410 }
1411
1412 double progress_proportion = 1.0 / static_cast<double>(m_groupSize);
1413 // Go through each entry in the input group(s)
1414 for (size_t entry = 0; entry < m_groupSize; entry++) {
1415 // use create Child Algorithm that look like this one
1416 Algorithm_sptr alg_sptr = this->createChildAlgorithm(this->name(), progress_proportion * static_cast<double>(entry),
1417 progress_proportion * (1 + static_cast<double>(entry)),
1418 this->isLogging(), this->version());
1419 // Make a child algorithm and turn off history recording for it, but always
1420 // store result in the ADS
1421 alg_sptr->setChild(true);
1422 alg_sptr->setAlwaysStoreInADS(true);
1423 alg_sptr->enableHistoryRecordingForChild(false);
1424 alg_sptr->setRethrows(true);
1425
1426 Algorithm *alg = alg_sptr.get();
1427 // Set all non-workspace properties
1428 this->copyNonWorkspaceProperties(alg, int(entry) + 1);
1429
1430 std::string outputBaseName;
1431
1432 // ---------- Set all the input workspaces ----------------------------
1433 for (size_t iwp = 0; iwp < m_unrolledInputWorkspaces.size(); iwp++) {
1434 const std::vector<Workspace_sptr> &thisGroup = m_unrolledInputWorkspaces[iwp];
1435 if (!thisGroup.empty()) {
1436 // By default (for a single group) point to the first/only workspace
1437 Workspace_sptr ws = thisGroup[0];
1438
1439 if ((m_singleGroup == int(iwp)) || m_singleGroup < 0) {
1440 // Either: this is the single group
1441 // OR: all inputs are groups
1442 // ... so get then entry^th workspace in this group
1443 if (entry < thisGroup.size()) {
1444 ws = thisGroup[entry];
1445 } else {
1446 // This can happen when one has more than one input group
1447 // workspaces, having different sizes. For example one workspace
1448 // group is the corrections which has N parts (e.g. weights for
1449 // polarized measurement) while the other one is the actual input
1450 // workspace group, where each item needs to be corrected together
1451 // with all N inputs of the second group. In this case processGroup
1452 // needs to be overridden, which is currently not possible in
1453 // python.
1454 throw std::runtime_error("Unable to process over groups; consider passing workspaces "
1455 "one-by-one or override processGroup method of the algorithm.");
1456 }
1457 }
1458 // Append the names together
1459 if (!outputBaseName.empty())
1460 outputBaseName += "_";
1461 outputBaseName += ws->getName();
1462
1463 // Set the property using the name of that workspace
1464 if (auto *prop = dynamic_cast<Property *>(m_inputWorkspaceProps[iwp])) {
1465 if (ws->getName().empty()) {
1466 alg->setProperty(prop->name(), ws);
1467 } else {
1468 alg->setPropertyValue(prop->name(), ws->getName());
1469 }
1470 } else {
1471 throw std::logic_error("Found a Workspace property which doesn't "
1472 "inherit from Property.");
1473 }
1474 } // not an empty (i.e. optional) input
1475 } // for each InputWorkspace property
1476
1477 std::vector<std::string> outputWSNames(m_pureOutputWorkspaceProps.size());
1478 // ---------- Set all the output workspaces ----------------------------
1479 for (size_t owp = 0; owp < m_pureOutputWorkspaceProps.size(); owp++) {
1480 if (auto *prop = dynamic_cast<Property *>(m_pureOutputWorkspaceProps[owp])) {
1481 // Default name = "in1_in2_out"
1482 const std::string inName = prop->value();
1483 if (inName.empty())
1484 continue;
1485 std::string outName;
1487 outName.append(inName).append("_").append(Strings::toString(entry + 1));
1488 } else {
1489 outName.append(outputBaseName).append("_").append(inName);
1490 }
1491
1492 auto inputProp =
1493 std::find_if(m_inputWorkspaceProps.begin(), m_inputWorkspaceProps.end(), WorkspacePropertyValueIs(inName));
1494
1495 // Overwrite workspaces in any input property if they have the same
1496 // name as an output (i.e. copy name button in algorithm dialog used)
1497 // (only need to do this for a single input, multiple will be handled
1498 // by ADS)
1499 if (inputProp != m_inputWorkspaceProps.end()) {
1500 const auto &inputGroup = m_unrolledInputWorkspaces[inputProp - m_inputWorkspaceProps.begin()];
1501 if (!inputGroup.empty())
1502 outName = inputGroup[entry]->getName();
1503 }
1504 // Except if all inputs had similar names, then the name is "out_1"
1505
1506 // Set in the output
1507 alg->setPropertyValue(prop->name(), outName);
1508
1509 outputWSNames[owp] = outName;
1510 } else {
1511 throw std::logic_error("Found a Workspace property which doesn't "
1512 "inherit from Property.");
1513 }
1514 } // for each OutputWorkspace property
1515
1516 // ------------ Execute the algo --------------
1517 try {
1518 alg->execute();
1519 } catch (std::exception &e) {
1520 std::ostringstream msg;
1521 msg << "Execution of " << this->name() << " for group entry " << (entry + 1) << " failed: ";
1522 msg << e.what(); // Add original message
1523 throw std::runtime_error(msg.str());
1524 }
1525
1526 // ------------ Fill in the output workspace group ------------------
1527 // this has to be done after execute() because a workspace must exist
1528 // when it is added to a group
1529 for (size_t owp = 0; owp < m_pureOutputWorkspaceProps.size(); owp++) {
1530 auto *prop = dynamic_cast<Property *>(m_pureOutputWorkspaceProps[owp]);
1531 if (prop && prop->value().empty())
1532 continue;
1533 // And add it to the output group
1534 outGroups[owp]->add(outputWSNames[owp]);
1535 }
1536
1537 } // for each entry in each group
1538
1539 // restore group notifications
1540 for (auto &outGroup : outGroups) {
1541 outGroup->observeADSNotifications(true);
1542 }
1543
1544 return true;
1545}
1546
1547//--------------------------------------------------------------------------------------------
1554 if (!alg)
1555 throw std::runtime_error("Algorithm not created!");
1556 const auto &props = this->getProperties();
1557 for (const auto &prop : props) {
1558 if (prop) {
1559
1560 const auto *wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
1561 // Copy the property using the string
1562 if (!wsProp)
1563 this->setOtherProperties(alg, prop->name(), prop->value(), periodNum);
1564 }
1565 }
1566}
1567
1568//--------------------------------------------------------------------------------------------
1577void Algorithm::setOtherProperties(IAlgorithm *alg, const std::string &propertyName, const std::string &propertyValue,
1578 int periodNum) {
1579 (void)periodNum; // Avoid compiler warning
1580 if (alg)
1581 alg->setPropertyValue(propertyName, propertyValue);
1582}
1583
1584//--------------------------------------------------------------------------------------------
1590 if (!prop) {
1591 return false;
1592 }
1593 const auto *const wsProp = dynamic_cast<const IWorkspaceProperty *>(prop);
1594 return (wsProp != nullptr);
1595}
1596
1597//=============================================================================================
1598//================================== Asynchronous Execution
1599//===================================
1600//=============================================================================================
1601namespace {
1605struct AsyncFlagHolder {
1609 explicit AsyncFlagHolder(bool &running_flag) : m_running_flag(running_flag) { m_running_flag = true; }
1611 ~AsyncFlagHolder() { m_running_flag = false; }
1612
1613private:
1615 AsyncFlagHolder() = delete;
1618};
1619} // namespace
1620
1621//--------------------------------------------------------------------------------------------
1627 std::make_unique<Poco::ActiveMethod<bool, Poco::Void, Algorithm>>(this, &Algorithm::executeAsyncImpl);
1628 return (*m_executeAsync)(Poco::Void());
1629}
1630
1635bool Algorithm::executeAsyncImpl(const Poco::Void & /*unused*/) {
1636 AsyncFlagHolder running(m_runningAsync);
1637 return this->execute();
1638}
1639
1644Poco::NotificationCenter &Algorithm::notificationCenter() const {
1646 m_notificationCenter = std::make_unique<Poco::NotificationCenter>();
1647 return *m_notificationCenter;
1648}
1649
1653void Algorithm::handleChildProgressNotification(const Poco::AutoPtr<ProgressNotification> &pNf) {
1654 double p = m_startChildProgress + (m_endChildProgress - m_startChildProgress) * pNf->progress;
1655
1656 progress(p, pNf->message);
1657}
1658
1662const Poco::AbstractObserver &Algorithm::progressObserver() const {
1663 if (!m_progressObserver)
1664 m_progressObserver = std::make_unique<Poco::NObserver<Algorithm, ProgressNotification>>(
1666
1667 return *m_progressObserver;
1668}
1669
1670//--------------------------------------------------------------------------------------------
1675 // set myself to be cancelled
1676 m_cancel = true;
1677
1678 // Loop over the output workspaces and try to cancel them
1679 for (auto &weakPtr : m_ChildAlgorithms) {
1680 if (IAlgorithm_sptr sharedPtr = weakPtr.lock()) {
1681 sharedPtr->cancel();
1682 }
1683 }
1684}
1685
1687bool Algorithm::getCancel() const { return m_cancel; }
1688
1694bool Algorithm::isLogging() const { return g_log.getEnabled(); }
1695
1696/* Sets the logging priority offset. Values are subtracted from the log level.
1697 *
1698 * Example value=1 will turn warning into notice
1699 * Example value=-1 will turn notice into warning
1700 */
1702
1705
1706//--------------------------------------------------------------------------------------------
1711 // only throw exceptions if the code is not multi threaded otherwise you
1712 // contravene the OpenMP standard
1713 // that defines that all loops must complete, and no exception can leave an
1714 // OpenMP section
1715 // openmp cancel handling is performed using the ??, ?? and ?? macros in
1716 // each algrothim
1718 if (m_cancel)
1719 throw CancelException();
1720}
1721
1727void Algorithm::reportCompleted(const double &duration, const bool groupProcessing) {
1728 std::string optionalMessage;
1729 if (groupProcessing) {
1730 optionalMessage = ". Processed as a workspace group";
1731 }
1732
1735
1736 std::stringstream msg;
1737 msg << name() << " successful, Duration ";
1738 double seconds = duration;
1739 if (seconds > 60.) {
1740 auto minutes = static_cast<int>(seconds / 60.);
1741 msg << minutes << " minutes ";
1742 seconds = seconds - static_cast<double>(minutes) * 60.;
1743 }
1744 msg << std::fixed << std::setprecision(2) << seconds << " seconds" << optionalMessage;
1745 getLogger().notice(msg.str());
1746 }
1747 }
1748
1749 else {
1750 getLogger().debug() << name() << " finished with isChild = " << isChild() << '\n';
1751 }
1753}
1754
1758 if (UsageService::Instance().isEnabled()) {
1759 std::ostringstream oss;
1760 oss << this->name() << ".v" << this->version();
1761 UsageService::Instance().registerFeatureUsage(FeatureType::Algorithm, oss.str(), isChild());
1762 }
1763}
1764
1769
1774
1775bool Algorithm::isCompoundProperty(const std::string &name) const {
1776 return std::find(m_reservedList.cbegin(), m_reservedList.cend(), name) != m_reservedList.cend();
1777}
1778
1779//---------------------------------------------------------------------------
1780// Algorithm's inner classes
1781//---------------------------------------------------------------------------
1782
1784 : Poco::Notification(), m_algorithm(alg) {}
1785
1786const IAlgorithm *Algorithm::AlgorithmNotification::algorithm() const { return m_algorithm; }
1787
1789std::string Algorithm::StartedNotification::name() const { return "StartedNotification"; }
1790
1792 : AlgorithmNotification(alg), success(res) {}
1793std::string Algorithm::FinishedNotification::name() const { return "FinishedNotification"; }
1794
1795Algorithm::ProgressNotification::ProgressNotification(const Algorithm *const alg, double p, std::string msg,
1796 double estimatedTime, int progressPrecision)
1797 : AlgorithmNotification(alg), progress(p), message(std::move(msg)), estimatedTime(estimatedTime),
1798 progressPrecision(progressPrecision) {}
1799
1800std::string Algorithm::ProgressNotification::name() const { return "ProgressNotification"; }
1801
1803 : AlgorithmNotification(alg), what(std::move(str)) {}
1804
1805std::string Algorithm::ErrorNotification::name() const { return "ErrorNotification"; }
1806
1807const char *Algorithm::CancelException::what() const noexcept { return "Algorithm terminated"; }
1808
1815void Algorithm::declareProperty(std::unique_ptr<Property> p, const std::string &doc) {
1816 m_properties.declareProperty(std::move(p), doc);
1817}
1818
1823void Algorithm::declareOrReplaceProperty(std::unique_ptr<Property> p, const std::string &doc) {
1824 m_properties.declareOrReplaceProperty(std::move(p), doc);
1825}
1826
1830
1842void Algorithm::setProperties(const std::string &propertiesJson,
1843 const std::unordered_set<std::string> &ignoreProperties, bool createMissing) {
1844 m_properties.setProperties(propertiesJson, ignoreProperties, createMissing);
1845}
1846
1853void Algorithm::setProperties(const ::Json::Value &jsonValue, const std::unordered_set<std::string> &ignoreProperties,
1854 bool createMissing) {
1855 m_properties.setProperties(jsonValue, ignoreProperties, createMissing);
1856}
1857
1864void Algorithm::setPropertiesWithString(const std::string &propertiesString,
1865 const std::unordered_set<std::string> &ignoreProperties) {
1866 m_properties.setPropertiesWithString(propertiesString, ignoreProperties);
1867}
1868
1877void Algorithm::setPropertyValue(const std::string &name, const std::string &value) {
1879 this->afterPropertySet(name);
1880}
1881
1889void Algorithm::setPropertyValueFromJson(const std::string &name, const Json::Value &value) {
1891 this->afterPropertySet(name);
1892}
1893
1904
1910bool Algorithm::existsProperty(const std::string &name) const { return m_properties.existsProperty(name); }
1911
1916
1922
1928std::string Algorithm::getPropertyValue(const std::string &name) const { return m_properties.getPropertyValue(name); }
1929
1938
1947
1952const std::vector<Property *> &Algorithm::getProperties() const { return m_properties.getProperties(); }
1953
1958std::vector<std::string> Algorithm::getDeclaredPropertyNames() const noexcept {
1960}
1961
1981
1986bool Algorithm::isDefault(const std::string &name) const {
1988}
1989
1997std::string Algorithm::asString(bool withDefaultValues) const { return m_properties.asString(withDefaultValues); }
2004::Json::Value Algorithm::asJson(bool withDefaultValues) const { return m_properties.asJson(withDefaultValues); }
2005
2011void Algorithm::removeProperty(const std::string &name, const bool delproperty) {
2012 m_properties.removeProperty(name, delproperty);
2013}
2014
2020std::unique_ptr<Kernel::Property> Algorithm::takeProperty(const size_t index) {
2022}
2023
2028
2036
2037} // namespace API
2038
2039//---------------------------------------------------------------------------
2040// Specialized templated PropertyManager getValue definitions for Algorithm
2041// types
2042//---------------------------------------------------------------------------
2043namespace Kernel {
2049template <>
2050MANTID_API_DLL API::IAlgorithm_sptr IPropertyManager::getValue<API::IAlgorithm_sptr>(const std::string &name) const {
2051 auto *prop = dynamic_cast<PropertyWithValue<API::IAlgorithm_sptr> *>(getPointerToProperty(name));
2052 if (prop) {
2053 return *prop;
2054 } else {
2055 std::string message = "Attempt to assign property " + name + " to incorrect type. Expected shared_ptr<IAlgorithm>";
2056 throw std::runtime_error(message);
2057 }
2058}
2059
2066template <>
2068IPropertyManager::getValue<API::IAlgorithm_const_sptr>(const std::string &name) const {
2069 const auto *prop = dynamic_cast<PropertyWithValue<API::IAlgorithm_sptr> *>(getPointerToProperty(name));
2070 if (prop) {
2071 return prop->operator()();
2072 } else {
2073 std::string message =
2074 "Attempt to assign property " + name + " to incorrect type. Expected const shared_ptr<IAlgorithm>";
2075 throw std::runtime_error(message);
2076 }
2077}
2078
2079} // namespace Kernel
2080
2081} // namespace Mantid
const std::string & m_value
Definition Algorithm.cpp:71
bool & m_running_flag
Running flag.
T m_onfinsh
Definition Algorithm.cpp:79
std::string name
Definition Run.cpp:60
double value
The value of the point.
Definition FitMW.cpp:51
double error
IPeaksWorkspace_sptr workspace
std::map< DeltaEMode::Type, std::string > index
#define PARALLEL_CRITICAL(name)
#define IF_NOT_PARALLEL
std::vector< history_type > history
history information
ADSValidator : a validator that requires the value of a property to be present in the ADS.
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:79
AlgorithmNotification(const Algorithm *const alg)
CancelException is thrown to cancel execution of the algorithm.
Definition Algorithm.h:136
const char * what() const noexcept override
Returns the message string.
ErrorNotification is sent when an exception is caught during execution of the algorithm.
Definition Algorithm.h:121
std::string name() const override
ErrorNotification(const Algorithm *const alg, std::string str)
Constructor.
FinishedNotification is sent after the algorithm finishes its execution.
Definition Algorithm.h:96
FinishedNotification(const Algorithm *const alg, bool res)
An algorithm can report its progress by sending ProgressNotification.
Definition Algorithm.h:106
ProgressNotification(const Algorithm *const alg, double p, std::string msg, double estimatedTime, int progressPrecision)
Constructor.
StartedNotification is sent when the algorithm begins execution.
Definition Algorithm.h:89
StartedNotification(const Algorithm *const alg)
std::string name() const override
class name
Base class from which all concrete algorithm classes should be derived.
Definition Algorithm.h:76
void clearWorkspaceCaches()
Clear any internal workspace handles so that workspaces will be deleted promptly after a managed algo...
void setRethrows(const bool rethrow) override
Set whether the algorithm will rethrow exceptions.
const std::string categorySeparator() const override
Function to return the separator token for the category string.
Definition Algorithm.h:165
std::vector< std::shared_ptr< WorkspaceGroup > > m_groupWorkspaces
Pointer to the WorkspaceGroup (if any) for each input workspace property.
Definition Algorithm.h:516
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
void store()
Stores any output workspaces into the AnalysisDataService.
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:523
bool isRunning() const override
True if the algorithm is running.
void setExecutionState(const ExecutionState state)
Sets the current execution state.
virtual const std::string workspaceMethodOnTypes() const
Returns a semi-colon separated list of workspace types to attach this algorithm.
Definition Algorithm.h:365
Kernel::Property * getPointerToProperty(const std::string &name) const override
Get a property by name.
const std::string workspaceMethodName() const override
bool calledByAlias
Flag to indicate if the algorithm is called by its alias.
Definition Algorithm.h:172
std::vector< std::string > getDeclaredPropertyNames() const noexcept override
Return the list of declared property names.
std::unique_ptr< Poco::NObserver< Algorithm, ProgressNotification > > m_progressObserver
Child algorithm progress observer.
Definition Algorithm.h:481
std::vector< std::string > m_reservedList
Reserved property names.
Definition Algorithm.h:526
AlgorithmID getAlgorithmID() const override
Algorithm ID.
Definition Algorithm.h:204
int m_singleGroup
If only one input is a group, this is its index. -1 if they are all groups.
Definition Algorithm.h:518
void clear() override
Clears all properties under management.
std::vector< IWorkspaceProperty * > m_inputWorkspaceProps
All the WorkspaceProperties that are Input or InOut. Set in execute()
Definition Algorithm.h:417
bool isExecuted() const override
Has the Algorithm already been executed successfully.
::Json::Value asJson(bool withDefaultValues=false) const override
Return the property manager serialized as a json object.
void registerFeatureUsage() const
Registers the usage of the algorithm with the UsageService.
bool existsProperty(const std::string &name) const override
Checks whether the named property is already in the list of managed property.
WorkspaceVector m_writeLockedWorkspaces
Vector of all the workspaces that have been write-locked.
Definition Algorithm.h:508
bool m_rethrow
Algorithm should rethrow exceptions while executing.
Definition Algorithm.h:490
bool validateProperties() const override
Validates all the properties in the collection.
double m_startChildProgress
Whether to log alg startup and closedown messages from the base class (default = true)
Definition Algorithm.h:494
void setPropertyOrdinal(const int &index, const std::string &value) override
Set the value of a property by an index N.B.
void afterPropertySet(const std::string &) override
Override this method to perform a custom action right after a property was set.
bool m_usingBaseProcessGroups
distinguish between base processGroups() and overriden/algorithm specific versions
Definition Algorithm.h:435
void setAlgStartupLogging(const bool enabled) override
disable Logging of start and end messages
void removeProperty(const std::string &name, const bool delproperty=true) override
Removes the property from management.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
std::vector< std::weak_ptr< IAlgorithm > > m_ChildAlgorithms
A list of weak pointers to any child algorithms created.
Definition Algorithm.h:499
Kernel::Property * getPointerToPropertyOrdinal(const int &index) const override
Get a property by an index.
std::unique_ptr< Kernel::Property > takeProperty(const size_t index) override
Removes the property from management and returns a pointer to it.
bool m_recordHistoryForProcessGroups
Opt-in for overridden processGroups() implementations that want the parent algorithm history recorded...
Definition Algorithm.h:438
void copyNonWorkspaceProperties(IAlgorithm *alg, int periodNum)
Copy all the non-workspace properties from this to alg.
std::atomic< bool > m_cancel
Set to true to stop execution.
Definition Algorithm.h:405
void setLogging(const bool value) override
Logging can be disabled by passing a value of false.
std::shared_ptr< AlgorithmHistory > m_parentHistory
Pointer to the parent history object (if set)
Definition Algorithm.h:426
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
virtual void fillHistory()
Copy workspace history from input workspaces to output workspaces and record the history for ths algo...
void setResultState(const ResultState state)
Sets the result execution state.
void handleChildProgressNotification(const Poco::AutoPtr< ProgressNotification > &pNf)
Observation slot for child algorithm progress notification messages, these are scaled and then signal...
void addObserver(const Poco::AbstractObserver &observer) const override
Add an observer for a notification.
std::string toString() const override
Serialize an object to a string.
std::shared_ptr< AlgorithmHistory > m_history
Pointer to the history for the algorithm being executed.
Definition Algorithm.h:419
std::vector< IWorkspaceProperty * > m_outputWorkspaceProps
All the WorkspaceProperties that are Output or InOut. Set in execute()
Definition Algorithm.h:511
void initialize() override
Initialization method invoked by the framework.
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.
std::vector< IWorkspaceProperty * > m_pureOutputWorkspaceProps
All the WorkspaceProperties that are Output (not inOut). Set in execute()
Definition Algorithm.h:513
size_t propertyCount() const override
Count the number of properties under management.
bool isChild() const override
To query whether algorithm is a child.
void setLoggingOffset(const int value) override
gets the logging priority offset
size_t m_groupSize
Size of the group(s) being processed.
Definition Algorithm.h:432
static IAlgorithm_sptr fromString(const std::string &input)
De-serialize an object from a string.
WorkspaceVector m_readLockedWorkspaces
Vector of all the workspaces that have been read-locked.
Definition Algorithm.h:506
virtual void init()=0
Virtual method - must be overridden by concrete algorithm.
Kernel::Logger & g_log
Definition Algorithm.h:423
std::vector< std::shared_ptr< Workspace > > WorkspaceVector
Definition Algorithm.h:283
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
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.
bool isInitialized() const override
Has the Algorithm already been initialized.
bool m_alwaysStoreInADS
Always store in the ADS, even for child algos.
Definition Algorithm.h:488
ExecutionState executionState() const override
Gets the current execution state.
bool trackingHistory()
get whether we are tracking the history for this algorithm,
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...
void linkHistoryWithLastChild()
Link the name of the output workspaces on this parent algorithm.
bool isLogging() const override
returns the status of logging, True = enabled
bool getAlgStartupLogging() const override
get the state of Logging of start and end messages
bool isWorkspaceProperty(const Kernel::Property *const prop) const
checks the property is a workspace property
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.
std::atomic< ResultState > m_resultState
the current result State
Definition Algorithm.h:484
bool isReadyForGarbageCollection() const override
True if the algorithm is ready for garbage collection.
Poco::NotificationCenter & notificationCenter() const
Return a reference to the algorithm's notification dispatcher.
int getLoggingOffset() const override
returns the logging priority offset
std::unique_ptr< Poco::ActiveMethod< bool, Poco::Void, Algorithm, Poco::ActiveStarter< Algorithm > > > m_executeAsync
Poco::ActiveMethod used to implement asynchronous execution.
Definition Algorithm.h:474
std::vector< WorkspaceVector > m_unrolledInputWorkspaces
One vector of workspaces for each input workspace property.
Definition Algorithm.h:430
void resetProperties() override
Reset property values back to initial values (blank or default values)
void removeObserver(const Poco::AbstractObserver &observer) const override
Remove an observer.
void logAlgorithmInfo() const
Sends out algorithm parameter information to the logger.
void reportCompleted(const double &duration, const bool groupProcessing=false)
Report that the algorithm has completed.
bool m_isChildAlgorithm
Algorithm is a child algorithm.
Definition Algorithm.h:485
bool getAlwaysStoreInADS() const override
Returns true if we always store in the AnalysisDataService.
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 executeInternal()
Invoced internally in execute()
Mantid::Kernel::PropertyManagerOwner m_properties
Definition Algorithm.h:531
ResultState resultState() const override
Gets the current result State.
const std::string category() const override
function to return a category of the algorithm.
Definition Algorithm.h:160
virtual void exec()=0
Virtual method - must be overridden by concrete algorithm.
void executeAsChildAlg() override
Execute as a Child Algorithm.
bool isDefault(const std::string &name) const
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.
const std::string workspaceMethodInputProperty() const override
std::string asString(bool withDefaultValues=false) const override
Return the property manager serialized as a string.
void declareOrReplaceProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add or replace property in the list of managed properties.
void interruption_point()
This is called during long-running operations, and check if the algorithm has requested that it be ca...
const std::vector< std::string > categories() const override
Function to return all of the categories that contain this algorithm.
void cancel() override
Raises the cancel flag.
const std::vector< std::string > workspaceMethodOn() const override
void setPropertyValue(const std::string &name, const std::string &value) override
Set the value of a property by string N.B.
~Algorithm() override
Virtual destructor.
void enableHistoryRecordingForChild(const bool on) override
Change the state of the history recording flag.
bool m_runningAsync
Algorithm is running asynchronously.
Definition Algorithm.h:489
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:483
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:520
Poco::ActiveResult< bool > executeAsync() override
Asynchronous execution.
std::map< std::string, std::string > validateInputs() override
Perform validation of ALL the input properties of the algorithm.
void lockWorkspaces()
Go through the workspace properties of this algorithm and lock the workspaces for reading or writing.
void setupAsChildAlgorithm(const Algorithm_sptr &algorithm, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true)
Setup algorithm as child algorithm.
bool getCancel() const
Returns the cancellation state.
bool doCallProcessGroups(Mantid::Types::Core::DateAndTime &start_time)
Calls process groups with the required timing checks and algorithm execution finalization steps.
void cacheWorkspaceProperties()
Go through the properties and cache the input/output workspace properties for later use.
::Json::Value toJson() const override
Serialize an object to a json object.
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...
Kernel::Logger & getLogger() const
Returns a reference to the logger.
void cacheInputWorkspaceHistories()
Cache the histories of any input workspaces so they can be copied over after algorithm completion.
double m_endChildProgress
Keeps value for algorithm's progress at Child Algorithm's finish.
Definition Algorithm.h:496
virtual bool checkGroups()
Check the input workspace properties for groups.
bool isCompoundProperty(const std::string &name) const
Algorithm()
Constructor.
Mantid::Types::Core::DateAndTime m_gcTime
The earliest this class should be considered for garbage collection.
Definition Algorithm.h:529
std::unique_ptr< Poco::NotificationCenter > m_notificationCenter
Sends notifications to observers.
Definition Algorithm.h:479
void setChild(const bool isChild) override
To set whether algorithm is a child.
void setPropertyValueFromJson(const std::string &name, const Json::Value &value) override
Set the value of a property by Json::Value object.
static size_t g_execCount
Counter to keep track of algorithm execution order.
Definition Algorithm.h:411
bool m_recordHistoryForChild
Flag to indicate whether history should be recorded.
Definition Algorithm.h:486
static IAlgorithm_sptr fromHistory(const AlgorithmHistory &history)
Construct an object from a history entry.
static IAlgorithm_sptr fromJson(const Json::Value &input)
De-serialize an object from a Json.
void unlockWorkspaces()
Unlock any previously locked workspaces.
const std::vector< Kernel::Property * > & getProperties() const override
Get the list of managed properties.
virtual bool processGroups()
Process WorkspaceGroup inputs.
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.
const Poco::AbstractObserver & progressObserver() const
Return a reference to the algorithm's object that is reporting progress.
void enableHistoryRecordingForProcessGroups(const bool on) override
Change the state of the processGroups history recording flag.
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.
bool areNamesSimilar() const
Are the members of this group of similar names, e.g.
A property class for workspaces.
Workspace_sptr getWorkspace() const override
Get a pointer to the workspace.
Base Workspace Abstract Class.
Definition Workspace.h:29
const WorkspaceHistory & getHistory() const
Returns a reference to the WorkspaceHistory const.
Definition Workspace.h:85
Support for a property that holds an array of values.
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:51
void debug(const std::string &msg)
Logs at debug level.
Definition Logger.cpp:145
void notice(const std::string &msg)
Logs at notice level.
Definition Logger.cpp:126
void setName(const std::string &name)
Update the name of the logger.
Definition Logger.cpp:69
int getLevelOffset() const
Gets the Logger's log offset level.
Definition Logger.cpp:467
void error(const std::string &msg)
Logs at error level.
Definition Logger.cpp:108
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
void setEnabled(const bool enabled)
set if the logging is enabled
Definition Logger.cpp:90
bool getEnabled() const
returns true if the log is enabled
Definition Logger.cpp:83
void fatal(const std::string &msg)
Logs at Fatal level.
Definition Logger.cpp:99
void setLevelOffset(int level)
Sets the Logger's log offset level.
Definition Logger.cpp:461
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:63
virtual std::string value() const =0
Returns the value of the property as a string.
@ 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
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
MANTID_API_DLL void setPropertyModeForWorkspaceProperty(Mantid::Kernel::Property *prop, const PropertyMode::Type &optional)
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
Definition Algorithm.h:52
Mantid::Kernel::StringTokenizer tokenizer
std::string toString(const T &value)
Convert a number to a string.
Definition Strings.cpp:734
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:24
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition EmptyValues.h:42
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.