Mantid
Loading...
Searching...
No Matches
Algorithm.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
18
19#include "MantidJson/Json.h"
26#include "MantidKernel/Timer.h"
28
30#include <Poco/ActiveMethod.h>
31#include <Poco/ActiveResult.h>
32#include <Poco/NotificationCenter.h>
33#include <Poco/RWLock.h>
34#include <Poco/Void.h>
35
36#include <H5Cpp.h>
37#include <json/json.h>
38
39#include <algorithm>
40#include <iterator>
41#include <map>
42#include <memory>
43#include <utility>
44
45// Index property handling template definitions
47
48using namespace Mantid::Kernel;
49
50namespace Mantid {
51namespace API {
52namespace {
54const std::string WORKSPACE_TYPES_SEPARATOR = ";";
55
58const size_t DELAY_BEFORE_GC = 5;
59
60class WorkspacePropertyValueIs {
61public:
62 explicit WorkspacePropertyValueIs(const std::string &value) : m_value(value) {}
63 bool operator()(IWorkspaceProperty *property) {
64 auto *prop = dynamic_cast<Property *>(property);
65 if (!prop)
66 return false;
67 return prop->value() == m_value;
68 }
69
70private:
71 const std::string &m_value;
72};
73
74template <typename T> struct RunOnFinish {
75 RunOnFinish(T &&task) : m_onfinsh(std::move(task)) {}
76 ~RunOnFinish() { m_onfinsh(); }
77
78private:
80};
81
82} // namespace
83
84// Doxygen can't handle member specialization at the moment:
85// https://bugzilla.gnome.org/show_bug.cgi?id=406027
86// so we have to ignore them
88template <typename NumT> bool Algorithm::isEmpty(const NumT toCheck) {
89 return static_cast<int>(toCheck) == EMPTY_INT();
90}
91
92template <> MANTID_API_DLL bool Algorithm::isEmpty(const double toCheck) {
93 return std::abs((toCheck - EMPTY_DBL()) / (EMPTY_DBL())) < 1e-8;
94}
95
96// concrete instantiations
97template MANTID_API_DLL bool Algorithm::isEmpty<int>(const int);
98template MANTID_API_DLL bool Algorithm::isEmpty<int64_t>(const int64_t);
99template MANTID_API_DLL bool Algorithm::isEmpty<std::size_t>(const std::size_t);
101
102//=============================================================================================
103//================================== Constructors/Destructors
104//=================================
105//=============================================================================================
106
108size_t Algorithm::g_execCount = 0;
109
112 : m_cancel(false), m_parallelException(false), m_log("Algorithm"), g_log(m_log), m_groupSize(0),
113 m_executeAsync(nullptr), m_notificationCenter(nullptr), m_progressObserver(nullptr),
114 m_executionState(ExecutionState::Uninitialized), m_resultState(ResultState::NotFinished),
115 m_isChildAlgorithm(false), m_recordHistoryForChild(false), m_alwaysStoreInADS(true), m_runningAsync(false),
116 m_rethrow(false), m_isAlgStartupLoggingEnabled(true), m_startChildProgress(0.), m_endChildProgress(0.),
117 m_algorithmID(this), m_singleGroup(-1), m_groupsHaveSimilarNames(false), m_inputWorkspaceHistories(),
118 m_properties() {}
119
121Algorithm::~Algorithm() = default;
122
123//=============================================================================================
124//================================== Simple Getters/Setters
125//===================================
126//=============================================================================================
127
130
133
136
145
146//---------------------------------------------------------------------------------------------
149
154
155//---------------------------------------------------------------------------------------------
161
166void Algorithm::setChild(const bool isChild) {
168 this->setAlwaysStoreInADS(!isChild);
169}
170
177
183void Algorithm::setAlwaysStoreInADS(const bool doStore) {
184 m_alwaysStoreInADS = doStore;
185
186 // Set OutputWorkspace as an optional property in the case where alwaysStoreInADS is false. In
187 // this case, the output workspace name is not always required.
188 if (!m_alwaysStoreInADS && m_properties.existsProperty("OutputWorkspace")) {
189 Property *property = m_properties.getPointerToProperty("OutputWorkspace");
191 }
192}
193
198
202void Algorithm::setRethrows(const bool rethrow) { this->m_rethrow = rethrow; }
203
206
210 (Mantid::Types::Core::DateAndTime::getCurrentTime() > m_gcTime)) {
211 return true;
212 }
213 return false;
214}
215
216//---------------------------------------------------------------------------------------------
220void Algorithm::addObserver(const Poco::AbstractObserver &observer) const {
221 notificationCenter().addObserver(observer);
222}
223
227void Algorithm::removeObserver(const Poco::AbstractObserver &observer) const {
228 notificationCenter().removeObserver(observer);
229}
230
231//---------------------------------------------------------------------------------------------
240void Algorithm::progress(double p, const std::string &msg, double estimatedTime, int progressPrecision) {
241 notificationCenter().postNotification(new ProgressNotification(this, p, msg, estimatedTime, progressPrecision));
242}
243
244//---------------------------------------------------------------------------------------------
246const std::vector<std::string> Algorithm::categories() const {
250
251 auto res = tokenizer.asVector();
252
253 const auto *depo = dynamic_cast<const DeprecatedAlgorithm *>(this);
254 if (depo != nullptr) {
255 res.emplace_back("Deprecated");
256 }
257 return res;
258}
259
264const std::string Algorithm::workspaceMethodName() const { return ""; }
265
277
281const std::string Algorithm::workspaceMethodInputProperty() const { return ""; }
282
283//---------------------------------------------------------------------------------------------
293 // Bypass the initialization if the algorithm has already been initialized.
294 if (isInitialized())
295 return;
296
297 g_log.setName(this->name());
299 try {
300 try {
301 this->init();
302 } catch (std::runtime_error &) {
303 throw;
304 }
305
306 // Indicate that this Algorithm has been initialized to prevent duplicate
307 // attempts.
309 } catch (std::runtime_error &) {
310 throw;
311 }
312 // Unpleasant catch-all! Along with this, Gaudi version catches GaudiException
313 // & std::exception
314 // but doesn't really do anything except (print fatal) messages.
315 catch (...) {
316 // Gaudi: A call to the auditor service is here
317 // (1) perform the printout
318 getLogger().fatal("UNKNOWN Exception is caught in initialize()");
319 throw;
320 }
321}
322
323//---------------------------------------------------------------------------------------------
332std::map<std::string, std::string> Algorithm::validateInputs() { return std::map<std::string, std::string>(); }
333
334//---------------------------------------------------------------------------------------------
340 m_inputWorkspaceProps.clear();
343 const auto &props = this->getProperties();
344 for (const auto &prop : props) {
345 auto wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
346 if (!wsProp)
347 continue;
348 switch (prop->direction()) {
350 m_inputWorkspaceProps.emplace_back(wsProp);
351 break;
353 m_inputWorkspaceProps.emplace_back(wsProp);
354 m_outputWorkspaceProps.emplace_back(wsProp);
355 break;
357 m_outputWorkspaceProps.emplace_back(wsProp);
358 m_pureOutputWorkspaceProps.emplace_back(wsProp);
359 break;
360 default:
361 throw std::logic_error("Unexpected property direction found for property " + prop->name() + " of algorithm " +
362 this->name());
363 }
364 }
365}
366
372 if (!trackingHistory())
373 return;
374
375 auto cacheHistories = [this](const Workspace_sptr &ws) {
376 if (auto group = dynamic_cast<const WorkspaceGroup *>(ws.get())) {
378 std::copy(group->begin(), group->end(), std::back_inserter(m_inputWorkspaceHistories));
379 } else {
380 m_inputWorkspaceHistories.emplace_back(ws);
381 }
382 };
383 using ArrayPropertyString = ArrayProperty<std::string>;
384 auto isADSValidator = [](const IValidator_sptr &validator) -> bool {
385 if (!validator)
386 return false;
387 if (dynamic_cast<ADSValidator *>(validator.get()))
388 return true;
389 if (const auto compValidator = dynamic_cast<CompositeValidator *>(validator.get()))
390 return compValidator->contains<ADSValidator>();
391
392 return false;
393 };
394
395 // Look over all properties so we can catch an string array properties
396 // with an ADSValidator. ADSValidator indicates that the strings
397 // point to workspace names so we want to pick up the history from these too.
398 const auto &ads = AnalysisDataService::Instance();
400 const auto &props = this->getProperties();
401 for (const auto &prop : props) {
402 if (prop->direction() != Direction::Input && prop->direction() != Direction::InOut)
403 continue;
404
405 if (auto wsProp = dynamic_cast<IWorkspaceProperty const *>(prop)) {
406 if (auto ws = wsProp->getWorkspace()) {
407 cacheHistories(ws);
408 } else {
409 Workspace_sptr wsFromADS;
410 try {
411 wsFromADS = ads.retrieve(prop->value());
412 } catch (Exception::NotFoundError &) {
413 continue;
414 }
415 cacheHistories(wsFromADS);
416 }
417 } else if (auto strArrayProp = dynamic_cast<ArrayPropertyString *>(prop)) {
418 if (!isADSValidator(strArrayProp->getValidator()))
419 continue;
420 const auto &wsNames((*strArrayProp)());
421 for (const auto &wsName : wsNames) {
422 cacheHistories(ads.retrieve(wsName));
423 }
424 }
425 }
426} // namespace API
427
428//---------------------------------------------------------------------------------------------
434 // Do not lock workspace for child algos
435 if (this->isChild())
436 return;
437
438 if (!m_readLockedWorkspaces.empty() || !m_writeLockedWorkspaces.empty())
439 throw std::logic_error("Algorithm::lockWorkspaces(): The workspaces have "
440 "already been locked!");
441
442 // First, Write-lock the output workspaces
443 auto &debugLog = g_log.debug();
444 for (auto &outputWorkspaceProp : m_outputWorkspaceProps) {
445 Workspace_sptr ws = outputWorkspaceProp->getWorkspace();
446 if (ws) {
447 // The workspace property says to do locking,
448 // AND it has NOT already been write-locked
449 if (outputWorkspaceProp->isLocking() && std::find(m_writeLockedWorkspaces.begin(), m_writeLockedWorkspaces.end(),
450 ws) == m_writeLockedWorkspaces.end()) {
451 // Write-lock it if not already
452 debugLog << "Write-locking " << ws->getName() << '\n';
453 ws->getLock()->writeLock();
454 m_writeLockedWorkspaces.emplace_back(ws);
455 }
456 }
457 }
458
459 // Next read-lock the input workspaces
460 for (auto &inputWorkspaceProp : m_inputWorkspaceProps) {
461 Workspace_sptr ws = inputWorkspaceProp->getWorkspace();
462 if (ws) {
463 // The workspace property says to do locking,
464 // AND it has NOT already been write-locked
465 if (inputWorkspaceProp->isLocking() && std::find(m_writeLockedWorkspaces.begin(), m_writeLockedWorkspaces.end(),
466 ws) == m_writeLockedWorkspaces.end()) {
467 // Read-lock it if not already write-locked
468 debugLog << "Read-locking " << ws->getName() << '\n';
469 ws->getLock()->readLock();
470 m_readLockedWorkspaces.emplace_back(ws);
471 }
472 }
473 }
474}
475
476//---------------------------------------------------------------------------------------------
481 // Do not lock workspace for child algos
482 if (this->isChild())
483 return;
484 auto &debugLog = g_log.debug();
485 for (auto &ws : m_writeLockedWorkspaces) {
486 if (ws) {
487 debugLog << "Unlocking " << ws->getName() << '\n';
488 ws->getLock()->unlock();
489 }
490 }
491 for (auto &ws : m_readLockedWorkspaces) {
492 if (ws) {
493 debugLog << "Unlocking " << ws->getName() << '\n';
494 ws->getLock()->unlock();
495 }
496 }
497
498 // Don't double-unlock workspaces
501}
502
515
516//---------------------------------------------------------------------------------------------
521 Timer timer;
522 bool algIsExecuted = false;
523 AlgorithmManager::Instance().notifyAlgorithmStarting(this->getAlgorithmID());
524
525 // runtime check for deprecation warning
526 {
527 auto *depo = dynamic_cast<DeprecatedAlgorithm *>(this);
528 if (depo != nullptr)
529 getLogger().error(depo->deprecationMsg(this));
530 }
531
532 // runtime check for deprecated alias warning
533 {
534 auto *da_alg = dynamic_cast<DeprecatedAlias *>(this);
535 if ((da_alg != nullptr) && (this->calledByAlias))
536 getLogger().warning(da_alg->deprecationMessage(this));
537 }
538
539 // Register clean up tasks that should happen regardless of the route
540 // out of the algorithm. These tasks will get run after this method
541 // finishes.
542 RunOnFinish onFinish([this]() { this->clearWorkspaceCaches(); });
543
544 notificationCenter().postNotification(new StartedNotification(this));
545 Mantid::Types::Core::DateAndTime startTime;
546
547 // Return a failure if the algorithm hasn't been initialized
548 if (!isInitialized()) {
549 throw std::runtime_error("Algorithm is not initialised:" + this->name());
550 }
551
552 // no logging of input if a child algorithm (except for python child algos)
555
556 // Check all properties for validity
557 constexpr bool resetTimer{true};
558 float timingInit = timer.elapsed(resetTimer);
559 if (!validateProperties()) {
560 // Reset name on input workspaces to trigger attempt at collection from ADS
561 const auto &props = getProperties();
562 for (auto &prop : props) {
563 const auto *wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
564 if (wsProp && !(wsProp->getWorkspace())) {
565 // Setting it's name to the same one it already had
566 prop->setValue(prop->value());
567 }
568 }
569 // Try the validation again
570 if (!validateProperties()) {
571 notificationCenter().postNotification(new ErrorNotification(this, "Some invalid Properties found"));
572 throw std::runtime_error("Some invalid Properties found");
573 }
574 }
575 const float timingPropertyValidation = timer.elapsed(resetTimer);
576
577 // All properties are now valid - cache workspace properties and histories
580
581 // ----- Check for processing groups -------------
582 // default true so that it has the right value at the check below the catch
583 // block should checkGroups throw
584 bool callProcessGroups = true;
585 try {
586 // Checking the input is a group. Throws if the sizes are wrong
587 callProcessGroups = this->checkGroups();
588 } catch (std::exception &ex) {
589 getLogger().error() << "Error in execution of algorithm " << this->name() << "\n" << ex.what() << "\n";
590 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
593 m_runningAsync = false;
594 throw;
595 }
596 return false;
597 }
598
599 timingInit += timer.elapsed(resetTimer);
600 // ----- Perform validation of the whole set of properties -------------
601 if ((!callProcessGroups)) // for groups this is called on each workspace separately
602 {
603 std::map<std::string, std::string> errors = this->validateInputs();
604 if (!errors.empty()) {
605 size_t numErrors = errors.size();
606 // Log each issue
607 auto &errorLog = getLogger().error();
608 auto &warnLog = getLogger().warning();
609 for (auto &error : errors) {
610 if (this->existsProperty(error.first))
611 errorLog << "Invalid value for " << error.first << ": " << error.second << "\n";
612 else {
613 numErrors -= 1; // don't count it as an error
614 warnLog << "validateInputs() references non-existant property \"" << error.first << "\"\n";
615 }
616 }
617 // Throw because something was invalid
618 if (numErrors > 0) {
619 std::stringstream msg;
620 msg << "Some invalid Properties found: ";
621 for (const auto &error : errors) {
622 msg << "\n " << error.first << ": " << error.second;
623 }
624 notificationCenter().postNotification(new ErrorNotification(this, "Some invalid Properties found"));
625 throw std::runtime_error(msg.str());
626 }
627 }
628 }
629 const float timingInputValidation = timer.elapsed(resetTimer);
630
631 if (trackingHistory()) {
632 // count used for defining the algorithm execution order
633 // If history is being recorded we need to count this as a separate
634 // algorithm
635 // as the history compares histories by their execution number
637
638 // populate history record before execution so we can record child
639 // algorithms in it
640 AlgorithmHistory algHist;
641 m_history = std::make_shared<AlgorithmHistory>(algHist);
642 }
643
644 // ----- Process groups -------------
645 // If checkGroups() threw an exception but there ARE group workspaces
646 // (means that the group sizes were incompatible)
647 if (callProcessGroups) {
648 return doCallProcessGroups(startTime);
649 }
650
651 // Read or write locks every input/output workspace
652 this->lockWorkspaces();
653 timingInit += timer.elapsed(resetTimer);
654
655 // Invoke exec() method of derived class and catch all uncaught exceptions
656 try {
657 try {
659
660 startTime = Mantid::Types::Core::DateAndTime::getCurrentTime();
661 // Call the concrete algorithm's exec method
662 this->exec();
664 // Check for a cancellation request in case the concrete algorithm doesn't
666 const float timingExec = timer.elapsed(resetTimer);
667 // The total runtime including all init steps is used for general logging.
668 const float duration = timingInit + timingPropertyValidation + timingInputValidation + timingExec;
669 // need it to throw before trying to run fillhistory() on an algorithm
670 // which has failed
671 if (trackingHistory() && m_history) {
672 m_history->fillAlgorithmHistory(this, startTime, duration, Algorithm::g_execCount);
673 fillHistory();
675 }
676
677 // Put the output workspaces into the AnalysisDataService - if requested
679 this->store();
680
681 // just cache the value internally, it is set at the very end of this
682 // method
683 algIsExecuted = true;
684
685 // Log that execution has completed.
686 getLogger().debug("Time to validate properties: " + std::to_string(timingPropertyValidation) + " seconds\n" +
687 "Time for other input validation: " + std::to_string(timingInputValidation) + " seconds\n" +
688 "Time for other initialization: " + std::to_string(timingInit) + " seconds\n" +
689 "Time to run exec: " + std::to_string(timingExec) + " seconds\n");
690 reportCompleted(duration);
691 } catch (std::runtime_error &ex) {
692 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
693 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
695 this->unlockWorkspaces();
697 throw;
698 else {
699 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
700 getLogger().error() << "Error in execution of algorithm " << this->name() << '\n' << ex.what() << '\n';
701 }
702
703 } catch (std::logic_error &ex) {
704 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
705 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
706 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
708 this->unlockWorkspaces();
710 throw;
711 else {
712 getLogger().error() << "Logic Error in execution of algorithm " << this->name() << '\n' << ex.what() << '\n';
713 }
714 }
715 } catch (CancelException &ex) {
716 m_runningAsync = false;
717 getLogger().warning() << this->name() << ": Execution cancelled by user.\n";
718 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
719 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
721 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
722 this->unlockWorkspaces();
723
724 throw;
725 }
726 // Gaudi also specifically catches GaudiException & std:exception.
727 catch (std::exception &ex) {
728 m_runningAsync = false;
729 getLogger().error() << "Error in execution of algorithm " << this->name() << ":\n" << ex.what() << "\n";
730 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
731 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
733 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
734 this->unlockWorkspaces();
735
736 throw;
737 }
738
739 catch (H5::Exception &ex) {
740 m_runningAsync = false;
741 std::string errmsg;
742 errmsg.append(ex.getCFuncName()).append(": ").append(ex.getCDetailMsg());
743 getLogger().error() << "H5 Exception in execution of algorithm " << this->name() << ":\n" << errmsg << "\n";
744 m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
745 (Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
747 notificationCenter().postNotification(new ErrorNotification(this, errmsg));
748 this->unlockWorkspaces();
749
750 throw;
751 }
752
753 catch (...) {
754 // Execution failed with an unknown exception object
755 m_runningAsync = false;
756
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 }
1122 }
1123}
1124
1127 auto &logger = getLogger();
1128
1130 logger.notice() << name() << " started";
1131 if (this->isChild())
1132 logger.notice() << " (child)";
1133 logger.notice() << '\n';
1134 // Make use of the AlgorithmHistory class, which holds all the info we
1135 // want here
1136 AlgorithmHistory algHistory(this);
1137 size_t maxPropertyLength = 40;
1138 if (logger.is(Logger::Priority::PRIO_DEBUG)) {
1139 // include the full property value when logging in debug
1140 maxPropertyLength = 0;
1141 }
1142 algHistory.printSelf(logger.information(), 0, maxPropertyLength);
1143 }
1144}
1145
1146//=============================================================================================
1147//================================== WorkspaceGroup-related
1148//===================================
1149//=============================================================================================
1150
1173 size_t numGroups = 0;
1174 bool doProcessGroups = false;
1175
1176 // Unroll the groups or single inputs into vectors of workspaces
1177 const auto &ads = AnalysisDataService::Instance();
1179 m_groupWorkspaces.clear();
1180 for (auto inputWorkspaceProp : m_inputWorkspaceProps) {
1181 auto const prop = dynamic_cast<Property *>(inputWorkspaceProp);
1182 auto wsGroupProp = dynamic_cast<WorkspaceProperty<WorkspaceGroup> const *>(prop);
1183 auto ws = inputWorkspaceProp->getWorkspace();
1184 auto wsGroup = std::dynamic_pointer_cast<WorkspaceGroup>(ws);
1185
1186 // Workspace groups are NOT returned by IWP->getWorkspace() most of the
1187 // time because WorkspaceProperty is templated by <MatrixWorkspace> and
1188 // WorkspaceGroup does not subclass <MatrixWorkspace>
1189 if (!wsGroup && prop && !prop->value().empty()) {
1190 // So try to use the name in the AnalysisDataService
1191 try {
1192 wsGroup = ads.retrieveWS<WorkspaceGroup>(prop->value());
1193 } catch (Exception::NotFoundError &) { /* Do nothing */
1194 }
1195 }
1196
1197 // Found the group either directly or by name?
1198 // If the property is of type WorkspaceGroup then don't unroll
1199 if (wsGroup && !wsGroupProp) {
1200 numGroups++;
1201 doProcessGroups = true;
1202 m_unrolledInputWorkspaces.emplace_back(wsGroup->getAllItems());
1203 } else {
1204 // Single Workspace. Treat it as a "group" with only one member
1205 if (ws)
1207 else
1209 }
1210
1211 // Add to the list of groups
1212 m_groupWorkspaces.emplace_back(wsGroup);
1213 }
1214
1215 // No groups? Get out.
1216 if (numGroups == 0)
1217 return doProcessGroups;
1218
1219 // ---- Confirm that all the groups are the same size -----
1220 // Index of the single group
1221 m_singleGroup = -1;
1222 // Size of the single or of all the groups
1223 m_groupSize = 1;
1225 for (size_t i = 0; i < m_unrolledInputWorkspaces.size(); i++) {
1226 const auto &thisGroup = m_unrolledInputWorkspaces[i];
1227 // We're ok with empty groups if the workspace property is optional
1228 if (thisGroup.empty() && !m_inputWorkspaceProps[i]->isOptional())
1229 throw std::invalid_argument("Empty group passed as input");
1230 if (!thisGroup.empty()) {
1231 // Record the index of the single group.
1233 if (wsGroup && (numGroups == 1))
1234 m_singleGroup = int(i);
1235
1236 // For actual groups (>1 members)
1237 if (thisGroup.size() > 1) {
1238 // Check for matching group size
1239 if (m_groupSize > 1)
1240 if (thisGroup.size() != m_groupSize)
1241 throw std::invalid_argument("Input WorkspaceGroups are not of the same size.");
1242
1243 // Are ALL the names similar?
1244 if (wsGroup)
1246
1247 // Save the size for the next group
1248 m_groupSize = thisGroup.size();
1249 }
1250 }
1251 } // end for each group
1252
1253 // If you get here, then the groups are compatible
1254 return doProcessGroups;
1255}
1256
1265bool Algorithm::doCallProcessGroups(Mantid::Types::Core::DateAndTime &startTime) {
1266 // In the base implementation of processGroups, this normally calls
1267 // this->execute() again on each member of the group. Other algorithms may
1268 // choose to override that behavior (examples: CompareWorkspaces,
1269 // RenameWorkspace)
1270
1271 startTime = Mantid::Types::Core::DateAndTime::getCurrentTime();
1272 // Start a timer
1273 Timer timer;
1274 bool completed = false;
1275 try {
1276 // Call the concrete algorithm's processGroups method
1277 completed = processGroups();
1278 } catch (std::exception &ex) {
1279 // The child algorithm will already have logged the error etc.,
1280 // but we also need to update flags in the parent algorithm and
1281 // send an ErrorNotification (because the child isn't registered with the
1282 // AlgorithmMonitor).
1284 m_runningAsync = false;
1285 notificationCenter().postNotification(new ErrorNotification(this, ex.what()));
1286 throw;
1287 } catch (...) {
1289 m_runningAsync = false;
1290 notificationCenter().postNotification(new ErrorNotification(this, "UNKNOWN Exception caught from processGroups"));
1291 throw;
1292 }
1293
1294 // Check for a cancellation request in case the concrete algorithm doesn't
1296
1297 if (completed) {
1298 // Get how long this algorithm took to run
1299 const float duration = timer.elapsed();
1300
1301 m_history = std::make_shared<AlgorithmHistory>(this, startTime, duration, ++g_execCount);
1302 if (trackingHistory() && m_history) {
1303 // find any further outputs created by the execution
1304 WorkspaceVector outputWorkspaces;
1305 const bool checkADS{true};
1306 findWorkspaces(outputWorkspaces, Direction::Output, checkADS);
1307 fillHistory(outputWorkspaces);
1308 }
1309
1310 // in the base processGroups each individual exec stores its outputs
1312 this->store();
1313
1314 // Log that execution has completed.
1315 reportCompleted(duration, true /* this is for group processing*/);
1317 } else {
1319 }
1320
1321 notificationCenter().postNotification(new FinishedNotification(this, isExecuted()));
1322
1323 return completed;
1324}
1325
1333void Algorithm::fillHistory(const std::vector<Workspace_sptr> &outputWorkspaces) {
1334 // this is not a child algorithm. Add the history algorithm to the
1335 // WorkspaceHistory object.
1336 if (!isChild()) {
1337 auto copyHistoryToGroup = [](const Workspace &in, WorkspaceGroup &out) {
1338 for (auto &outGroupItem : out) {
1339 outGroupItem->history().addHistory(in.getHistory());
1340 }
1341 };
1342
1343 for (auto &outWS : outputWorkspaces) {
1344 auto outWSGroup = std::dynamic_pointer_cast<WorkspaceGroup>(outWS);
1345 // Copy the history from the cached input workspaces to the output ones
1346 for (const auto &inputWS : m_inputWorkspaceHistories) {
1347 if (outWSGroup) {
1348 copyHistoryToGroup(*inputWS, *outWSGroup);
1349 } else {
1350 outWS->history().addHistory(inputWS->getHistory());
1351 }
1352 }
1353 // Add history for this operation
1354 if (outWSGroup) {
1355 for (auto &outGroupItem : *outWSGroup) {
1356 outGroupItem->history().addHistory(m_history);
1357 }
1358 } else {
1359 // Add the history for the current algorithm to all the output
1360 // workspaces
1361 outWS->history().addHistory(m_history);
1362 }
1363 }
1364 }
1365 // this is a child algorithm, but we still want to keep the history.
1367 m_parentHistory->addChildHistory(m_history);
1368 }
1369}
1370
1371//--------------------------------------------------------------------------------------------
1385
1386 std::vector<WorkspaceGroup_sptr> outGroups;
1387
1388 // ---------- Create all the output workspaces ----------------------------
1389 for (auto &pureOutputWorkspaceProp : m_pureOutputWorkspaceProps) {
1390 auto *prop = dynamic_cast<Property *>(pureOutputWorkspaceProp);
1391 if (prop && !prop->value().empty()) {
1392 auto outWSGrp = std::make_shared<WorkspaceGroup>();
1393 outGroups.emplace_back(outWSGrp);
1394 // Put the GROUP in the ADS
1395 AnalysisDataService::Instance().addOrReplace(prop->value(), outWSGrp);
1396 outWSGrp->observeADSNotifications(false);
1397 }
1398 }
1399
1400 double progress_proportion = 1.0 / static_cast<double>(m_groupSize);
1401 // Go through each entry in the input group(s)
1402 for (size_t entry = 0; entry < m_groupSize; entry++) {
1403 // use create Child Algorithm that look like this one
1404 Algorithm_sptr alg_sptr = this->createChildAlgorithm(this->name(), progress_proportion * static_cast<double>(entry),
1405 progress_proportion * (1 + static_cast<double>(entry)),
1406 this->isLogging(), this->version());
1407 // Make a child algorithm and turn off history recording for it, but always
1408 // store result in the ADS
1409 alg_sptr->setChild(true);
1410 alg_sptr->setAlwaysStoreInADS(true);
1411 alg_sptr->enableHistoryRecordingForChild(false);
1412 alg_sptr->setRethrows(true);
1413
1414 Algorithm *alg = alg_sptr.get();
1415 // Set all non-workspace properties
1416 this->copyNonWorkspaceProperties(alg, int(entry) + 1);
1417
1418 std::string outputBaseName;
1419
1420 // ---------- Set all the input workspaces ----------------------------
1421 for (size_t iwp = 0; iwp < m_unrolledInputWorkspaces.size(); iwp++) {
1422 const std::vector<Workspace_sptr> &thisGroup = m_unrolledInputWorkspaces[iwp];
1423 if (!thisGroup.empty()) {
1424 // By default (for a single group) point to the first/only workspace
1425 Workspace_sptr ws = thisGroup[0];
1426
1427 if ((m_singleGroup == int(iwp)) || m_singleGroup < 0) {
1428 // Either: this is the single group
1429 // OR: all inputs are groups
1430 // ... so get then entry^th workspace in this group
1431 if (entry < thisGroup.size()) {
1432 ws = thisGroup[entry];
1433 } else {
1434 // This can happen when one has more than one input group
1435 // workspaces, having different sizes. For example one workspace
1436 // group is the corrections which has N parts (e.g. weights for
1437 // polarized measurement) while the other one is the actual input
1438 // workspace group, where each item needs to be corrected together
1439 // with all N inputs of the second group. In this case processGroup
1440 // needs to be overridden, which is currently not possible in
1441 // python.
1442 throw std::runtime_error("Unable to process over groups; consider passing workspaces "
1443 "one-by-one or override processGroup method of the algorithm.");
1444 }
1445 }
1446 // Append the names together
1447 if (!outputBaseName.empty())
1448 outputBaseName += "_";
1449 outputBaseName += ws->getName();
1450
1451 // Set the property using the name of that workspace
1452 if (auto *prop = dynamic_cast<Property *>(m_inputWorkspaceProps[iwp])) {
1453 if (ws->getName().empty()) {
1454 alg->setProperty(prop->name(), ws);
1455 } else {
1456 alg->setPropertyValue(prop->name(), ws->getName());
1457 }
1458 } else {
1459 throw std::logic_error("Found a Workspace property which doesn't "
1460 "inherit from Property.");
1461 }
1462 } // not an empty (i.e. optional) input
1463 } // for each InputWorkspace property
1464
1465 std::vector<std::string> outputWSNames(m_pureOutputWorkspaceProps.size());
1466 // ---------- Set all the output workspaces ----------------------------
1467 for (size_t owp = 0; owp < m_pureOutputWorkspaceProps.size(); owp++) {
1468 if (auto *prop = dynamic_cast<Property *>(m_pureOutputWorkspaceProps[owp])) {
1469 // Default name = "in1_in2_out"
1470 const std::string inName = prop->value();
1471 if (inName.empty())
1472 continue;
1473 std::string outName;
1475 outName.append(inName).append("_").append(Strings::toString(entry + 1));
1476 } else {
1477 outName.append(outputBaseName).append("_").append(inName);
1478 }
1479
1480 auto inputProp =
1481 std::find_if(m_inputWorkspaceProps.begin(), m_inputWorkspaceProps.end(), WorkspacePropertyValueIs(inName));
1482
1483 // Overwrite workspaces in any input property if they have the same
1484 // name as an output (i.e. copy name button in algorithm dialog used)
1485 // (only need to do this for a single input, multiple will be handled
1486 // by ADS)
1487 if (inputProp != m_inputWorkspaceProps.end()) {
1488 const auto &inputGroup = m_unrolledInputWorkspaces[inputProp - m_inputWorkspaceProps.begin()];
1489 if (!inputGroup.empty())
1490 outName = inputGroup[entry]->getName();
1491 }
1492 // Except if all inputs had similar names, then the name is "out_1"
1493
1494 // Set in the output
1495 alg->setPropertyValue(prop->name(), outName);
1496
1497 outputWSNames[owp] = outName;
1498 } else {
1499 throw std::logic_error("Found a Workspace property which doesn't "
1500 "inherit from Property.");
1501 }
1502 } // for each OutputWorkspace property
1503
1504 // ------------ Execute the algo --------------
1505 try {
1506 alg->execute();
1507 } catch (std::exception &e) {
1508 std::ostringstream msg;
1509 msg << "Execution of " << this->name() << " for group entry " << (entry + 1) << " failed: ";
1510 msg << e.what(); // Add original message
1511 throw std::runtime_error(msg.str());
1512 }
1513
1514 // ------------ Fill in the output workspace group ------------------
1515 // this has to be done after execute() because a workspace must exist
1516 // when it is added to a group
1517 for (size_t owp = 0; owp < m_pureOutputWorkspaceProps.size(); owp++) {
1518 auto *prop = dynamic_cast<Property *>(m_pureOutputWorkspaceProps[owp]);
1519 if (prop && prop->value().empty())
1520 continue;
1521 // And add it to the output group
1522 outGroups[owp]->add(outputWSNames[owp]);
1523 }
1524
1525 } // for each entry in each group
1526
1527 // restore group notifications
1528 for (auto &outGroup : outGroups) {
1529 outGroup->observeADSNotifications(true);
1530 }
1531
1532 return true;
1533}
1534
1535//--------------------------------------------------------------------------------------------
1542 if (!alg)
1543 throw std::runtime_error("Algorithm not created!");
1544 const auto &props = this->getProperties();
1545 for (const auto &prop : props) {
1546 if (prop) {
1547
1548 const auto *wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
1549 // Copy the property using the string
1550 if (!wsProp)
1551 this->setOtherProperties(alg, prop->name(), prop->value(), periodNum);
1552 }
1553 }
1554}
1555
1556//--------------------------------------------------------------------------------------------
1565void Algorithm::setOtherProperties(IAlgorithm *alg, const std::string &propertyName, const std::string &propertyValue,
1566 int periodNum) {
1567 (void)periodNum; // Avoid compiler warning
1568 if (alg)
1569 alg->setPropertyValue(propertyName, propertyValue);
1570}
1571
1572//--------------------------------------------------------------------------------------------
1578 if (!prop) {
1579 return false;
1580 }
1581 const auto *const wsProp = dynamic_cast<const IWorkspaceProperty *>(prop);
1582 return (wsProp != nullptr);
1583}
1584
1585//=============================================================================================
1586//================================== Asynchronous Execution
1587//===================================
1588//=============================================================================================
1589namespace {
1593struct AsyncFlagHolder {
1597 explicit AsyncFlagHolder(bool &running_flag) : m_running_flag(running_flag) { m_running_flag = true; }
1599 ~AsyncFlagHolder() { m_running_flag = false; }
1600
1601private:
1603 AsyncFlagHolder() = delete;
1606};
1607} // namespace
1608
1609//--------------------------------------------------------------------------------------------
1615 std::make_unique<Poco::ActiveMethod<bool, Poco::Void, Algorithm>>(this, &Algorithm::executeAsyncImpl);
1616 return (*m_executeAsync)(Poco::Void());
1617}
1618
1623bool Algorithm::executeAsyncImpl(const Poco::Void & /*unused*/) {
1624 AsyncFlagHolder running(m_runningAsync);
1625 return this->execute();
1626}
1627
1632Poco::NotificationCenter &Algorithm::notificationCenter() const {
1634 m_notificationCenter = std::make_unique<Poco::NotificationCenter>();
1635 return *m_notificationCenter;
1636}
1637
1641void Algorithm::handleChildProgressNotification(const Poco::AutoPtr<ProgressNotification> &pNf) {
1642 double p = m_startChildProgress + (m_endChildProgress - m_startChildProgress) * pNf->progress;
1643
1644 progress(p, pNf->message);
1645}
1646
1650const Poco::AbstractObserver &Algorithm::progressObserver() const {
1651 if (!m_progressObserver)
1652 m_progressObserver = std::make_unique<Poco::NObserver<Algorithm, ProgressNotification>>(
1654
1655 return *m_progressObserver;
1656}
1657
1658//--------------------------------------------------------------------------------------------
1663 // set myself to be cancelled
1664 m_cancel = true;
1665
1666 // Loop over the output workspaces and try to cancel them
1667 for (auto &weakPtr : m_ChildAlgorithms) {
1668 if (IAlgorithm_sptr sharedPtr = weakPtr.lock()) {
1669 sharedPtr->cancel();
1670 }
1671 }
1672}
1673
1675bool Algorithm::getCancel() const { return m_cancel; }
1676
1682bool Algorithm::isLogging() const { return g_log.getEnabled(); }
1683
1684/* Sets the logging priority offset. Values are subtracted from the log level.
1685 *
1686 * Example value=1 will turn warning into notice
1687 * Example value=-1 will turn notice into warning
1688 */
1690
1693
1694//--------------------------------------------------------------------------------------------
1699 // only throw exceptions if the code is not multi threaded otherwise you
1700 // contravene the OpenMP standard
1701 // that defines that all loops must complete, and no exception can leave an
1702 // OpenMP section
1703 // openmp cancel handling is performed using the ??, ?? and ?? macros in
1704 // each algrothim
1706 if (m_cancel)
1707 throw CancelException();
1708}
1709
1715void Algorithm::reportCompleted(const double &duration, const bool groupProcessing) {
1716 std::string optionalMessage;
1717 if (groupProcessing) {
1718 optionalMessage = ". Processed as a workspace group";
1719 }
1720
1723
1724 std::stringstream msg;
1725 msg << name() << " successful, Duration ";
1726 double seconds = duration;
1727 if (seconds > 60.) {
1728 auto minutes = static_cast<int>(seconds / 60.);
1729 msg << minutes << " minutes ";
1730 seconds = seconds - static_cast<double>(minutes) * 60.;
1731 }
1732 msg << std::fixed << std::setprecision(2) << seconds << " seconds" << optionalMessage;
1733 getLogger().notice(msg.str());
1734 }
1735 }
1736
1737 else {
1738 getLogger().debug() << name() << " finished with isChild = " << isChild() << '\n';
1739 }
1741}
1742
1746 if (UsageService::Instance().isEnabled()) {
1747 std::ostringstream oss;
1748 oss << this->name() << ".v" << this->version();
1749 UsageService::Instance().registerFeatureUsage(FeatureType::Algorithm, oss.str(), isChild());
1750 }
1751}
1752
1757
1762
1763bool Algorithm::isCompoundProperty(const std::string &name) const {
1764 return std::find(m_reservedList.cbegin(), m_reservedList.cend(), name) != m_reservedList.cend();
1765}
1766
1767//---------------------------------------------------------------------------
1768// Algorithm's inner classes
1769//---------------------------------------------------------------------------
1770
1772 : Poco::Notification(), m_algorithm(alg) {}
1773
1774const IAlgorithm *Algorithm::AlgorithmNotification::algorithm() const { return m_algorithm; }
1775
1777std::string Algorithm::StartedNotification::name() const { return "StartedNotification"; }
1778
1780 : AlgorithmNotification(alg), success(res) {}
1781std::string Algorithm::FinishedNotification::name() const { return "FinishedNotification"; }
1782
1783Algorithm::ProgressNotification::ProgressNotification(const Algorithm *const alg, double p, std::string msg,
1784 double estimatedTime, int progressPrecision)
1785 : AlgorithmNotification(alg), progress(p), message(std::move(msg)), estimatedTime(estimatedTime),
1786 progressPrecision(progressPrecision) {}
1787
1788std::string Algorithm::ProgressNotification::name() const { return "ProgressNotification"; }
1789
1791 : AlgorithmNotification(alg), what(std::move(str)) {}
1792
1793std::string Algorithm::ErrorNotification::name() const { return "ErrorNotification"; }
1794
1795const char *Algorithm::CancelException::what() const noexcept { return "Algorithm terminated"; }
1796
1803void Algorithm::declareProperty(std::unique_ptr<Property> p, const std::string &doc) {
1804 m_properties.declareProperty(std::move(p), doc);
1805}
1806
1811void Algorithm::declareOrReplaceProperty(std::unique_ptr<Property> p, const std::string &doc) {
1812 m_properties.declareOrReplaceProperty(std::move(p), doc);
1813}
1814
1818
1830void Algorithm::setProperties(const std::string &propertiesJson,
1831 const std::unordered_set<std::string> &ignoreProperties, bool createMissing) {
1832 m_properties.setProperties(propertiesJson, ignoreProperties, createMissing);
1833}
1834
1841void Algorithm::setProperties(const ::Json::Value &jsonValue, const std::unordered_set<std::string> &ignoreProperties,
1842 bool createMissing) {
1843 m_properties.setProperties(jsonValue, ignoreProperties, createMissing);
1844}
1845
1852void Algorithm::setPropertiesWithString(const std::string &propertiesString,
1853 const std::unordered_set<std::string> &ignoreProperties) {
1854 m_properties.setPropertiesWithString(propertiesString, ignoreProperties);
1855}
1856
1865void Algorithm::setPropertyValue(const std::string &name, const std::string &value) {
1867 this->afterPropertySet(name);
1868}
1869
1877void Algorithm::setPropertyValueFromJson(const std::string &name, const Json::Value &value) {
1879 this->afterPropertySet(name);
1880}
1881
1892
1898bool Algorithm::existsProperty(const std::string &name) const { return m_properties.existsProperty(name); }
1899
1904
1910
1916std::string Algorithm::getPropertyValue(const std::string &name) const { return m_properties.getPropertyValue(name); }
1917
1926
1935
1940const std::vector<Property *> &Algorithm::getProperties() const { return m_properties.getProperties(); }
1941
1946std::vector<std::string> Algorithm::getDeclaredPropertyNames() const noexcept {
1948}
1949
1969
1974bool Algorithm::isDefault(const std::string &name) const {
1976}
1977
1985std::string Algorithm::asString(bool withDefaultValues) const { return m_properties.asString(withDefaultValues); }
1992::Json::Value Algorithm::asJson(bool withDefaultValues) const { return m_properties.asJson(withDefaultValues); }
1993
1999void Algorithm::removeProperty(const std::string &name, const bool delproperty) {
2000 m_properties.removeProperty(name, delproperty);
2001}
2002
2008std::unique_ptr<Kernel::Property> Algorithm::takeProperty(const size_t index) {
2010}
2011
2016
2024
2025} // namespace API
2026
2027//---------------------------------------------------------------------------
2028// Specialized templated PropertyManager getValue definitions for Algorithm
2029// types
2030//---------------------------------------------------------------------------
2031namespace Kernel {
2037template <>
2038MANTID_API_DLL API::IAlgorithm_sptr IPropertyManager::getValue<API::IAlgorithm_sptr>(const std::string &name) const {
2039 auto *prop = dynamic_cast<PropertyWithValue<API::IAlgorithm_sptr> *>(getPointerToProperty(name));
2040 if (prop) {
2041 return *prop;
2042 } else {
2043 std::string message = "Attempt to assign property " + name + " to incorrect type. Expected shared_ptr<IAlgorithm>";
2044 throw std::runtime_error(message);
2045 }
2046}
2047
2054template <>
2056IPropertyManager::getValue<API::IAlgorithm_const_sptr>(const std::string &name) const {
2057 const auto *prop = dynamic_cast<PropertyWithValue<API::IAlgorithm_sptr> *>(getPointerToProperty(name));
2058 if (prop) {
2059 return prop->operator()();
2060 } else {
2061 std::string message =
2062 "Attempt to assign property " + name + " to incorrect type. Expected const shared_ptr<IAlgorithm>";
2063 throw std::runtime_error(message);
2064 }
2065}
2066
2067} // namespace Kernel
2068
2069} // namespace Mantid
const std::string & m_value
Definition Algorithm.cpp:71
bool & m_running_flag
Running flag.
T m_onfinsh
Definition Algorithm.cpp:79
std::string name
Definition Run.cpp:60
double value
The value of the point.
Definition FitMW.cpp:51
double error
IPeaksWorkspace_sptr workspace
std::map< DeltaEMode::Type, std::string > index
#define PARALLEL_CRITICAL(name)
#define IF_NOT_PARALLEL
std::vector< history_type > history
history information
ADSValidator : a validator that requires the value of a property to be present in the ADS.
This class stores information about the Command History used by algorithms on a workspace.
void printSelf(std::ostream &, const int indent=0, const size_t maxPropertyLength=0) const
print contents of object
Base class for algorithm notifications.
Definition Algorithm.h:79
AlgorithmNotification(const Algorithm *const alg)
CancelException is thrown to cancel execution of the algorithm.
Definition Algorithm.h:136
const char * what() const noexcept override
Returns the message string.
ErrorNotification is sent when an exception is caught during execution of the algorithm.
Definition Algorithm.h:121
std::string name() const override
ErrorNotification(const Algorithm *const alg, std::string str)
Constructor.
FinishedNotification is sent after the algorithm finishes its execution.
Definition Algorithm.h:96
FinishedNotification(const Algorithm *const alg, bool res)
An algorithm can report its progress by sending ProgressNotification.
Definition Algorithm.h:106
ProgressNotification(const Algorithm *const alg, double p, std::string msg, double estimatedTime, int progressPrecision)
Constructor.
StartedNotification is sent when the algorithm begins execution.
Definition Algorithm.h:89
StartedNotification(const Algorithm *const alg)
std::string name() const override
class name
Base class from which all concrete algorithm classes should be derived.
Definition Algorithm.h:76
void clearWorkspaceCaches()
Clear any internal workspace handles so that workspaces will be deleted promptly after a managed algo...
void setRethrows(const bool rethrow) override
Set whether the algorithm will rethrow exceptions.
const std::string categorySeparator() const override
Function to return the separator token for the category string.
Definition Algorithm.h:165
std::vector< std::shared_ptr< WorkspaceGroup > > m_groupWorkspaces
Pointer to the WorkspaceGroup (if any) for each input workspace property.
Definition Algorithm.h:512
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:519
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:364
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:477
std::vector< std::string > m_reservedList
Reserved property names.
Definition Algorithm.h:522
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:514
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:416
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:504
bool m_rethrow
Algorithm should rethrow exceptions while executing.
Definition Algorithm.h:486
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:490
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:434
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:495
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.
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:404
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:425
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:418
std::vector< IWorkspaceProperty * > m_outputWorkspaceProps
All the WorkspaceProperties that are Output or InOut. Set in execute()
Definition Algorithm.h:507
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:509
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:431
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:502
virtual void init()=0
Virtual method - must be overridden by concrete algorithm.
Kernel::Logger & g_log
Definition Algorithm.h:422
std::vector< std::shared_ptr< Workspace > > WorkspaceVector
Definition Algorithm.h:282
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:484
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:480
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:470
std::vector< WorkspaceVector > m_unrolledInputWorkspaces
One vector of workspaces for each input workspace property.
Definition Algorithm.h:429
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:481
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:527
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:485
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:479
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:516
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:492
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:525
std::unique_ptr< Poco::NotificationCenter > m_notificationCenter
Sends notifications to observers.
Definition Algorithm.h:475
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:410
bool m_recordHistoryForChild
Flag to indicate whether history should be recorded.
Definition Algorithm.h:482
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.
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:61
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.