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 +
19
20#include "MantidJson/Json.h"
27#include "MantidKernel/Timer.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 <H5Cpp.h>
38#include <json/json.h>
39
40#include <algorithm>
41#include <iterator>
42#include <map>
43#include <memory>
44#include <utility>
45
46// Index property handling template definitions
48
49using namespace Mantid::Kernel;
50
51namespace Mantid {
52namespace API {
53namespace {
55const std::string WORKSPACE_TYPES_SEPARATOR = ";";
56
59const size_t DELAY_BEFORE_GC = 5;
60
61class WorkspacePropertyValueIs {
62public:
63 explicit WorkspacePropertyValueIs(const std::string &value) : m_value(value) {}
64 bool operator()(IWorkspaceProperty *property) {
65 auto *prop = dynamic_cast<Property *>(property);
66 if (!prop)
67 return false;
68 return prop->value() == m_value;
69 }
70
71private:
72 const std::string &m_value;
73};
74
75template <typename T> struct RunOnFinish {
76 RunOnFinish(T &&task) : m_onfinsh(std::move(task)) {}
77 ~RunOnFinish() { m_onfinsh(); }
78
79private:
81};
82
83} // namespace
84
85// Doxygen can't handle member specialization at the moment:
86// https://bugzilla.gnome.org/show_bug.cgi?id=406027
87// so we have to ignore them
89template <typename NumT> bool Algorithm::isEmpty(const NumT toCheck) {
90 return static_cast<int>(toCheck) == EMPTY_INT();
91}
92
93template <> MANTID_API_DLL bool Algorithm::isEmpty(const double toCheck) {
94 return std::abs((toCheck - EMPTY_DBL()) / (EMPTY_DBL())) < 1e-8;
95}
96
97// concrete instantiations
98template MANTID_API_DLL bool Algorithm::isEmpty<int>(const int);
99template MANTID_API_DLL bool Algorithm::isEmpty<int64_t>(const int64_t);
100template MANTID_API_DLL bool Algorithm::isEmpty<std::size_t>(const std::size_t);
102
103//=============================================================================================
104//================================== Constructors/Destructors
105//=================================
106//=============================================================================================
107
109size_t Algorithm::g_execCount = 0;
110
113 : m_cancel(false), m_parallelException(false), m_log("Algorithm"), g_log(m_log), m_groupSize(0),
114 m_executeAsync(nullptr), m_notificationCenter(nullptr), m_progressObserver(nullptr),
115 m_executionState(ExecutionState::Uninitialized), m_resultState(ResultState::NotFinished),
116 m_isChildAlgorithm(false), m_recordHistoryForChild(false), m_alwaysStoreInADS(true), m_runningAsync(false),
117 m_rethrow(false), m_isAlgStartupLoggingEnabled(true), m_startChildProgress(0.), m_endChildProgress(0.),
118 m_algorithmID(this), m_singleGroup(-1), m_groupsHaveSimilarNames(false), m_inputWorkspaceHistories(),
119 m_properties() {}
120
122Algorithm::~Algorithm() = default;
123
124//=============================================================================================
125//================================== Simple Getters/Setters
126//===================================
127//=============================================================================================
128
131
134
137
146
147//---------------------------------------------------------------------------------------------
150
155
156//---------------------------------------------------------------------------------------------
162
167void Algorithm::setChild(const bool isChild) {
169 this->setAlwaysStoreInADS(!isChild);
170}
171
178
183
189void Algorithm::setAlwaysStoreInADS(const bool doStore) {
190 m_alwaysStoreInADS = doStore;
191
192 // Set OutputWorkspace as an optional property in the case where alwaysStoreInADS is false. In
193 // this case, the output workspace name is not always required.
194 if (!m_alwaysStoreInADS && m_properties.existsProperty("OutputWorkspace")) {
195 Property *property = m_properties.getPointerToProperty("OutputWorkspace");
197 }
198}
199
204
208void Algorithm::setRethrows(const bool rethrow) { this->m_rethrow = rethrow; }
209
212
216 (Mantid::Types::Core::DateAndTime::getCurrentTime() > m_gcTime)) {
217 return true;
218 }
219 return false;
220}
221
222//---------------------------------------------------------------------------------------------
226void Algorithm::addObserver(const Poco::AbstractObserver &observer) const {
227 notificationCenter().addObserver(observer);
228}
229
233void Algorithm::removeObserver(const Poco::AbstractObserver &observer) const {
234 notificationCenter().removeObserver(observer);
235}
236
237//---------------------------------------------------------------------------------------------
246void Algorithm::progress(double p, const std::string &msg, double estimatedTime, int progressPrecision) {
247 notificationCenter().postNotification(new ProgressNotification(this, p, msg, estimatedTime, progressPrecision));
248}
249
250//---------------------------------------------------------------------------------------------
252const std::vector<std::string> Algorithm::categories() const {
256
257 auto res = tokenizer.asVector();
258
259 const auto *depo = dynamic_cast<const DeprecatedAlgorithm *>(this);
260 if (depo != nullptr) {
261 res.emplace_back("Deprecated");
262 }
263 return res;
264}
265
270const std::string Algorithm::workspaceMethodName() const { return ""; }
271
283
287const std::string Algorithm::workspaceMethodInputProperty() const { return ""; }
288
289//---------------------------------------------------------------------------------------------
299 // Bypass the initialization if the algorithm has already been initialized.
300 if (isInitialized())
301 return;
302
303 g_log.setName(this->name());
305 try {
306 try {
307 this->init();
308 } catch (std::runtime_error &) {
309 throw;
310 }
311
312 // Indicate that this Algorithm has been initialized to prevent duplicate
313 // attempts.
315 } catch (std::runtime_error &) {
316 throw;
317 }
318 // Unpleasant catch-all! Along with this, Gaudi version catches GaudiException
319 // & std::exception
320 // but doesn't really do anything except (print fatal) messages.
321 catch (...) {
322 // Gaudi: A call to the auditor service is here
323 // (1) perform the printout
324 getLogger().fatal("UNKNOWN Exception is caught in initialize()");
325 throw;
326 }
327}
328
329//---------------------------------------------------------------------------------------------
338std::map<std::string, std::string> Algorithm::validateInputs() { return std::map<std::string, std::string>(); }
339
340//---------------------------------------------------------------------------------------------
346 m_inputWorkspaceProps.clear();
349 const auto &props = this->getProperties();
350 for (const auto &prop : props) {
351 auto wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
352 if (!wsProp)
353 continue;
354 switch (prop->direction()) {
356 m_inputWorkspaceProps.emplace_back(wsProp);
357 break;
359 m_inputWorkspaceProps.emplace_back(wsProp);
360 m_outputWorkspaceProps.emplace_back(wsProp);
361 break;
363 m_outputWorkspaceProps.emplace_back(wsProp);
364 m_pureOutputWorkspaceProps.emplace_back(wsProp);
365 break;
366 default:
367 throw std::logic_error("Unexpected property direction found for property " + prop->name() + " of algorithm " +
368 this->name());
369 }
370 }
371}
372
378 if (!trackingHistory())
379 return;
380
381 auto cacheHistories = [this](const Workspace_sptr &ws) {
382 if (auto group = dynamic_cast<const WorkspaceGroup *>(ws.get())) {
384 std::copy(group->begin(), group->end(), std::back_inserter(m_inputWorkspaceHistories));
385 } else {
386 m_inputWorkspaceHistories.emplace_back(ws);
387 }
388 };
389 using ArrayPropertyString = ArrayProperty<std::string>;
390 auto isADSValidator = [](const IValidator_sptr &validator) -> bool {
391 if (!validator)
392 return false;
393 if (dynamic_cast<ADSValidator *>(validator.get()))
394 return true;
395 if (const auto compValidator = dynamic_cast<CompositeValidator *>(validator.get()))
396 return compValidator->contains<ADSValidator>();
397
398 return false;
399 };
400
401 // Look over all properties so we can catch an string array properties
402 // with an ADSValidator. ADSValidator indicates that the strings
403 // point to workspace names so we want to pick up the history from these too.
404 const auto &ads = AnalysisDataService::Instance();
406 const auto &props = this->getProperties();
407 for (const auto &prop : props) {
408 if (prop->direction() != Direction::Input && prop->direction() != Direction::InOut)
409 continue;
410
411 if (auto wsProp = dynamic_cast<IWorkspaceProperty const *>(prop)) {
412 if (auto ws = wsProp->getWorkspace()) {
413 cacheHistories(ws);
414 } else {
415 Workspace_sptr wsFromADS;
416 try {
417 wsFromADS = ads.retrieve(prop->value());
418 } catch (Exception::NotFoundError &) {
419 continue;
420 }
421 cacheHistories(wsFromADS);
422 }
423 } else if (auto strArrayProp = dynamic_cast<ArrayPropertyString *>(prop)) {
424 if (!isADSValidator(strArrayProp->getValidator()))
425 continue;
426 const auto &wsNames((*strArrayProp)());
427 for (const auto &wsName : wsNames) {
428 cacheHistories(ads.retrieve(wsName));
429 }
430 }
431 }
432} // namespace API
433
434//---------------------------------------------------------------------------------------------
440 // Do not lock workspace for child algos
441 if (this->isChild())
442 return;
443
444 if (!m_readLockedWorkspaces.empty() || !m_writeLockedWorkspaces.empty())
445 throw std::logic_error("Algorithm::lockWorkspaces(): The workspaces have "
446 "already been locked!");
447
448 // First, Write-lock the output workspaces
449 auto &debugLog = g_log.debug();
450 for (auto &outputWorkspaceProp : m_outputWorkspaceProps) {
451 Workspace_sptr ws = outputWorkspaceProp->getWorkspace();
452 if (ws) {
453 // The workspace property says to do locking,
454 // AND it has NOT already been write-locked
455 if (outputWorkspaceProp->isLocking() && std::find(m_writeLockedWorkspaces.begin(), m_writeLockedWorkspaces.end(),
456 ws) == m_writeLockedWorkspaces.end()) {
457 // Write-lock it if not already
458 debugLog << "Write-locking " << ws->getName() << '\n';
459 ws->getLock()->writeLock();
460 m_writeLockedWorkspaces.emplace_back(ws);
461 }
462 }
463 }
464
465 // Next read-lock the input workspaces
466 for (auto &inputWorkspaceProp : m_inputWorkspaceProps) {
467 Workspace_sptr ws = inputWorkspaceProp->getWorkspace();
468 if (ws) {
469 // The workspace property says to do locking,
470 // AND it has NOT already been write-locked
471 if (inputWorkspaceProp->isLocking() && std::find(m_writeLockedWorkspaces.begin(), m_writeLockedWorkspaces.end(),
472 ws) == m_writeLockedWorkspaces.end()) {
473 // Read-lock it if not already write-locked
474 debugLog << "Read-locking " << ws->getName() << '\n';
475 ws->getLock()->readLock();
476 m_readLockedWorkspaces.emplace_back(ws);
477 }
478 }
479 }
480}
481
482//---------------------------------------------------------------------------------------------
487 // Do not lock workspace for child algos
488 if (this->isChild())
489 return;
490 auto &debugLog = g_log.debug();
491 for (auto &ws : m_writeLockedWorkspaces) {
492 if (ws) {
493 debugLog << "Unlocking " << ws->getName() << '\n';
494 ws->getLock()->unlock();
495 }
496 }
497 for (auto &ws : m_readLockedWorkspaces) {
498 if (ws) {
499 debugLog << "Unlocking " << ws->getName() << '\n';
500 ws->getLock()->unlock();
501 }
502 }
503
504 // Don't double-unlock workspaces
507}
508
521
522//---------------------------------------------------------------------------------------------
527 Timer timer;
528 bool algIsExecuted = false;
529 AlgorithmManager::Instance().notifyAlgorithmStarting(this->getAlgorithmID());
530
531 // runtime check for deprecation warning
532 {
533 auto *depo = dynamic_cast<DeprecatedAlgorithm *>(this);
534 if (depo != nullptr)
535 getLogger().error(depo->deprecationMsg(this));
536 }
537
538 // runtime check for deprecated alias warning
539 {
540 auto *da_alg = dynamic_cast<DeprecatedAlias *>(this);
541 if ((da_alg != nullptr) && (this->calledByAlias))
542 getLogger().warning(da_alg->deprecationMessage(this));
543 }
544
545 // Register clean up tasks that should happen regardless of the route
546 // out of the algorithm. These tasks will get run after this method
547 // finishes.
548 RunOnFinish onFinish([this]() { this->clearWorkspaceCaches(); });
549
550 notificationCenter().postNotification(new StartedNotification(this));
551 Mantid::Types::Core::DateAndTime startTime;
552
553 // Return a failure if the algorithm hasn't been initialized
554 if (!isInitialized()) {
555 throw std::runtime_error("Algorithm is not initialised:" + this->name());
556 }
557
558 // no logging of input if a child algorithm (except for python child algos)
561
562 // Check all properties for validity
563 constexpr bool resetTimer{true};
564 float timingInit = timer.elapsed(resetTimer);
565 if (!validateProperties()) {
566 // Reset name on input workspaces to trigger attempt at collection from ADS
567 const auto &props = getProperties();
568 for (auto &prop : props) {
569 const auto *wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
570 if (wsProp && !(wsProp->getWorkspace())) {
571 // Setting it's name to the same one it already had
572 prop->setValue(prop->value());
573 }
574 }
575 // Try the validation again
576 if (!validateProperties()) {
577 notificationCenter().postNotification(new ErrorNotification(this, "Some invalid Properties found"));
578 throw std::runtime_error("Some invalid Properties found");
579 }
580 }
581 const float timingPropertyValidation = timer.elapsed(resetTimer);
582
583 // All properties are now valid - cache workspace properties and histories
586
587 // ----- Check for processing groups -------------
588 // default true so that it has the right value at the check below the catch
589 // block should checkGroups throw
590 bool callProcessGroups = true;
591 try {
592 // Checking the input is a group. Throws if the sizes are wrong
593 callProcessGroups = this->checkGroups();
594 } catch (std::exception &ex) {
595 getLogger().error() << "Error in execution of algorithm " << this->name() << "\n" << ex.what() << "\n";
596 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
599 m_runningAsync = false;
600 throw;
601 }
602 return false;
603 }
604
605 timingInit += timer.elapsed(resetTimer);
606 // ----- Perform validation of the whole set of properties -------------
607 if ((!callProcessGroups)) // for groups this is called on each workspace separately
608 {
609 std::map<std::string, std::string> errors = this->validateInputs();
610 if (!errors.empty()) {
611 size_t numErrors = errors.size();
612 // Log each issue
613 auto &errorLog = getLogger().error();
614 auto &warnLog = getLogger().warning();
615 for (auto &error : errors) {
616 if (this->existsProperty(error.first))
617 errorLog << "Invalid value for " << error.first << ": " << error.second << "\n";
618 else {
619 numErrors -= 1; // don't count it as an error
620 warnLog << "validateInputs() references non-existant property \"" << error.first << "\"\n";
621 }
622 }
623 // Throw because something was invalid
624 if (numErrors > 0) {
625 std::stringstream msg;
626 msg << "Some invalid Properties found: ";
627 for (const auto &error : errors) {
628 msg << "\n " << error.first << ": " << error.second;
629 }
630 notificationCenter().postNotification(new ErrorNotification(this, "Some invalid Properties found"));
631 throw std::runtime_error(msg.str());
632 }
633 }
634 }
635 const float timingInputValidation = timer.elapsed(resetTimer);
636
637 if (trackingHistory()) {
638 // count used for defining the algorithm execution order
639 // If history is being recorded we need to count this as a separate
640 // algorithm
641 // as the history compares histories by their execution number
643
644 // populate history record before execution so we can record child
645 // algorithms in it
646 AlgorithmHistory algHist;
647 m_history = std::make_shared<AlgorithmHistory>(algHist);
648 }
649
650 // ----- Process groups -------------
651 // If checkGroups() threw an exception but there ARE group workspaces
652 // (means that the group sizes were incompatible)
653 if (callProcessGroups) {
654 return doCallProcessGroups(startTime);
655 }
656
657 // Read or write locks every input/output workspace
658 this->lockWorkspaces();
659 timingInit += timer.elapsed(resetTimer);
660
661 // Invoke exec() method of derived class and catch all uncaught exceptions
662 try {
663 try {
665
666 startTime = Mantid::Types::Core::DateAndTime::getCurrentTime();
667 // Call the concrete algorithm's exec method
668 this->exec();
670 // Check for a cancellation request in case the concrete algorithm doesn't
672 const float timingExec = timer.elapsed(resetTimer);
673 // The total runtime including all init steps is used for general logging.
674 const float duration = timingInit + timingPropertyValidation + timingInputValidation + timingExec;
675 // need it to throw before trying to run fillhistory() on an algorithm
676 // which has failed
677 if (trackingHistory() && m_history) {
678 m_history->fillAlgorithmHistory(this, startTime, duration, Algorithm::g_execCount);
679 fillHistory();
681 }
682
683 // Put the output workspaces into the AnalysisDataService - if requested
685 this->store();
686
687 // just cache the value internally, it is set at the very end of this
688 // method
689 algIsExecuted = true;
690
691 // Log that execution has completed.
692 getLogger().debug("Time to validate properties: " + std::to_string(timingPropertyValidation) + " seconds\n" +
693 "Time for other input validation: " + std::to_string(timingInputValidation) + " seconds\n" +
694 "Time for other initialization: " + std::to_string(timingInit) + " seconds\n" +
695 "Time to run exec: " + std::to_string(timingExec) + " seconds\n");
696 reportCompleted(duration);
697 } catch (std::runtime_error &ex) {
698 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
699 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
701 this->unlockWorkspaces();
703 throw;
704 else {
705 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
706 getLogger().error() << "Error in execution of algorithm " << this->name() << '\n' << ex.what() << '\n';
707 }
708
709 } catch (std::logic_error &ex) {
710 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
711 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
712 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
714 this->unlockWorkspaces();
716 throw;
717 else {
718 getLogger().error() << "Logic Error in execution of algorithm " << this->name() << '\n' << ex.what() << '\n';
719 }
720 }
721 } catch (CancelException &ex) {
722 m_runningAsync = false;
723 getLogger().warning() << this->name() << ": Execution cancelled by user.\n";
724 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
725 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
727 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
728 this->unlockWorkspaces();
729
730 throw;
731 }
732 // Gaudi also specifically catches GaudiException & std:exception.
733 catch (std::exception &ex) {
734 m_runningAsync = false;
735 getLogger().error() << "Error in execution of algorithm " << this->name() << ":\n" << ex.what() << "\n";
736 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
737 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
739 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
740 this->unlockWorkspaces();
741
742 throw;
743 }
744
745 catch (H5::Exception &ex) {
746 m_runningAsync = false;
747 std::string errmsg;
748 errmsg.append(ex.getCFuncName()).append(": ").append(ex.getCDetailMsg());
749 getLogger().error() << "H5 Exception in execution of algorithm " << this->name() << ":\n" << errmsg << "\n";
750 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
751 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
753 notificationCenter().postNotification(new ErrorNotification(this, errmsg));
754 this->unlockWorkspaces();
755
756 throw;
757 }
758
759 catch (...) {
760 // Execution failed with an unknown exception object
761 m_runningAsync = false;
762
763 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
764 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
766 notificationCenter().postNotification(new ErrorNotification(this, "UNKNOWN Exception is caught in exec()"));
767 getLogger().error() << this->name() << ": UNKNOWN Exception is caught in exec()\n";
768 this->unlockWorkspaces();
769
770 throw;
771 }
772
773 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
774 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
775 if (algIsExecuted) {
777 }
778
779 // Only gets to here if algorithm ended normally
780 notificationCenter().postNotification(new FinishedNotification(this, isExecuted()));
781
782 // Unlock the workspaces once the notification has been sent, to prevent too early deletion
783 this->unlockWorkspaces();
784
785 return isExecuted();
786}
787
788//---------------------------------------------------------------------------------------------
794 bool executed = false;
795 try {
796 executed = execute();
797 } catch (std::runtime_error &) {
798 throw;
799 }
800
801 if (!executed) {
802 throw std::runtime_error("Unable to successfully run ChildAlgorithm " + this->name());
803 }
804}
805
806//---------------------------------------------------------------------------------------------
812 const std::vector<Property *> &props = getProperties();
813 std::vector<int> groupWsIndicies;
814
815 // add any regular/child workspaces first, then add the groups
816 for (unsigned int i = 0; i < props.size(); ++i) {
817 auto *wsProp = dynamic_cast<IWorkspaceProperty *>(props[i]);
818 if (wsProp) {
819 // check if the workspace is a group, if so remember where it is and add
820 // it later
821 auto group = std::dynamic_pointer_cast<WorkspaceGroup>(wsProp->getWorkspace());
822 if (!group) {
823 try {
824 wsProp->store();
825 } catch (std::runtime_error &) {
826 throw;
827 }
828 } else {
829 groupWsIndicies.emplace_back(i);
830 }
831 }
832 }
833
834 // now store workspace groups once their members have been added
835 std::vector<int>::const_iterator wsIndex;
836 for (wsIndex = groupWsIndicies.begin(); wsIndex != groupWsIndicies.end(); ++wsIndex) {
837 auto *wsProp = dynamic_cast<IWorkspaceProperty *>(props[*wsIndex]);
838 if (wsProp) {
839 try {
840 wsProp->store();
841 } catch (std::runtime_error &) {
842 throw;
843 }
844 }
845 }
846}
847
848//---------------------------------------------------------------------------------------------
866Algorithm_sptr Algorithm::createChildAlgorithm(const std::string &name, const double startProgress,
867 const double endProgress, const bool enableLogging, const int &version) {
868 Algorithm_sptr alg = AlgorithmManager::Instance().createUnmanaged(name, version);
869 setupAsChildAlgorithm(alg, startProgress, endProgress, enableLogging);
870 return alg;
871}
872
879void Algorithm::setupAsChildAlgorithm(const Algorithm_sptr &alg, const double startProgress, const double endProgress,
880 const bool enableLogging) {
881 // set as a child
882 alg->setChild(true);
883 alg->setLogging(enableLogging);
884
885 // Initialise the Child Algorithm
886 try {
887 alg->initialize();
888 } catch (std::runtime_error &) {
889 throw std::runtime_error("Unable to initialise Child Algorithm '" + alg->name() + "'");
890 }
891
892 // If output workspaces are nameless, give them a temporary name to satisfy
893 // validator
894 const std::vector<Property *> &props = alg->getProperties();
895 for (auto prop : props) {
896 const auto *wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
897 if (prop->direction() == Mantid::Kernel::Direction::Output && wsProp) {
898 if (prop->value().empty() && !wsProp->isOptional()) {
899 prop->createTemporaryValue();
900 }
901 }
902 }
903
904 if (startProgress >= 0.0 && endProgress > startProgress && endProgress <= 1.0) {
905 alg->addObserver(this->progressObserver());
906 m_startChildProgress = startProgress;
907 m_endChildProgress = endProgress;
908 }
909
910 // Before we return the shared pointer, use it to create a weak pointer and
911 // keep that in a vector.
912 // It will be used this to pass on cancellation requests
913 // It must be protected by a critical block so that Child Algorithms can run
914 // in parallel safely.
915 std::weak_ptr<IAlgorithm> weakPtr(alg);
916 PARALLEL_CRITICAL(Algorithm_StoreWeakPtr) { m_ChildAlgorithms.emplace_back(weakPtr); }
917}
918
919//=============================================================================================
920//================================== Algorithm History
921//========================================
922//=============================================================================================
923
929std::string Algorithm::toString() const { return Mantid::JsonHelpers::jsonToString(toJson()); }
930
935::Json::Value Algorithm::toJson() const {
936 ::Json::Value root;
937
938 root["name"] = name();
939 root["version"] = this->version();
940 root["properties"] = m_properties.asJson(false);
941
942 return root;
943}
944
945//--------------------------------------------------------------------------------------------
954 ::Json::Value root;
955 ::Json::Value jsonMap;
956
957 auto props = history.getProperties();
958 const size_t numProps(props.size());
959 for (size_t i = 0; i < numProps; ++i) {
960 PropertyHistory_sptr prop = props[i];
961 if (!prop->isDefault()) {
962 jsonMap[prop->name()] = prop->value();
963 }
964 }
965
966 root["name"] = history.name();
967 root["version"] = history.version();
968 root["properties"] = jsonMap;
969
970 const std::string output = Mantid::JsonHelpers::jsonToString(root);
971 IAlgorithm_sptr alg;
972
973 try {
974 alg = Algorithm::fromString(output);
975 } catch (std::invalid_argument &) {
976 throw std::runtime_error("Could not create algorithm from history. "
977 "Is this a child algorithm whose workspaces are not in the ADS?");
978 }
979 return alg;
980}
981
982//--------------------------------------------------------------------------------------------
991IAlgorithm_sptr Algorithm::fromString(const std::string &input) {
992 ::Json::Value root;
993 if (Mantid::JsonHelpers::parse(input, &root)) {
994 return fromJson(root);
995 } else {
996 throw std::runtime_error("Cannot create algorithm, invalid string format.");
997 }
998}
999
1007IAlgorithm_sptr Algorithm::fromJson(const Json::Value &serialized) {
1008 const std::string algName = serialized["name"].asString();
1009 const int versionNumber = serialized.get("version", -1).asInt();
1010 auto alg = AlgorithmManager::Instance().createUnmanaged(algName, versionNumber);
1011 alg->initialize();
1012 alg->setProperties(serialized["properties"]);
1013 return alg;
1014}
1015
1019 WorkspaceVector outputWorkspaces;
1020 if (!isChild()) {
1021 findWorkspaces(outputWorkspaces, Direction::Output);
1022 }
1023 fillHistory(outputWorkspaces);
1024}
1025
1036 return;
1037
1038 // iterate over the algorithms output workspaces
1039 const auto &algProperties = getProperties();
1040 for (const auto &prop : algProperties) {
1041 if (prop->direction() != Kernel::Direction::Output && prop->direction() != Kernel::Direction::InOut)
1042 continue;
1043 const auto *wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
1044 if (!wsProp)
1045 continue;
1046 // Check we actually have a workspace, it may have been optional
1048 if (!workspace)
1049 continue;
1050
1051 bool linked = false;
1052 // find child histories with anonymous output workspaces
1053 const auto &childHistories = m_history->getChildHistories();
1054 auto childIter = childHistories.rbegin();
1055 for (; childIter != childHistories.rend() && !linked; ++childIter) {
1056 const auto &props = (*childIter)->getProperties();
1057 auto propIter = props.begin();
1058 for (; propIter != props.end() && !linked; ++propIter) {
1059 // check we have a workspace property
1060 if ((*propIter)->direction() == Kernel::Direction::Output ||
1061 (*propIter)->direction() == Kernel::Direction::InOut) {
1062 // if the workspaces are equal, then rename the history
1063 std::ostringstream os;
1064 os << "__TMP" << wsProp->getWorkspace().get();
1065 if (os.str() == (*propIter)->value()) {
1066 (*propIter)->setValue(prop->value());
1067 linked = true;
1068 }
1069 }
1070 }
1071 }
1072 }
1073}
1074
1079void Algorithm::trackAlgorithmHistory(std::shared_ptr<AlgorithmHistory> parentHist) {
1081 m_parentHistory = std::move(parentHist);
1082}
1083
1088
1097void Algorithm::findWorkspaces(WorkspaceVector &workspaces, unsigned int direction, bool checkADS) const {
1098 auto workspaceFromWSProperty = [](const IWorkspaceProperty &prop, const AnalysisDataServiceImpl &ads,
1099 const std::string &strValue, bool checkADS) {
1100 auto workspace = prop.getWorkspace();
1101 if (workspace)
1102 return workspace;
1103
1104 // Empty string indicates optional workspace
1105 if (checkADS && !strValue.empty()) {
1106 return ads.retrieve(strValue);
1107 }
1108 return Workspace_sptr();
1109 };
1110 auto appendWS = [&workspaces](const Workspace_sptr &workspace) {
1111 if (!workspace)
1112 return false;
1113 workspaces.emplace_back(workspace);
1114 return true;
1115 };
1116
1117 // Additional output properties can be declared on the fly
1118 // so we need a fresh loop over the properties
1119 const auto &algProperties = getProperties();
1120 const auto &ads = AnalysisDataService::Instance();
1121 for (const auto &prop : algProperties) {
1122 const unsigned int propDirection = prop->direction();
1123 if (propDirection != direction && propDirection != Direction::InOut)
1124 continue;
1125 if (const auto wsProp = dynamic_cast<IWorkspaceProperty *>(prop)) {
1126 appendWS(workspaceFromWSProperty(*wsProp, ads, prop->value(), checkADS));
1127 }
1128 }
1129}
1130
1133 auto &logger = getLogger();
1134
1136 logger.notice() << name() << " started";
1137 if (this->isChild())
1138 logger.notice() << " (child)";
1139 logger.notice() << '\n';
1140 // Make use of the AlgorithmHistory class, which holds all the info we
1141 // want here
1142 AlgorithmHistory algHistory(this);
1143 size_t maxPropertyLength = 40;
1144 if (logger.is(Logger::Priority::PRIO_DEBUG)) {
1145 // include the full property value when logging in debug
1146 maxPropertyLength = 0;
1147 }
1148 algHistory.printSelf(logger.information(), 0, maxPropertyLength);
1149 }
1150}
1151
1152//=============================================================================================
1153//================================== WorkspaceGroup-related
1154//===================================
1155//=============================================================================================
1156
1179 size_t numGroups = 0;
1180 bool doProcessGroups = false;
1181
1182 // Unroll the groups or single inputs into vectors of workspaces
1183 const auto &ads = AnalysisDataService::Instance();
1185 m_groupWorkspaces.clear();
1186 for (auto inputWorkspaceProp : m_inputWorkspaceProps) {
1187 auto const prop = dynamic_cast<Property *>(inputWorkspaceProp);
1188 auto wsGroupProp = dynamic_cast<WorkspaceProperty<WorkspaceGroup> const *>(prop);
1189 auto ws = inputWorkspaceProp->getWorkspace();
1190 auto wsGroup = std::dynamic_pointer_cast<WorkspaceGroup>(ws);
1191
1192 // Workspace groups are NOT returned by IWP->getWorkspace() most of the
1193 // time because WorkspaceProperty is templated by <MatrixWorkspace> and
1194 // WorkspaceGroup does not subclass <MatrixWorkspace>
1195 if (!wsGroup && prop && !prop->value().empty()) {
1196 // So try to use the name in the AnalysisDataService
1197 try {
1198 wsGroup = ads.retrieveWS<WorkspaceGroup>(prop->value());
1199 } catch (Exception::NotFoundError &) { /* Do nothing */
1200 }
1201 }
1202
1203 // Found the group either directly or by name?
1204 // If the property is of type WorkspaceGroup then don't unroll
1205 if (wsGroup && !wsGroupProp) {
1206 numGroups++;
1207 doProcessGroups = true;
1208 m_unrolledInputWorkspaces.emplace_back(wsGroup->getAllItems());
1209 } else {
1210 // Single Workspace. Treat it as a "group" with only one member
1211 if (ws)
1213 else
1215 }
1216
1217 // Add to the list of groups
1218 m_groupWorkspaces.emplace_back(wsGroup);
1219 }
1220
1221 // No groups? Get out.
1222 if (numGroups == 0)
1223 return doProcessGroups;
1224
1225 // ---- Confirm that all the groups are the same size -----
1226 // Index of the single group
1227 m_singleGroup = -1;
1228 // Size of the single or of all the groups
1229 m_groupSize = 1;
1231 for (size_t i = 0; i < m_unrolledInputWorkspaces.size(); i++) {
1232 const auto &thisGroup = m_unrolledInputWorkspaces[i];
1233 // We're ok with empty groups if the workspace property is optional
1234 if (thisGroup.empty() && !m_inputWorkspaceProps[i]->isOptional())
1235 throw std::invalid_argument("Empty group passed as input");
1236 if (!thisGroup.empty()) {
1237 // Record the index of the single group.
1239 if (wsGroup && (numGroups == 1))
1240 m_singleGroup = int(i);
1241
1242 // For actual groups (>1 members)
1243 if (thisGroup.size() > 1) {
1244 // Check for matching group size
1245 if (m_groupSize > 1)
1246 if (thisGroup.size() != m_groupSize)
1247 throw std::invalid_argument("Input WorkspaceGroups are not of the same size.");
1248
1249 // Are ALL the names similar?
1250 if (wsGroup)
1252
1253 // Save the size for the next group
1254 m_groupSize = thisGroup.size();
1255 }
1256 }
1257 } // end for each group
1258
1259 // If you get here, then the groups are compatible
1260 return doProcessGroups;
1261}
1262
1271bool Algorithm::doCallProcessGroups(Mantid::Types::Core::DateAndTime &startTime) {
1272 // In the base implementation of processGroups, this normally calls
1273 // this->execute() again on each member of the group. Other algorithms may
1274 // choose to override that behavior (examples: CompareWorkspaces,
1275 // RenameWorkspace)
1276
1277 startTime = Mantid::Types::Core::DateAndTime::getCurrentTime();
1278 // Start a timer
1279 Timer timer;
1280 bool completed = false;
1281 try {
1282 // Call the concrete algorithm's processGroups method
1283 completed = processGroups();
1284 } catch (std::exception &ex) {
1285 // The child algorithm will already have logged the error etc.,
1286 // but we also need to update flags in the parent algorithm and
1287 // send an ErrorNotification (because the child isn't registered with the
1288 // AlgorithmMonitor).
1290 m_runningAsync = false;
1291 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
1292 throw;
1293 } catch (...) {
1295 m_runningAsync = false;
1296 notificationCenter().postNotification(new ErrorNotification(this, "UNKNOWN Exception caught from processGroups"));
1297 throw;
1298 }
1299
1300 // Check for a cancellation request in case the concrete algorithm doesn't
1302
1303 if (completed) {
1304 // Get how long this algorithm took to run
1305 const float duration = timer.elapsed();
1306
1307 if (trackingHistory()) {
1309 m_history->fillAlgorithmHistory(this, startTime, duration, g_execCount);
1310 } else {
1311 m_history = std::make_shared<AlgorithmHistory>(this, startTime, duration, ++g_execCount);
1312 }
1313 // find any further outputs created by the execution
1314 WorkspaceVector outputWorkspaces;
1315 const bool checkADS{true};
1316 findWorkspaces(outputWorkspaces, Direction::Output, checkADS);
1317 fillHistory(outputWorkspaces);
1320 }
1321 }
1322
1323 // in the base processGroups each individual exec stores its outputs
1325 this->store();
1326
1327 // Log that execution has completed.
1328 reportCompleted(duration, true /* this is for group processing*/);
1330 } else {
1332 }
1333
1334 notificationCenter().postNotification(new FinishedNotification(this, isExecuted()));
1335
1336 return completed;
1337}
1338
1346void Algorithm::fillHistory(const std::vector<Workspace_sptr> &outputWorkspaces) {
1347 // this is not a child algorithm. Add the history algorithm to the
1348 // WorkspaceHistory object.
1349 if (!isChild()) {
1350 auto copyHistoryToGroup = [](const Workspace &in, WorkspaceGroup &out) {
1351 for (auto &outGroupItem : out) {
1352 outGroupItem->history().addHistory(in.getHistory());
1353 }
1354 };
1355
1356 for (auto &outWS : outputWorkspaces) {
1357 auto outWSGroup = std::dynamic_pointer_cast<WorkspaceGroup>(outWS);
1358 // Copy the history from the cached input workspaces to the output ones
1359 for (const auto &inputWS : m_inputWorkspaceHistories) {
1360 if (outWSGroup) {
1361 copyHistoryToGroup(*inputWS, *outWSGroup);
1362 } else {
1363 outWS->history().addHistory(inputWS->getHistory());
1364 }
1365 }
1366 // Add history for this operation
1367 if (outWSGroup) {
1368 for (auto &outGroupItem : *outWSGroup) {
1369 outGroupItem->history().addHistory(m_history);
1370 }
1371 } else {
1372 // Add the history for the current algorithm to all the output
1373 // workspaces
1374 outWS->history().addHistory(m_history);
1375 }
1376 }
1377 }
1378 // this is a child algorithm, but we still want to keep the history.
1380 m_parentHistory->addChildHistory(m_history);
1381 }
1382}
1383
1384//--------------------------------------------------------------------------------------------
1398
1399 std::vector<WorkspaceGroup_sptr> outGroups;
1400
1401 // ---------- Create all the output workspaces ----------------------------
1402 for (auto &pureOutputWorkspaceProp : m_pureOutputWorkspaceProps) {
1403 auto *prop = dynamic_cast<Property *>(pureOutputWorkspaceProp);
1404 if (prop && !prop->value().empty()) {
1405 auto outWSGrp = std::make_shared<WorkspaceGroup>();
1406 outGroups.emplace_back(outWSGrp);
1407 // Put the GROUP in the ADS
1408 AnalysisDataService::Instance().addOrReplace(prop->value(), outWSGrp);
1409 if (auto workspaceProperty = dynamic_cast<WorkspaceProperty<Workspace> *>(pureOutputWorkspaceProp)) {
1410 Workspace_sptr outputWorkspace = outWSGrp;
1411 *workspaceProperty = outputWorkspace;
1412 }
1413 outWSGrp->observeADSNotifications(false);
1414 }
1415 }
1416
1417 double progress_proportion = 1.0 / static_cast<double>(m_groupSize);
1418 // Go through each entry in the input group(s)
1419 for (size_t entry = 0; entry < m_groupSize; entry++) {
1420 // use create Child Algorithm that look like this one
1421 Algorithm_sptr alg_sptr = this->createChildAlgorithm(this->name(), progress_proportion * static_cast<double>(entry),
1422 progress_proportion * (1 + static_cast<double>(entry)),
1423 this->isLogging(), this->version());
1424 // Make a child algorithm and turn off history recording for it, but always
1425 // store result in the ADS
1426 alg_sptr->setChild(true);
1427 alg_sptr->setAlwaysStoreInADS(true);
1428 alg_sptr->enableHistoryRecordingForChild(false);
1429 alg_sptr->setRethrows(true);
1430
1431 Algorithm *alg = alg_sptr.get();
1432 // Set all non-workspace properties
1433 this->copyNonWorkspaceProperties(alg, int(entry) + 1);
1434
1435 std::string outputBaseName;
1436
1437 // ---------- Set all the input workspaces ----------------------------
1438 for (size_t iwp = 0; iwp < m_unrolledInputWorkspaces.size(); iwp++) {
1439 const std::vector<Workspace_sptr> &thisGroup = m_unrolledInputWorkspaces[iwp];
1440 if (!thisGroup.empty()) {
1441 // By default (for a single group) point to the first/only workspace
1442 Workspace_sptr ws = thisGroup[0];
1443
1444 if ((m_singleGroup == int(iwp)) || m_singleGroup < 0) {
1445 // Either: this is the single group
1446 // OR: all inputs are groups
1447 // ... so get then entry^th workspace in this group
1448 if (entry < thisGroup.size()) {
1449 ws = thisGroup[entry];
1450 } else {
1451 // This can happen when one has more than one input group
1452 // workspaces, having different sizes. For example one workspace
1453 // group is the corrections which has N parts (e.g. weights for
1454 // polarized measurement) while the other one is the actual input
1455 // workspace group, where each item needs to be corrected together
1456 // with all N inputs of the second group. In this case processGroup
1457 // needs to be overridden, which is currently not possible in
1458 // python.
1459 throw std::runtime_error("Unable to process over groups; consider passing workspaces "
1460 "one-by-one or override processGroup method of the algorithm.");
1461 }
1462 }
1463 // Append the names together
1464 if (!outputBaseName.empty())
1465 outputBaseName += "_";
1466 outputBaseName += ws->getName();
1467
1468 // Set the property using the name of that workspace
1469 if (auto *prop = dynamic_cast<Property *>(m_inputWorkspaceProps[iwp])) {
1470 if (ws->getName().empty()) {
1471 alg->setProperty(prop->name(), ws);
1472 } else {
1473 alg->setPropertyValue(prop->name(), ws->getName());
1474 }
1475 } else {
1476 throw std::logic_error("Found a Workspace property which doesn't "
1477 "inherit from Property.");
1478 }
1479 } // not an empty (i.e. optional) input
1480 } // for each InputWorkspace property
1481
1482 std::vector<std::string> outputWSNames(m_pureOutputWorkspaceProps.size());
1483 // ---------- Set all the output workspaces ----------------------------
1484 for (size_t owp = 0; owp < m_pureOutputWorkspaceProps.size(); owp++) {
1485 if (auto *prop = dynamic_cast<Property *>(m_pureOutputWorkspaceProps[owp])) {
1486 // Default name = "in1_in2_out"
1487 const std::string inName = prop->value();
1488 if (inName.empty())
1489 continue;
1490 std::string outName;
1492 outName.append(inName).append("_").append(Strings::toString(entry + 1));
1493 } else {
1494 outName.append(outputBaseName).append("_").append(inName);
1495 }
1496
1497 auto inputProp =
1498 std::find_if(m_inputWorkspaceProps.begin(), m_inputWorkspaceProps.end(), WorkspacePropertyValueIs(inName));
1499
1500 // Overwrite workspaces in any input property if they have the same
1501 // name as an output (i.e. copy name button in algorithm dialog used)
1502 // (only need to do this for a single input, multiple will be handled
1503 // by ADS)
1504 if (inputProp != m_inputWorkspaceProps.end()) {
1505 const auto &inputGroup = m_unrolledInputWorkspaces[inputProp - m_inputWorkspaceProps.begin()];
1506 if (!inputGroup.empty())
1507 outName = inputGroup[entry]->getName();
1508 }
1509 // Except if all inputs had similar names, then the name is "out_1"
1510
1511 // Set in the output
1512 alg->setPropertyValue(prop->name(), outName);
1513
1514 outputWSNames[owp] = outName;
1515 } else {
1516 throw std::logic_error("Found a Workspace property which doesn't "
1517 "inherit from Property.");
1518 }
1519 } // for each OutputWorkspace property
1520
1521 // ------------ Execute the algo --------------
1522 try {
1523 alg->execute();
1524 } catch (std::exception &e) {
1525 std::ostringstream msg;
1526 msg << "Execution of " << this->name() << " for group entry " << (entry + 1) << " failed: ";
1527 msg << e.what(); // Add original message
1528 throw std::runtime_error(msg.str());
1529 }
1530
1531 // ------------ Fill in the output workspace group ------------------
1532 // this has to be done after execute() because a workspace must exist
1533 // when it is added to a group
1534 for (size_t owp = 0; owp < m_pureOutputWorkspaceProps.size(); owp++) {
1535 auto *prop = dynamic_cast<Property *>(m_pureOutputWorkspaceProps[owp]);
1536 if (prop && prop->value().empty())
1537 continue;
1538 // And add it to the output group
1539 outGroups[owp]->add(outputWSNames[owp]);
1540 }
1541
1542 } // for each entry in each group
1543
1544 // restore group notifications
1545 for (auto &outGroup : outGroups) {
1546 outGroup->observeADSNotifications(true);
1547 }
1548
1549 return true;
1550}
1551
1552//--------------------------------------------------------------------------------------------
1559 if (!alg)
1560 throw std::runtime_error("Algorithm not created!");
1561 const auto &props = this->getProperties();
1562 for (const auto &prop : props) {
1563 if (prop) {
1564
1565 const auto *wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
1566 // Copy the property using the string
1567 if (!wsProp)
1568 this->setOtherProperties(alg, prop->name(), prop->value(), periodNum);
1569 }
1570 }
1571}
1572
1573//--------------------------------------------------------------------------------------------
1582void Algorithm::setOtherProperties(IAlgorithm *alg, const std::string &propertyName, const std::string &propertyValue,
1583 int periodNum) {
1584 (void)periodNum; // Avoid compiler warning
1585 if (alg)
1586 alg->setPropertyValue(propertyName, propertyValue);
1587}
1588
1589//--------------------------------------------------------------------------------------------
1595 if (!prop) {
1596 return false;
1597 }
1598 const auto *const wsProp = dynamic_cast<const IWorkspaceProperty *>(prop);
1599 return (wsProp != nullptr);
1600}
1601
1602//=============================================================================================
1603//================================== Asynchronous Execution
1604//===================================
1605//=============================================================================================
1606namespace {
1610struct AsyncFlagHolder {
1614 explicit AsyncFlagHolder(bool &running_flag) : m_running_flag(running_flag) { m_running_flag = true; }
1616 ~AsyncFlagHolder() { m_running_flag = false; }
1617
1618private:
1620 AsyncFlagHolder() = delete;
1623};
1624} // namespace
1625
1626//--------------------------------------------------------------------------------------------
1632 std::make_unique<Poco::ActiveMethod<bool, Poco::Void, Algorithm>>(this, &Algorithm::executeAsyncImpl);
1633 return (*m_executeAsync)(Poco::Void());
1634}
1635
1640bool Algorithm::executeAsyncImpl(const Poco::Void & /*unused*/) {
1641 AsyncFlagHolder running(m_runningAsync);
1642 return this->execute();
1643}
1644
1649Poco::NotificationCenter &Algorithm::notificationCenter() const {
1651 m_notificationCenter = std::make_unique<Poco::NotificationCenter>();
1652 return *m_notificationCenter;
1653}
1654
1658void Algorithm::handleChildProgressNotification(const Poco::AutoPtr<ProgressNotification> &pNf) {
1659 double p = m_startChildProgress + (m_endChildProgress - m_startChildProgress) * pNf->progress;
1660
1661 progress(p, pNf->message);
1662}
1663
1667const Poco::AbstractObserver &Algorithm::progressObserver() const {
1668 if (!m_progressObserver)
1669 m_progressObserver = std::make_unique<Poco::NObserver<Algorithm, ProgressNotification>>(
1671
1672 return *m_progressObserver;
1673}
1674
1675//--------------------------------------------------------------------------------------------
1680 // set myself to be cancelled
1681 m_cancel = true;
1682
1683 // Loop over the output workspaces and try to cancel them
1684 for (auto &weakPtr : m_ChildAlgorithms) {
1685 if (IAlgorithm_sptr sharedPtr = weakPtr.lock()) {
1686 sharedPtr->cancel();
1687 }
1688 }
1689}
1690
1692bool Algorithm::getCancel() const { return m_cancel; }
1693
1699bool Algorithm::isLogging() const { return g_log.getEnabled(); }
1700
1701/* Sets the logging priority offset. Values are subtracted from the log level.
1702 *
1703 * Example value=1 will turn warning into notice
1704 * Example value=-1 will turn notice into warning
1705 */
1707
1710
1711//--------------------------------------------------------------------------------------------
1716 // only throw exceptions if the code is not multi threaded otherwise you
1717 // contravene the OpenMP standard
1718 // that defines that all loops must complete, and no exception can leave an
1719 // OpenMP section
1720 // openmp cancel handling is performed using the ??, ?? and ?? macros in
1721 // each algrothim
1723 if (m_cancel)
1724 throw CancelException();
1725}
1726
1732void Algorithm::reportCompleted(const double &duration, const bool groupProcessing) {
1733 std::string optionalMessage;
1734 if (groupProcessing) {
1735 optionalMessage = ". Processed as a workspace group";
1736 }
1737
1740
1741 std::stringstream msg;
1742 msg << name() << " successful, Duration ";
1743 double seconds = duration;
1744 if (seconds > 60.) {
1745 auto minutes = static_cast<int>(seconds / 60.);
1746 msg << minutes << " minutes ";
1747 seconds = seconds - static_cast<double>(minutes) * 60.;
1748 }
1749 msg << std::fixed << std::setprecision(2) << seconds << " seconds" << optionalMessage;
1750 getLogger().notice(msg.str());
1751 }
1752 }
1753
1754 else {
1755 getLogger().debug() << name() << " finished with isChild = " << isChild() << '\n';
1756 }
1758}
1759
1763 if (UsageService::Instance().isEnabled()) {
1764 std::ostringstream oss;
1765 oss << this->name() << ".v" << this->version();
1766 UsageService::Instance().registerFeatureUsage(FeatureType::Algorithm, oss.str(), isChild());
1767 }
1768}
1769
1774
1779
1780bool Algorithm::isCompoundProperty(const std::string &name) const {
1781 return std::find(m_reservedList.cbegin(), m_reservedList.cend(), name) != m_reservedList.cend();
1782}
1783
1784//---------------------------------------------------------------------------
1785// Algorithm's inner classes
1786//---------------------------------------------------------------------------
1787
1789 : Poco::Notification(), m_algorithm(alg) {}
1790
1791const IAlgorithm *Algorithm::AlgorithmNotification::algorithm() const { return m_algorithm; }
1792
1794std::string Algorithm::StartedNotification::name() const { return "StartedNotification"; }
1795
1797 : AlgorithmNotification(alg), success(res) {}
1798std::string Algorithm::FinishedNotification::name() const { return "FinishedNotification"; }
1799
1800Algorithm::ProgressNotification::ProgressNotification(const Algorithm *const alg, double p, std::string msg,
1801 double estimatedTime, int progressPrecision)
1802 : AlgorithmNotification(alg), progress(p), message(std::move(msg)), estimatedTime(estimatedTime),
1803 progressPrecision(progressPrecision) {}
1804
1805std::string Algorithm::ProgressNotification::name() const { return "ProgressNotification"; }
1806
1808 : AlgorithmNotification(alg), what(std::move(str)) {}
1809
1810std::string Algorithm::ErrorNotification::name() const { return "ErrorNotification"; }
1811
1812const char *Algorithm::CancelException::what() const noexcept { return "Algorithm terminated"; }
1813
1820void Algorithm::declareProperty(std::unique_ptr<Property> p, const std::string &doc) {
1821 m_properties.declareProperty(std::move(p), doc);
1822}
1823
1828void Algorithm::declareOrReplaceProperty(std::unique_ptr<Property> p, const std::string &doc) {
1829 m_properties.declareOrReplaceProperty(std::move(p), doc);
1830}
1831
1835
1847void Algorithm::setProperties(const std::string &propertiesJson,
1848 const std::unordered_set<std::string> &ignoreProperties, bool createMissing) {
1849 m_properties.setProperties(propertiesJson, ignoreProperties, createMissing);
1850}
1851
1858void Algorithm::setProperties(const ::Json::Value &jsonValue, const std::unordered_set<std::string> &ignoreProperties,
1859 bool createMissing) {
1860 m_properties.setProperties(jsonValue, ignoreProperties, createMissing);
1861}
1862
1869void Algorithm::setPropertiesWithString(const std::string &propertiesString,
1870 const std::unordered_set<std::string> &ignoreProperties) {
1871 m_properties.setPropertiesWithString(propertiesString, ignoreProperties);
1872}
1873
1882void Algorithm::setPropertyValue(const std::string &name, const std::string &value) {
1884 this->afterPropertySet(name);
1885}
1886
1894void Algorithm::setPropertyValueFromJson(const std::string &name, const Json::Value &value) {
1896 this->afterPropertySet(name);
1897}
1898
1909
1915bool Algorithm::existsProperty(const std::string &name) const { return m_properties.existsProperty(name); }
1916
1921
1927
1933std::string Algorithm::getPropertyValue(const std::string &name) const { return m_properties.getPropertyValue(name); }
1934
1943
1952
1957const std::vector<Property *> &Algorithm::getProperties() const { return m_properties.getProperties(); }
1958
1963std::vector<std::string> Algorithm::getDeclaredPropertyNames() const noexcept {
1965}
1966
1986
1991bool Algorithm::isDefault(const std::string &name) const {
1993}
1994
2002std::string Algorithm::asString(bool withDefaultValues) const { return m_properties.asString(withDefaultValues); }
2009::Json::Value Algorithm::asJson(bool withDefaultValues) const { return m_properties.asJson(withDefaultValues); }
2010
2016void Algorithm::removeProperty(const std::string &name, const bool delproperty) {
2017 m_properties.removeProperty(name, delproperty);
2018}
2019
2025std::unique_ptr<Kernel::Property> Algorithm::takeProperty(const size_t index) {
2027}
2028
2033
2041
2042} // namespace API
2043
2044//---------------------------------------------------------------------------
2045// Specialized templated PropertyManager getValue definitions for Algorithm
2046// types
2047//---------------------------------------------------------------------------
2048namespace Kernel {
2054template <>
2055MANTID_API_DLL API::IAlgorithm_sptr IPropertyManager::getValue<API::IAlgorithm_sptr>(const std::string &name) const {
2056 auto *prop = dynamic_cast<PropertyWithValue<API::IAlgorithm_sptr> *>(getPointerToProperty(name));
2057 if (prop) {
2058 return *prop;
2059 } else {
2060 std::string message = "Attempt to assign property " + name + " to incorrect type. Expected shared_ptr<IAlgorithm>";
2061 throw std::runtime_error(message);
2062 }
2063}
2064
2071template <>
2073IPropertyManager::getValue<API::IAlgorithm_const_sptr>(const std::string &name) const {
2074 const auto *prop = dynamic_cast<PropertyWithValue<API::IAlgorithm_sptr> *>(getPointerToProperty(name));
2075 if (prop) {
2076 return prop->operator()();
2077 } else {
2078 std::string message =
2079 "Attempt to assign property " + name + " to incorrect type. Expected const shared_ptr<IAlgorithm>";
2080 throw std::runtime_error(message);
2081 }
2082}
2083
2084} // namespace Kernel
2085
2086} // namespace Mantid
const std::string & m_value
Definition Algorithm.cpp:72
bool & m_running_flag
Running flag.
T m_onfinsh
Definition Algorithm.cpp:80
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.