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_checkForStringArrayWorkspaceOutputs(false),
117 m_alwaysStoreInADS(true), m_runningAsync(false), m_rethrow(false), m_isAlgStartupLoggingEnabled(true),
118 m_startChildProgress(0.), m_endChildProgress(0.), m_algorithmID(this), m_singleGroup(-1),
119 m_groupsHaveSimilarNames(false), m_inputWorkspaceHistories(), 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 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 getLogger().warning() << this->name() << ": Execution cancelled by user.\n";
722 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
723 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
725 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
726 this->unlockWorkspaces();
727
728 throw;
729 }
730 // Gaudi also specifically catches GaudiException & std:exception.
731 catch (std::exception &ex) {
732 getLogger().error() << "Error in execution of algorithm " << this->name() << ":\n" << ex.what() << "\n";
733 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
734 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
736 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
737 this->unlockWorkspaces();
738
739 throw;
740 }
741
742 catch (H5::Exception &ex) {
743 std::string errmsg;
744 errmsg.append(ex.getCFuncName()).append(": ").append(ex.getCDetailMsg());
745 getLogger().error() << "H5 Exception in execution of algorithm " << this->name() << ":\n" << errmsg << "\n";
746 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
747 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
749 notificationCenter().postNotification(new ErrorNotification(this, errmsg));
750 this->unlockWorkspaces();
751
752 throw;
753 }
754
755 catch (...) {
756 // Execution failed with an unknown exception object
757 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
758 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
760 notificationCenter().postNotification(new ErrorNotification(this, "UNKNOWN Exception is caught in exec()"));
761 getLogger().error() << this->name() << ": UNKNOWN Exception is caught in exec()\n";
762 this->unlockWorkspaces();
763
764 throw;
765 }
766
767 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
768 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
769 if (algIsExecuted) {
771 }
772
773 // Only gets to here if algorithm ended normally
774 notificationCenter().postNotification(new FinishedNotification(this, isExecuted()));
775
776 // Unlock the workspaces once the notification has been sent, to prevent too early deletion
777 this->unlockWorkspaces();
778
779 return isExecuted();
780}
781
782//---------------------------------------------------------------------------------------------
788 bool executed = false;
789 try {
790 executed = execute();
791 } catch (std::runtime_error &) {
792 throw;
793 }
794
795 if (!executed) {
796 throw std::runtime_error("Unable to successfully run ChildAlgorithm " + this->name());
797 }
798}
799
800//---------------------------------------------------------------------------------------------
806 const std::vector<Property *> &props = getProperties();
807 std::vector<int> groupWsIndicies;
808
809 // add any regular/child workspaces first, then add the groups
810 for (unsigned int i = 0; i < props.size(); ++i) {
811 auto *wsProp = dynamic_cast<IWorkspaceProperty *>(props[i]);
812 if (wsProp) {
813 // check if the workspace is a group, if so remember where it is and add
814 // it later
815 auto group = std::dynamic_pointer_cast<WorkspaceGroup>(wsProp->getWorkspace());
816 if (!group) {
817 try {
818 wsProp->store();
819 } catch (std::runtime_error &) {
820 throw;
821 }
822 } else {
823 groupWsIndicies.emplace_back(i);
824 }
825 }
826 }
827
828 // now store workspace groups once their members have been added
829 std::vector<int>::const_iterator wsIndex;
830 for (wsIndex = groupWsIndicies.begin(); wsIndex != groupWsIndicies.end(); ++wsIndex) {
831 auto *wsProp = dynamic_cast<IWorkspaceProperty *>(props[*wsIndex]);
832 if (wsProp) {
833 try {
834 wsProp->store();
835 } catch (std::runtime_error &) {
836 throw;
837 }
838 }
839 }
840}
841
842//---------------------------------------------------------------------------------------------
860Algorithm_sptr Algorithm::createChildAlgorithm(const std::string &name, const double startProgress,
861 const double endProgress, const bool enableLogging, const int &version) {
862 Algorithm_sptr alg = AlgorithmManager::Instance().createUnmanaged(name, version);
863 setupAsChildAlgorithm(alg, startProgress, endProgress, enableLogging);
864 return alg;
865}
866
873void Algorithm::setupAsChildAlgorithm(const Algorithm_sptr &alg, const double startProgress, const double endProgress,
874 const bool enableLogging) {
875 // set as a child
876 alg->setChild(true);
877 alg->setLogging(enableLogging);
878
879 // Initialise the Child Algorithm
880 try {
881 alg->initialize();
882 } catch (std::runtime_error &) {
883 throw std::runtime_error("Unable to initialise Child Algorithm '" + alg->name() + "'");
884 }
885
886 // If output workspaces are nameless, give them a temporary name to satisfy
887 // validator
888 const std::vector<Property *> &props = alg->getProperties();
889 for (auto prop : props) {
890 const auto *wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
891 if (prop->direction() == Mantid::Kernel::Direction::Output && wsProp) {
892 if (prop->value().empty() && !wsProp->isOptional()) {
893 prop->createTemporaryValue();
894 }
895 }
896 }
897
898 if (startProgress >= 0.0 && endProgress > startProgress && endProgress <= 1.0) {
899 alg->addObserver(this->progressObserver());
900 m_startChildProgress = startProgress;
901 m_endChildProgress = endProgress;
902 }
903
904 // Before we return the shared pointer, use it to create a weak pointer and
905 // keep that in a vector.
906 // It will be used this to pass on cancellation requests
907 // It must be protected by a critical block so that Child Algorithms can run
908 // in parallel safely.
909 std::weak_ptr<IAlgorithm> weakPtr(alg);
910 PARALLEL_CRITICAL(Algorithm_StoreWeakPtr) { m_ChildAlgorithms.emplace_back(weakPtr); }
911}
912
913//=============================================================================================
914//================================== Algorithm History
915//========================================
916//=============================================================================================
917
923std::string Algorithm::toString() const { return Mantid::JsonHelpers::jsonToString(toJson()); }
924
929::Json::Value Algorithm::toJson() const {
930 ::Json::Value root;
931
932 root["name"] = name();
933 root["version"] = this->version();
934 root["properties"] = m_properties.asJson(false);
935
936 return root;
937}
938
939//--------------------------------------------------------------------------------------------
948 ::Json::Value root;
949 ::Json::Value jsonMap;
950
951 auto props = history.getProperties();
952 const size_t numProps(props.size());
953 for (size_t i = 0; i < numProps; ++i) {
954 PropertyHistory_sptr prop = props[i];
955 if (!prop->isDefault()) {
956 jsonMap[prop->name()] = prop->value();
957 }
958 }
959
960 root["name"] = history.name();
961 root["version"] = history.version();
962 root["properties"] = jsonMap;
963
964 const std::string output = Mantid::JsonHelpers::jsonToString(root);
965 IAlgorithm_sptr alg;
966
967 try {
968 alg = Algorithm::fromString(output);
969 } catch (std::invalid_argument &) {
970 throw std::runtime_error("Could not create algorithm from history. "
971 "Is this a child algorithm whose workspaces are not in the ADS?");
972 }
973 return alg;
974}
975
976//--------------------------------------------------------------------------------------------
985IAlgorithm_sptr Algorithm::fromString(const std::string &input) {
986 ::Json::Value root;
987 if (Mantid::JsonHelpers::parse(input, &root)) {
988 return fromJson(root);
989 } else {
990 throw std::runtime_error("Cannot create algorithm, invalid string format.");
991 }
992}
993
1001IAlgorithm_sptr Algorithm::fromJson(const Json::Value &serialized) {
1002 const std::string algName = serialized["name"].asString();
1003 const int versionNumber = serialized.get("version", -1).asInt();
1004 auto alg = AlgorithmManager::Instance().createUnmanaged(algName, versionNumber);
1005 alg->initialize();
1006 alg->setProperties(serialized["properties"]);
1007 return alg;
1008}
1009
1013 WorkspaceVector outputWorkspaces;
1014 if (!isChild()) {
1015 findWorkspaces(outputWorkspaces, Direction::Output);
1016 }
1017 fillHistory(outputWorkspaces);
1018}
1019
1030 return;
1031
1032 // iterate over the algorithms output workspaces
1033 const auto &algProperties = getProperties();
1034 for (const auto &prop : algProperties) {
1035 if (prop->direction() != Kernel::Direction::Output && prop->direction() != Kernel::Direction::InOut)
1036 continue;
1037 const auto *wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
1038 if (!wsProp)
1039 continue;
1040 // Check we actually have a workspace, it may have been optional
1042 if (!workspace)
1043 continue;
1044
1045 bool linked = false;
1046 // find child histories with anonymous output workspaces
1047 const auto &childHistories = m_history->getChildHistories();
1048 auto childIter = childHistories.rbegin();
1049 for (; childIter != childHistories.rend() && !linked; ++childIter) {
1050 const auto &props = (*childIter)->getProperties();
1051 auto propIter = props.begin();
1052 for (; propIter != props.end() && !linked; ++propIter) {
1053 // check we have a workspace property
1054 if ((*propIter)->direction() == Kernel::Direction::Output ||
1055 (*propIter)->direction() == Kernel::Direction::InOut) {
1056 // if the workspaces are equal, then rename the history
1057 std::ostringstream os;
1058 os << "__TMP" << wsProp->getWorkspace().get();
1059 if (os.str() == (*propIter)->value()) {
1060 (*propIter)->setValue(prop->value());
1061 linked = true;
1062 }
1063 }
1064 }
1065 }
1066 }
1067}
1068
1073void Algorithm::trackAlgorithmHistory(std::shared_ptr<AlgorithmHistory> parentHist) {
1075 m_parentHistory = std::move(parentHist);
1076}
1077
1082
1091void Algorithm::findWorkspaces(WorkspaceVector &workspaces, unsigned int direction, bool checkADS) const {
1092 auto workspaceFromWSProperty = [](const IWorkspaceProperty &prop, const AnalysisDataServiceImpl &ads,
1093 const std::string &strValue, bool checkADS) {
1094 auto workspace = prop.getWorkspace();
1095 if (workspace)
1096 return workspace;
1097
1098 // Empty string indicates optional workspace
1099 if (checkADS && !strValue.empty()) {
1100 return ads.retrieve(strValue);
1101 }
1102 return Workspace_sptr();
1103 };
1104 auto appendWS = [&workspaces](const Workspace_sptr &workspace) {
1105 if (!workspace)
1106 return false;
1107 workspaces.emplace_back(workspace);
1108 return true;
1109 };
1110
1111 // Additional output properties can be declared on the fly
1112 // so we need a fresh loop over the properties
1113 const auto &algProperties = getProperties();
1114 const auto &ads = AnalysisDataService::Instance();
1115 for (const auto &prop : algProperties) {
1116 const unsigned int propDirection = prop->direction();
1117 if (propDirection != direction && propDirection != Direction::InOut)
1118 continue;
1119 if (const auto wsProp = dynamic_cast<IWorkspaceProperty *>(prop)) {
1120 appendWS(workspaceFromWSProperty(*wsProp, ads, prop->value(), checkADS));
1121 }
1123 continue;
1124 }
1125 if (auto strArrProp = dynamic_cast<ArrayProperty<std::string> *>(prop)) {
1126 const auto &wsNames((*strArrProp)());
1127 for (const auto &wsName : wsNames) {
1128 if (ads.doesExist(wsName)) {
1129 appendWS(ads.retrieve(wsName));
1130 }
1131 }
1132 }
1133 }
1134}
1135
1138 auto &logger = getLogger();
1139
1141 logger.notice() << name() << " started";
1142 if (this->isChild())
1143 logger.notice() << " (child)";
1144 logger.notice() << '\n';
1145 // Make use of the AlgorithmHistory class, which holds all the info we
1146 // want here
1147 AlgorithmHistory algHistory(this);
1148 size_t maxPropertyLength = 40;
1149 if (logger.is(Logger::Priority::PRIO_DEBUG)) {
1150 // include the full property value when logging in debug
1151 maxPropertyLength = 0;
1152 }
1153 algHistory.printSelf(logger.information(), 0, maxPropertyLength);
1154 }
1155}
1156
1157//=============================================================================================
1158//================================== WorkspaceGroup-related
1159//===================================
1160//=============================================================================================
1161
1184 size_t numGroups = 0;
1185 bool doProcessGroups = false;
1186
1187 // Unroll the groups or single inputs into vectors of workspaces
1188 const auto &ads = AnalysisDataService::Instance();
1190 m_groupWorkspaces.clear();
1191 for (auto inputWorkspaceProp : m_inputWorkspaceProps) {
1192 auto const prop = dynamic_cast<Property *>(inputWorkspaceProp);
1193 auto wsGroupProp = dynamic_cast<WorkspaceProperty<WorkspaceGroup> const *>(prop);
1194 auto ws = inputWorkspaceProp->getWorkspace();
1195 auto wsGroup = std::dynamic_pointer_cast<WorkspaceGroup>(ws);
1196
1197 // Workspace groups are NOT returned by IWP->getWorkspace() most of the
1198 // time because WorkspaceProperty is templated by <MatrixWorkspace> and
1199 // WorkspaceGroup does not subclass <MatrixWorkspace>
1200 if (!wsGroup && prop && !prop->value().empty()) {
1201 // So try to use the name in the AnalysisDataService
1202 try {
1203 wsGroup = ads.retrieveWS<WorkspaceGroup>(prop->value());
1204 } catch (Exception::NotFoundError &) { /* Do nothing */
1205 }
1206 }
1207
1208 // Found the group either directly or by name?
1209 // If the property is of type WorkspaceGroup then don't unroll
1210 if (wsGroup && !wsGroupProp) {
1211 numGroups++;
1212 doProcessGroups = true;
1213 m_unrolledInputWorkspaces.emplace_back(wsGroup->getAllItems());
1214 } else {
1215 // Single Workspace. Treat it as a "group" with only one member
1216 if (ws)
1218 else
1220 }
1221
1222 // Add to the list of groups
1223 m_groupWorkspaces.emplace_back(wsGroup);
1224 }
1225
1226 // No groups? Get out.
1227 if (numGroups == 0)
1228 return doProcessGroups;
1229
1230 // ---- Confirm that all the groups are the same size -----
1231 // Index of the single group
1232 m_singleGroup = -1;
1233 // Size of the single or of all the groups
1234 m_groupSize = 1;
1236 for (size_t i = 0; i < m_unrolledInputWorkspaces.size(); i++) {
1237 const auto &thisGroup = m_unrolledInputWorkspaces[i];
1238 // We're ok with empty groups if the workspace property is optional
1239 if (thisGroup.empty() && !m_inputWorkspaceProps[i]->isOptional())
1240 throw std::invalid_argument("Empty group passed as input");
1241 if (!thisGroup.empty()) {
1242 // Record the index of the single group.
1244 if (wsGroup && (numGroups == 1))
1245 m_singleGroup = int(i);
1246
1247 // For actual groups (>1 members)
1248 if (thisGroup.size() > 1) {
1249 // Check for matching group size
1250 if (m_groupSize > 1)
1251 if (thisGroup.size() != m_groupSize)
1252 throw std::invalid_argument("Input WorkspaceGroups are not of the same size.");
1253
1254 // Are ALL the names similar?
1255 if (wsGroup)
1257
1258 // Save the size for the next group
1259 m_groupSize = thisGroup.size();
1260 }
1261 }
1262 } // end for each group
1263
1264 // If you get here, then the groups are compatible
1265 return doProcessGroups;
1266}
1267
1276bool Algorithm::doCallProcessGroups(Mantid::Types::Core::DateAndTime &startTime) {
1277 // In the base implementation of processGroups, this normally calls
1278 // this->execute() again on each member of the group. Other algorithms may
1279 // choose to override that behavior (examples: CompareWorkspaces,
1280 // RenameWorkspace)
1281
1282 startTime = Mantid::Types::Core::DateAndTime::getCurrentTime();
1283 // Start a timer
1284 Timer timer;
1285 bool completed = false;
1286 try {
1287 // Call the concrete algorithm's processGroups method
1288 completed = processGroups();
1289 } catch (std::exception &ex) {
1290 // The child algorithm will already have logged the error etc.,
1291 // but we also need to update flags in the parent algorithm and
1292 // send an ErrorNotification (because the child isn't registered with the
1293 // AlgorithmMonitor).
1295 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
1296 throw;
1297 } catch (...) {
1299 notificationCenter().postNotification(new ErrorNotification(this, "UNKNOWN Exception caught from processGroups"));
1300 throw;
1301 }
1302
1303 // Check for a cancellation request in case the concrete algorithm doesn't
1305
1306 if (completed) {
1307 // Get how long this algorithm took to run
1308 const float duration = timer.elapsed();
1309
1310 if (trackingHistory()) {
1312 m_history->fillAlgorithmHistory(this, startTime, duration, g_execCount);
1313 } else {
1314 m_history = std::make_shared<AlgorithmHistory>(this, startTime, duration, ++g_execCount);
1315 }
1316 // find any further outputs created by the execution
1317 WorkspaceVector outputWorkspaces;
1318 const bool checkADS{true};
1319 findWorkspaces(outputWorkspaces, Direction::Output, checkADS);
1320 fillHistory(outputWorkspaces);
1323 }
1324 }
1325
1326 // in the base processGroups each individual exec stores its outputs
1328 this->store();
1329
1330 // Log that execution has completed.
1331 reportCompleted(duration, true /* this is for group processing*/);
1333 } else {
1335 }
1336
1337 notificationCenter().postNotification(new FinishedNotification(this, isExecuted()));
1338
1339 return completed;
1340}
1341
1349void Algorithm::fillHistory(const std::vector<Workspace_sptr> &outputWorkspaces) {
1350 // this is not a child algorithm. Add the history algorithm to the
1351 // WorkspaceHistory object.
1352 if (!isChild()) {
1353 auto copyHistoryToGroup = [](const Workspace &in, WorkspaceGroup &out) {
1354 for (auto &outGroupItem : out) {
1355 outGroupItem->history().addHistory(in.getHistory());
1356 }
1357 };
1358
1359 for (auto &outWS : outputWorkspaces) {
1360 auto outWSGroup = std::dynamic_pointer_cast<WorkspaceGroup>(outWS);
1361 // Copy the history from the cached input workspaces to the output ones
1362 for (const auto &inputWS : m_inputWorkspaceHistories) {
1363 if (outWSGroup) {
1364 copyHistoryToGroup(*inputWS, *outWSGroup);
1365 } else {
1366 outWS->history().addHistory(inputWS->getHistory());
1367 }
1368 }
1369 // Add history for this operation
1370 if (outWSGroup) {
1371 for (auto &outGroupItem : *outWSGroup) {
1372 outGroupItem->history().addHistory(m_history);
1373 }
1374 } else {
1375 // Add the history for the current algorithm to all the output
1376 // workspaces
1377 outWS->history().addHistory(m_history);
1378 }
1379 }
1380 }
1381 // this is a child algorithm, but we still want to keep the history.
1383 m_parentHistory->addChildHistory(m_history);
1384 }
1385}
1386
1387//--------------------------------------------------------------------------------------------
1401
1402 std::vector<WorkspaceGroup_sptr> outGroups;
1403
1404 // ---------- Create all the output workspaces ----------------------------
1405 for (auto &pureOutputWorkspaceProp : m_pureOutputWorkspaceProps) {
1406 auto *prop = dynamic_cast<Property *>(pureOutputWorkspaceProp);
1407 if (prop && !prop->value().empty()) {
1408 auto outWSGrp = std::make_shared<WorkspaceGroup>();
1409 outGroups.emplace_back(outWSGrp);
1410 // Put the GROUP in the ADS
1411 AnalysisDataService::Instance().addOrReplace(prop->value(), outWSGrp);
1412 if (auto workspaceProperty = dynamic_cast<WorkspaceProperty<Workspace> *>(pureOutputWorkspaceProp)) {
1413 Workspace_sptr outputWorkspace = outWSGrp;
1414 *workspaceProperty = outputWorkspace;
1415 }
1416 outWSGrp->observeADSNotifications(false);
1417 }
1418 }
1419
1420 double progress_proportion = 1.0 / static_cast<double>(m_groupSize);
1421 // Go through each entry in the input group(s)
1422 for (size_t entry = 0; entry < m_groupSize; entry++) {
1423 // use create Child Algorithm that look like this one
1424 Algorithm_sptr alg_sptr = this->createChildAlgorithm(this->name(), progress_proportion * static_cast<double>(entry),
1425 progress_proportion * (1 + static_cast<double>(entry)),
1426 this->isLogging(), this->version());
1427 // Make a child algorithm and turn off history recording for it, but always
1428 // store result in the ADS
1429 alg_sptr->setChild(true);
1430 alg_sptr->setAlwaysStoreInADS(true);
1431 alg_sptr->enableHistoryRecordingForChild(false);
1432 alg_sptr->setRethrows(true);
1433
1434 Algorithm *alg = alg_sptr.get();
1435 // Set all non-workspace properties
1436 this->copyNonWorkspaceProperties(alg, int(entry) + 1);
1437
1438 std::string outputBaseName;
1439
1440 // ---------- Set all the input workspaces ----------------------------
1441 for (size_t iwp = 0; iwp < m_unrolledInputWorkspaces.size(); iwp++) {
1442 const std::vector<Workspace_sptr> &thisGroup = m_unrolledInputWorkspaces[iwp];
1443 if (!thisGroup.empty()) {
1444 // By default (for a single group) point to the first/only workspace
1445 Workspace_sptr ws = thisGroup[0];
1446
1447 if ((m_singleGroup == int(iwp)) || m_singleGroup < 0) {
1448 // Either: this is the single group
1449 // OR: all inputs are groups
1450 // ... so get then entry^th workspace in this group
1451 if (entry < thisGroup.size()) {
1452 ws = thisGroup[entry];
1453 } else {
1454 // This can happen when one has more than one input group
1455 // workspaces, having different sizes. For example one workspace
1456 // group is the corrections which has N parts (e.g. weights for
1457 // polarized measurement) while the other one is the actual input
1458 // workspace group, where each item needs to be corrected together
1459 // with all N inputs of the second group. In this case processGroup
1460 // needs to be overridden, which is currently not possible in
1461 // python.
1462 throw std::runtime_error("Unable to process over groups; consider passing workspaces "
1463 "one-by-one or override processGroup method of the algorithm.");
1464 }
1465 }
1466 // Append the names together
1467 if (!outputBaseName.empty())
1468 outputBaseName += "_";
1469 outputBaseName += ws->getName();
1470
1471 // Set the property using the name of that workspace
1472 if (auto *prop = dynamic_cast<Property *>(m_inputWorkspaceProps[iwp])) {
1473 if (ws->getName().empty()) {
1474 alg->setProperty(prop->name(), ws);
1475 } else {
1476 alg->setPropertyValue(prop->name(), ws->getName());
1477 }
1478 } else {
1479 throw std::logic_error("Found a Workspace property which doesn't "
1480 "inherit from Property.");
1481 }
1482 } // not an empty (i.e. optional) input
1483 } // for each InputWorkspace property
1484
1485 std::vector<std::string> outputWSNames(m_pureOutputWorkspaceProps.size());
1486 // ---------- Set all the output workspaces ----------------------------
1487 for (size_t owp = 0; owp < m_pureOutputWorkspaceProps.size(); owp++) {
1488 if (auto *prop = dynamic_cast<Property *>(m_pureOutputWorkspaceProps[owp])) {
1489 // Default name = "in1_in2_out"
1490 const std::string inName = prop->value();
1491 if (inName.empty())
1492 continue;
1493 std::string outName;
1495 outName.append(inName).append("_").append(Strings::toString(entry + 1));
1496 } else {
1497 outName.append(outputBaseName).append("_").append(inName);
1498 }
1499
1500 auto inputProp =
1501 std::find_if(m_inputWorkspaceProps.begin(), m_inputWorkspaceProps.end(), WorkspacePropertyValueIs(inName));
1502
1503 // Overwrite workspaces in any input property if they have the same
1504 // name as an output (i.e. copy name button in algorithm dialog used)
1505 // (only need to do this for a single input, multiple will be handled
1506 // by ADS)
1507 if (inputProp != m_inputWorkspaceProps.end()) {
1508 const auto &inputGroup = m_unrolledInputWorkspaces[inputProp - m_inputWorkspaceProps.begin()];
1509 if (!inputGroup.empty())
1510 outName = inputGroup[entry]->getName();
1511 }
1512 // Except if all inputs had similar names, then the name is "out_1"
1513
1514 // Set in the output
1515 alg->setPropertyValue(prop->name(), outName);
1516
1517 outputWSNames[owp] = outName;
1518 } else {
1519 throw std::logic_error("Found a Workspace property which doesn't "
1520 "inherit from Property.");
1521 }
1522 } // for each OutputWorkspace property
1523
1524 // ------------ Execute the algo --------------
1525 try {
1526 alg->execute();
1527 } catch (std::exception &e) {
1528 std::ostringstream msg;
1529 msg << "Execution of " << this->name() << " for group entry " << (entry + 1) << " failed: ";
1530 msg << e.what(); // Add original message
1531 throw std::runtime_error(msg.str());
1532 }
1533
1534 // ------------ Fill in the output workspace group ------------------
1535 // this has to be done after execute() because a workspace must exist
1536 // when it is added to a group
1537 for (size_t owp = 0; owp < m_pureOutputWorkspaceProps.size(); owp++) {
1538 auto *prop = dynamic_cast<Property *>(m_pureOutputWorkspaceProps[owp]);
1539 if (prop && prop->value().empty())
1540 continue;
1541 // And add it to the output group
1542 outGroups[owp]->add(outputWSNames[owp]);
1543 }
1544
1545 } // for each entry in each group
1546
1547 // restore group notifications
1548 for (auto &outGroup : outGroups) {
1549 outGroup->observeADSNotifications(true);
1550 }
1551
1552 return true;
1553}
1554
1555//--------------------------------------------------------------------------------------------
1562 if (!alg)
1563 throw std::runtime_error("Algorithm not created!");
1564 const auto &props = this->getProperties();
1565 for (const auto &prop : props) {
1566 if (prop) {
1567
1568 const auto *wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
1569 // Copy the property using the string
1570 if (!wsProp)
1571 this->setOtherProperties(alg, prop->name(), prop->value(), periodNum);
1572 }
1573 }
1574}
1575
1576//--------------------------------------------------------------------------------------------
1585void Algorithm::setOtherProperties(IAlgorithm *alg, const std::string &propertyName, const std::string &propertyValue,
1586 int periodNum) {
1587 (void)periodNum; // Avoid compiler warning
1588 if (alg)
1589 alg->setPropertyValue(propertyName, propertyValue);
1590}
1591
1592//--------------------------------------------------------------------------------------------
1598 if (!prop) {
1599 return false;
1600 }
1601 const auto *const wsProp = dynamic_cast<const IWorkspaceProperty *>(prop);
1602 return (wsProp != nullptr);
1603}
1604
1605//=============================================================================================
1606//================================== Asynchronous Execution
1607//===================================
1608//=============================================================================================
1609namespace {
1613struct AsyncFlagHolder {
1617 explicit AsyncFlagHolder(std::atomic_bool &running_flag) : m_running_flag(running_flag) { m_running_flag = true; }
1619 ~AsyncFlagHolder() { m_running_flag = false; }
1620
1621private:
1623 AsyncFlagHolder() = delete;
1625 std::atomic_bool &m_running_flag;
1626};
1627} // namespace
1628
1629//--------------------------------------------------------------------------------------------
1635 std::make_unique<Poco::ActiveMethod<bool, Poco::Void, Algorithm>>(this, &Algorithm::executeAsyncImpl);
1636 m_runningAsync = true;
1637 try {
1638 return (*m_executeAsync)(Poco::Void());
1639 } catch (...) {
1640 m_runningAsync = false;
1641 throw;
1642 }
1643}
1644
1649bool Algorithm::executeAsyncImpl(const Poco::Void & /*unused*/) {
1650 AsyncFlagHolder running(m_runningAsync);
1651 return this->execute();
1652}
1653
1658Poco::NotificationCenter &Algorithm::notificationCenter() const {
1660 m_notificationCenter = std::make_unique<Poco::NotificationCenter>();
1661 return *m_notificationCenter;
1662}
1663
1667void Algorithm::handleChildProgressNotification(const Poco::AutoPtr<ProgressNotification> &pNf) {
1668 double p = m_startChildProgress + (m_endChildProgress - m_startChildProgress) * pNf->progress;
1669
1670 progress(p, pNf->message);
1671}
1672
1676const Poco::AbstractObserver &Algorithm::progressObserver() const {
1677 if (!m_progressObserver)
1678 m_progressObserver = std::make_unique<Poco::NObserver<Algorithm, ProgressNotification>>(
1680
1681 return *m_progressObserver;
1682}
1683
1684//--------------------------------------------------------------------------------------------
1689 // set myself to be cancelled
1690 m_cancel = true;
1691
1692 // Loop over the output workspaces and try to cancel them
1693 for (auto &weakPtr : m_ChildAlgorithms) {
1694 if (IAlgorithm_sptr sharedPtr = weakPtr.lock()) {
1695 sharedPtr->cancel();
1696 }
1697 }
1698}
1699
1701bool Algorithm::getCancel() const { return m_cancel; }
1702
1708bool Algorithm::isLogging() const { return g_log.getEnabled(); }
1709
1710/* Sets the logging priority offset. Values are subtracted from the log level.
1711 *
1712 * Example value=1 will turn warning into notice
1713 * Example value=-1 will turn notice into warning
1714 */
1716
1719
1720//--------------------------------------------------------------------------------------------
1725 // only throw exceptions if the code is not multi threaded otherwise you
1726 // contravene the OpenMP standard
1727 // that defines that all loops must complete, and no exception can leave an
1728 // OpenMP section
1729 // openmp cancel handling is performed using the ??, ?? and ?? macros in
1730 // each algrothim
1732 if (m_cancel)
1733 throw CancelException();
1734}
1735
1741void Algorithm::reportCompleted(const double &duration, const bool groupProcessing) {
1742 std::string optionalMessage;
1743 if (groupProcessing) {
1744 optionalMessage = ". Processed as a workspace group";
1745 }
1746
1749
1750 std::stringstream msg;
1751 msg << name() << " successful, Duration ";
1752 double seconds = duration;
1753 if (seconds > 60.) {
1754 auto minutes = static_cast<int>(seconds / 60.);
1755 msg << minutes << " minutes ";
1756 seconds = seconds - static_cast<double>(minutes) * 60.;
1757 }
1758 msg << std::fixed << std::setprecision(2) << seconds << " seconds" << optionalMessage;
1759 getLogger().notice(msg.str());
1760 }
1761 }
1762
1763 else {
1764 getLogger().debug() << name() << " finished with isChild = " << isChild() << '\n';
1765 }
1767}
1768
1772 if (UsageService::Instance().isEnabled()) {
1773 std::ostringstream oss;
1774 oss << this->name() << ".v" << this->version();
1775 UsageService::Instance().registerFeatureUsage(FeatureType::Algorithm, oss.str(), isChild());
1776 }
1777}
1778
1783
1788
1789bool Algorithm::isCompoundProperty(const std::string &name) const {
1790 return std::find(m_reservedList.cbegin(), m_reservedList.cend(), name) != m_reservedList.cend();
1791}
1792
1796
1797//---------------------------------------------------------------------------
1798// Algorithm's inner classes
1799//---------------------------------------------------------------------------
1800
1802 : Poco::Notification(), m_algorithm(alg) {}
1803
1804const IAlgorithm *Algorithm::AlgorithmNotification::algorithm() const { return m_algorithm; }
1805
1807std::string Algorithm::StartedNotification::name() const { return "StartedNotification"; }
1808
1810 : AlgorithmNotification(alg), success(res) {}
1811std::string Algorithm::FinishedNotification::name() const { return "FinishedNotification"; }
1812
1813Algorithm::ProgressNotification::ProgressNotification(const Algorithm *const alg, double p, std::string msg,
1814 double estimatedTime, int progressPrecision)
1815 : AlgorithmNotification(alg), progress(p), message(std::move(msg)), estimatedTime(estimatedTime),
1816 progressPrecision(progressPrecision) {}
1817
1818std::string Algorithm::ProgressNotification::name() const { return "ProgressNotification"; }
1819
1821 : AlgorithmNotification(alg), what(std::move(str)) {}
1822
1823std::string Algorithm::ErrorNotification::name() const { return "ErrorNotification"; }
1824
1825const char *Algorithm::CancelException::what() const noexcept { return "Algorithm terminated"; }
1826
1833void Algorithm::declareProperty(std::unique_ptr<Property> p, const std::string &doc) {
1834 m_properties.declareProperty(std::move(p), doc);
1835}
1836
1841void Algorithm::declareOrReplaceProperty(std::unique_ptr<Property> p, const std::string &doc) {
1842 m_properties.declareOrReplaceProperty(std::move(p), doc);
1843}
1844
1848
1860void Algorithm::setProperties(const std::string &propertiesJson,
1861 const std::unordered_set<std::string> &ignoreProperties, bool createMissing) {
1862 m_properties.setProperties(propertiesJson, ignoreProperties, createMissing);
1863}
1864
1871void Algorithm::setProperties(const ::Json::Value &jsonValue, const std::unordered_set<std::string> &ignoreProperties,
1872 bool createMissing) {
1873 m_properties.setProperties(jsonValue, ignoreProperties, createMissing);
1874}
1875
1882void Algorithm::setPropertiesWithString(const std::string &propertiesString,
1883 const std::unordered_set<std::string> &ignoreProperties) {
1884 m_properties.setPropertiesWithString(propertiesString, ignoreProperties);
1885}
1886
1895void Algorithm::setPropertyValue(const std::string &name, const std::string &value) {
1897 this->afterPropertySet(name);
1898}
1899
1907void Algorithm::setPropertyValueFromJson(const std::string &name, const Json::Value &value) {
1909 this->afterPropertySet(name);
1910}
1911
1922
1928bool Algorithm::existsProperty(const std::string &name) const { return m_properties.existsProperty(name); }
1929
1934
1940
1946std::string Algorithm::getPropertyValue(const std::string &name) const { return m_properties.getPropertyValue(name); }
1947
1956
1965
1970const std::vector<Property *> &Algorithm::getProperties() const { return m_properties.getProperties(); }
1971
1976std::vector<std::string> Algorithm::getDeclaredPropertyNames() const noexcept {
1978}
1979
1999
2004bool Algorithm::isDefault(const std::string &name) const {
2006}
2007
2015std::string Algorithm::asString(bool withDefaultValues) const { return m_properties.asString(withDefaultValues); }
2022::Json::Value Algorithm::asJson(bool withDefaultValues) const { return m_properties.asJson(withDefaultValues); }
2023
2029void Algorithm::removeProperty(const std::string &name, const bool delproperty) {
2030 m_properties.removeProperty(name, delproperty);
2031}
2032
2038std::unique_ptr<Kernel::Property> Algorithm::takeProperty(const size_t index) {
2040}
2041
2046
2054
2055} // namespace API
2056
2057//---------------------------------------------------------------------------
2058// Specialized templated PropertyManager getValue definitions for Algorithm
2059// types
2060//---------------------------------------------------------------------------
2061namespace Kernel {
2067template <>
2068MANTID_API_DLL API::IAlgorithm_sptr IPropertyManager::getValue<API::IAlgorithm_sptr>(const std::string &name) const {
2069 auto *prop = dynamic_cast<PropertyWithValue<API::IAlgorithm_sptr> *>(getPointerToProperty(name));
2070 if (prop) {
2071 return *prop;
2072 } else {
2073 std::string message = "Attempt to assign property " + name + " to incorrect type. Expected shared_ptr<IAlgorithm>";
2074 throw std::runtime_error(message);
2075 }
2076}
2077
2084template <>
2086IPropertyManager::getValue<API::IAlgorithm_const_sptr>(const std::string &name) const {
2087 const auto *prop = dynamic_cast<PropertyWithValue<API::IAlgorithm_sptr> *>(getPointerToProperty(name));
2088 if (prop) {
2089 return prop->operator()();
2090 } else {
2091 std::string message =
2092 "Attempt to assign property " + name + " to incorrect type. Expected const shared_ptr<IAlgorithm>";
2093 throw std::runtime_error(message);
2094 }
2095}
2096
2097} // namespace Kernel
2098
2099} // namespace Mantid
const std::string & m_value
Definition Algorithm.cpp:72
std::atomic_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:521
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:528
bool isRunning() const override
True if the algorithm is scheduled or 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:368
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:484
std::vector< std::string > m_reservedList
Reserved property names.
Definition Algorithm.h:531
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:523
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:420
bool isExecuted() const override
Has the Algorithm already been executed successfully.
void enableCheckForStringArrayWorkspaceOutputs(const bool on)
enable flag to scan output StringArrayProperties for workspace names
::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:513
bool m_rethrow
Algorithm should rethrow exceptions while executing.
Definition Algorithm.h:495
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:499
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:438
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:504
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:441
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:408
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:429
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:422
std::vector< IWorkspaceProperty * > m_outputWorkspaceProps
All the WorkspaceProperties that are Output or InOut. Set in execute()
Definition Algorithm.h:516
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:518
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:435
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:511
virtual void init()=0
Virtual method - must be overridden by concrete algorithm.
Kernel::Logger & g_log
Definition Algorithm.h:426
std::vector< std::shared_ptr< Workspace > > WorkspaceVector
Definition Algorithm.h:286
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:493
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:487
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
bool m_checkForStringArrayWorkspaceOutputs
Flag to indicate checking of output StringArrayProperty outputs for valid workspaces.
Definition Algorithm.h:491
std::unique_ptr< Poco::ActiveMethod< bool, Poco::Void, Algorithm, Poco::ActiveStarter< Algorithm > > > m_executeAsync
Poco::ActiveMethod used to implement asynchronous execution.
Definition Algorithm.h:477
std::vector< WorkspaceVector > m_unrolledInputWorkspaces
One vector of workspaces for each input workspace property.
Definition Algorithm.h:433
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:488
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:536
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.
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:486
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:525
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.
std::atomic_bool m_runningAsync
Algorithm is scheduled or running asynchronously.
Definition Algorithm.h:494
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:501
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:534
std::unique_ptr< Poco::NotificationCenter > m_notificationCenter
Sends notifications to observers.
Definition Algorithm.h:482
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:414
bool m_recordHistoryForChild
Flag to indicate whether history should be recorded.
Definition Algorithm.h:489
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:46
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:30
const WorkspaceHistory & getHistory() const
Returns a reference to the WorkspaceHistory const.
Definition Workspace.h:86
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:95
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:34
ExecutionState
The current state of the algorithm object.
Definition IAlgorithm.h:32
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:735
std::shared_ptr< PropertyHistory > PropertyHistory_sptr
std::shared_ptr< IValidator > IValidator_sptr
A shared_ptr to an IValidator.
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:56
@ Input
An input workspace.
Definition Property.h:54
@ Output
An output workspace.
Definition Property.h:55
Utility class that enables the getProperty() method to effectively be templated on the return type.