Mantid
Loading...
Searching...
No Matches
IFunction.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 +
8#include "MantidAPI/Axis.h"
14#include "MantidAPI/Jacobian.h"
30#include "MantidKernel/Logger.h"
36
37#include <boost/lexical_cast.hpp>
38
40
41#include <algorithm>
42#include <limits>
43#include <sstream>
44#include <utility>
45
46namespace {
47
48constexpr double EPSILON = std::numeric_limits<double>::epsilon();
49constexpr double MIN_DOUBLE = std::numeric_limits<double>::min();
50constexpr double STEP_PERCENTAGE = 0.001;
51
52const auto defaultStepSize = [](const double parameterValue) -> double {
53 return fabs(parameterValue) < 100.0 * MIN_DOUBLE / STEP_PERCENTAGE ? 100.0 * EPSILON
54 : parameterValue * STEP_PERCENTAGE;
55};
56
57const auto sqrtEpsilonStepSize = [](const double parameterValue) -> double {
58 return fabs(parameterValue) < 1 ? sqrt(EPSILON) : parameterValue * sqrt(EPSILON);
59};
60
61} // namespace
62
63namespace Mantid::API {
64using namespace Geometry;
65
66namespace {
68Kernel::Logger g_log("IFunction");
69
71struct TieNode {
72 // Index of the tied parameter
73 size_t left;
74 // Indices of parameters on the right-hand-side of the expression
75 std::vector<size_t> right;
76 // This tie must be applied before the other if the RHS of the other
77 // contains this (left) parameter.
78 bool operator<(TieNode const &other) const {
79 return std::find(other.right.begin(), other.right.end(), left) != other.right.end();
80 }
81};
82const std::vector<std::string> EXCLUDEUSAGE = {"CompositeFunction"};
83} // namespace
84
88IFunction::IFunction() : m_isParallel(false), m_handler(nullptr), m_chiSquared(0.0) {}
89
94
99 if (!Kernel::UsageService::Instance().isEnabled()) {
100 return;
101 }
102 if (std::find(EXCLUDEUSAGE.cbegin(), EXCLUDEUSAGE.cend(), name()) == EXCLUDEUSAGE.cend() && !m_isRegistered) {
103 m_isRegistered = true;
104 Kernel::UsageService::Instance().registerFeatureUsage(Kernel::FeatureType::Function, name(), internal);
105 }
106}
110std::shared_ptr<IFunction> IFunction::clone() const {
111 auto clonedFunction = FunctionFactory::Instance().createInitialized(this->asString());
112 for (size_t i = 0; i < this->nParams(); i++) {
113 double error = this->getError(i);
114 clonedFunction->setError(i, error);
115 }
116 return clonedFunction;
117}
118
124void IFunction::setProgressReporter(std::shared_ptr<Kernel::ProgressBase> reporter) {
125 m_progReporter = std::move(reporter);
126 m_progReporter->setNotifyStep(0.01);
127}
128
133void IFunction::setCustomStepSizes(const std::vector<double> &stepSizes) { m_stepSizes = stepSizes; }
134
139void IFunction::reportProgress(const std::string &msg) const {
140 if (m_progReporter) {
141 const_cast<Kernel::ProgressBase *>(m_progReporter.get())->report(msg);
142 }
143}
144
151 if (m_progReporter)
153 else
154 return false;
155}
156
162void IFunction::functionDeriv(const FunctionDomain &domain, Jacobian &jacobian) { calNumericalDeriv(domain, jacobian); }
163
167bool IFunction::isActive(size_t i) const { return getParameterStatus(i) == Active; }
168
174bool IFunction::isFixed(size_t i) const {
175 auto status = getParameterStatus(i);
176 return status == Fixed || status == FixedByDefault;
177}
178
183
188void IFunction::fix(size_t i, bool isDefault) {
189 auto status = getParameterStatus(i);
190 if (status == Tied) {
191 throw std::runtime_error("Cannot fix parameter " + std::to_string(i) + " (" + parameterName(i) +
192 "): it has a tie.");
193 }
194 if (isDefault) {
196 } else {
198 }
199}
200
204void IFunction::unfix(size_t i) {
205 auto status = getParameterStatus(i);
206 if (status == Tied) {
207 throw std::runtime_error("Cannot unfix parameter " + std::to_string(i) + " (" + parameterName(i) +
208 "): it has a tie.");
209 }
211}
212
220std::unique_ptr<ParameterTie> IFunction::createAndProcessTie(const std::string &parName, const std::string &expr,
221 bool isDefault) {
222 auto newTie = std::make_unique<ParameterTie>(this, parName, expr, isDefault);
223
224 if (!isDefault && newTie->isConstant()) {
225 setParameter(parName, newTie->eval());
226 fix(getParameterIndex(*newTie));
227 return nullptr;
228 }
229
230 return newTie;
231}
232
240void IFunction::tie(const std::string &parName, const std::string &expr, bool isDefault) {
241 auto tiePtr = createAndProcessTie(parName, expr, isDefault);
242
243 if (tiePtr) {
244 addTie(std::move(tiePtr));
245 }
246}
247
257void IFunction::addTies(const std::string &ties, bool isDefault) {
258 std::map<size_t, std::pair<size_t, std::string>> oldTies;
259
260 Expression list;
261 list.parse(ties);
262 list.toList();
263 for (const auto &t : list) {
264 if (t.name() == "=" && t.size() >= 2) {
265 size_t n = t.size() - 1;
266 const std::string expr = t[n].str();
267 for (size_t i = n; i != 0;) {
268 --i;
269 const auto &parName = t[i].name();
270 auto parTie = createAndProcessTie(parName, expr, isDefault);
271
272 if (parTie) {
273 auto iPar = getParameterIndex(*parTie);
274 oldTies[iPar] = insertTie(std::move(parTie));
275 }
276 }
277 }
278 }
279
280 try {
281 sortTies(true);
282 } catch (std::runtime_error &) {
283 for (const auto &[iPar, oldTie] : oldTies) {
284 auto [oldIdx, oldExp] = oldTie;
285
286 if (!oldExp.empty()) {
287 m_ties[oldIdx] = std::make_unique<ParameterTie>(this, parameterName(iPar), oldExp);
288 } else {
289 removeTie(iPar);
290 }
291 }
292 throw;
293 }
294 applyTies();
295}
296
301void IFunction::removeTie(const std::string &parName) {
302 size_t i = parameterIndex(parName);
303 this->removeTie(i);
304}
305
308std::string IFunction::writeTies() const {
309 std::ostringstream tieStream;
310 bool first = true;
311 for (auto &parTie : m_ties) {
312 if (parTie->isDefault())
313 continue;
314 if (!first) {
315 tieStream << ',';
316 } else {
317 first = false;
318 }
319 tieStream << parTie->asString(this);
320 }
321 return tieStream.str();
322}
323
329std::pair<std::size_t, std::string> IFunction::insertTie(std::unique_ptr<ParameterTie> tie) {
330 auto iPar = getParameterIndex(*tie);
331 std::size_t existingTieIndex =
332 std::distance(m_ties.begin(), std::find_if(m_ties.begin(), m_ties.end(),
333 [&](const auto &m_tie) { return getParameterIndex(*m_tie) == iPar; }));
334 std::string oldExp = "";
335 const auto oldTie = getTie(iPar);
336 if (oldTie) {
337 const auto oldTieStr = oldTie->asString();
338 oldExp = oldTieStr.substr(oldTieStr.find("=") + 1);
339 }
340
341 if (existingTieIndex < m_ties.size()) {
342 m_ties[existingTieIndex] = std::move(tie);
343 } else {
344 m_ties.emplace_back(std::move(tie));
346 }
347
348 if (oldTie) {
349 return {existingTieIndex, oldExp};
350 } else {
351 return {existingTieIndex, ""};
352 }
353}
354
360void IFunction::addTie(std::unique_ptr<ParameterTie> tie) {
361 auto iPar = getParameterIndex(*tie);
362 const auto [oldIdx, oldExp] = insertTie(std::move(tie));
363
364 try {
365 // sortTies checks for circular and self ties
366 sortTies(true);
367 } catch (std::runtime_error &) {
368 // revert / remove tie if invalid
369 if (!oldExp.empty()) {
370 m_ties[oldIdx] = std::make_unique<ParameterTie>(this, parameterName(iPar), oldExp);
371 } else {
372 removeTie(iPar);
373 }
374 throw;
375 }
376}
377
378bool IFunction::hasOrderedTies() const { return !m_orderedTies.empty(); }
379
381 for (auto &&parTie : m_orderedTies) {
382 parTie->eval();
383 }
384}
385
390 if (hasOrderedTies()) {
392 } else {
393 for (auto &parTie : m_ties) {
394 parTie->eval();
395 }
396 }
397}
398
406 const size_t m_i;
407
408public:
410 explicit ReferenceEqual(const IFunction &fun, size_t i) : m_fun(fun), m_i(i) {}
414 template <class T> bool operator()(const std::unique_ptr<T> &p) { return m_fun.getParameterIndex(*p) == m_i; }
415};
416
421bool IFunction::removeTie(size_t i) {
422 if (i >= nParams()) {
423 throw std::out_of_range("Function parameter index out of range.");
424 }
425 auto it = std::find_if(m_ties.begin(), m_ties.end(), ReferenceEqual(*this, i));
426 if (it != m_ties.end()) {
427 m_ties.erase(it);
429 return true;
430 }
431 unfix(i);
432 return false;
433}
434
440 auto it = std::find_if(m_ties.cbegin(), m_ties.cend(), ReferenceEqual(*this, i));
441 if (it != m_ties.cend()) {
442 return it->get();
443 }
444 return nullptr;
445}
446
450 for (size_t i = 0; i < nParams(); ++i) {
452 }
453 m_ties.clear();
454}
455
459void IFunction::addConstraint(std::unique_ptr<IConstraint> ic) {
460 size_t iPar = ic->parameterIndex();
461 auto it = std::find_if(m_constraints.begin(), m_constraints.end(),
462 [&iPar](const auto &constraint) { return constraint->parameterIndex() == iPar; });
463
464 if (it != m_constraints.end()) {
465 *it = std::move(ic);
466 } else {
467 m_constraints.emplace_back(std::move(ic));
468 }
469}
470
476 auto it = std::find_if(m_constraints.cbegin(), m_constraints.cend(), ReferenceEqual(*this, i));
477 if (it != m_constraints.cend()) {
478 return it->get();
479 }
480 return nullptr;
481}
482
486void IFunction::removeConstraint(const std::string &parName) {
487 size_t iPar = parameterIndex(parName);
488 const auto it = std::find_if(m_constraints.cbegin(), m_constraints.cend(),
489 [&iPar](const auto &constraint) { return iPar == constraint->getLocalIndex(); });
490 if (it != m_constraints.cend()) {
491 m_constraints.erase(it);
492 }
493}
494
499void IFunction::setConstraintPenaltyFactor(const std::string &parName, const double &c) {
500 size_t iPar = parameterIndex(parName);
501 const auto it = std::find_if(m_constraints.cbegin(), m_constraints.cend(),
502 [&iPar](const auto &constraint) { return iPar == constraint->getLocalIndex(); });
503
504 if (it != m_constraints.cend()) {
505 (*it)->setPenaltyFactor(c);
506 } else {
507 g_log.warning() << parName << " does not have constraint so setConstraintPenaltyFactor failed"
508 << "\n";
509 }
510}
511
514
516 for (auto &constraint : m_constraints) {
517 constraint->setParamToSatisfyConstraint();
518 }
519}
520
523std::string IFunction::writeConstraints() const {
524 std::ostringstream stream;
525 bool first = true;
526 for (const auto &constrint : m_constraints) {
527 if (constrint->isDefault())
528 continue;
529 if (!first) {
530 stream << ',';
531 } else {
532 first = false;
533 }
534 stream << constrint->asString();
535 }
536 return stream.str();
537}
538
544std::string IFunction::asString() const { return writeToString(); }
545
553std::string IFunction::writeToString(const std::string &parentLocalAttributesStr) const {
554 std::ostringstream ostr;
555 ostr << "name=" << this->name();
556 // print the attributes
557 std::vector<std::string> attr = this->getAttributeNames();
558 for (const auto &attName : attr) {
559 std::string attValue = this->getAttribute(attName).value();
560 if (!attValue.empty() && attValue != "\"\"") {
561 ostr << ',' << attName << '=' << attValue;
562 }
563 }
564 std::vector<std::string> ties;
565 // print the parameters
566 for (size_t i = 0; i < nParams(); i++) {
567 std::ostringstream paramOut;
568 paramOut << parameterName(i) << '=' << getParameter(i);
569 ostr << ',' << paramOut.str();
570 // Output non-default ties only.
571 if (getParameterStatus(i) == Fixed) {
572 ties.emplace_back(paramOut.str());
573 }
574 }
575
576 // collect non-default constraints
577 std::string constraints = writeConstraints();
578 // print constraints
579 if (!constraints.empty()) {
580 ostr << ",constraints=(" << constraints << ")";
581 }
582
583 // collect the non-default ties
584 auto tiesString = writeTies();
585 if (!tiesString.empty()) {
586 ties.emplace_back(tiesString);
587 }
588 // print the ties
589 if (!ties.empty()) {
590 ostr << ",ties=(" << Kernel::Strings::join(ties.begin(), ties.end(), ",") << ")";
591 }
592 // "local" attributes of a parent composite function
593 ostr << parentLocalAttributesStr;
594 return ostr.str();
595}
596
603void IFunction::addConstraints(const std::string &str, bool isDefault) {
604 Expression list;
605 list.parse(str);
606 list.toList();
607 for (auto it = list.begin(); it != list.end(); ++it) {
608 auto expr = (*it);
609 if (expr.terms()[0].str().compare("penalty") == 0) {
610 continue;
611 }
612 if ((it + 1) != list.end()) {
613 auto next_expr = *(it + 1);
614 if (next_expr.terms()[0].str().compare("penalty") == 0) {
615 auto c = std::unique_ptr<IConstraint>(ConstraintFactory::Instance().createInitialized(this, expr, isDefault));
616 double penalty_factor = std::stof(next_expr.terms()[1].str(), NULL);
617 c->setPenaltyFactor(penalty_factor);
618 this->addConstraint(std::move(c));
619 } else {
620 auto c = std::unique_ptr<IConstraint>(ConstraintFactory::Instance().createInitialized(this, expr, isDefault));
621 this->addConstraint(std::move(c));
622 }
623 } else {
624 auto c = std::unique_ptr<IConstraint>(ConstraintFactory::Instance().createInitialized(this, expr, isDefault));
625 this->addConstraint(std::move(c));
626 }
627 }
628}
629
633std::vector<std::string> IFunction::getParameterNames() const {
634 std::vector<std::string> out;
635 for (size_t i = 0; i < nParams(); ++i) {
636 out.emplace_back(parameterName(i));
637 }
638 return out;
639}
640
644void IFunction::setHandler(std::unique_ptr<FunctionHandler> handler) {
645 if (handler && handler->function().get() != this) {
646 throw std::runtime_error("Function handler points to a different function");
647 }
648
649 m_handler = std::move(handler);
650 m_handler->init();
651}
652
660
666std::ostream &operator<<(std::ostream &ostr, const IFunction &f) {
667 ostr << f.asString();
668 return ostr;
669}
670
671namespace {
675class AttType : public IFunction::ConstAttributeVisitor<std::string> {
676protected:
678 std::string apply(const std::string & /*str*/) const override { return "std::string"; }
680 std::string apply(const int & /*i*/) const override { return "int"; }
682 std::string apply(const double & /*d*/) const override { return "double"; }
684 std::string apply(const bool & /*i*/) const override { return "bool"; }
686 std::string apply(const std::vector<double> & /*unused*/) const override { return "std::vector<double>"; }
687};
688} // namespace
689
690std::string IFunction::Attribute::type() const {
691 AttType tmp;
692 return apply(tmp);
693}
694
695namespace {
699class AttValue : public IFunction::ConstAttributeVisitor<std::string> {
700public:
701 explicit AttValue(bool quoteString = false)
702 : IFunction::ConstAttributeVisitor<std::string>(), m_quoteString(quoteString) {}
703
704protected:
706 std::string apply(const std::string &str) const override {
707 return (m_quoteString) ? std::string("\"" + str + "\"") : str;
708 }
710 std::string apply(const int &i) const override { return std::to_string(i); }
712 std::string apply(const double &d) const override { return boost::lexical_cast<std::string>(d); }
714 std::string apply(const bool &b) const override { return b ? "true" : "false"; }
716 std::string apply(const std::vector<double> &v) const override {
717 std::string res = "(";
718 if (!v.empty()) {
719 for (size_t i = 0; i < v.size() - 1; ++i) {
720 res += boost::lexical_cast<std::string>(v[i]) + ",";
721 }
722 res += boost::lexical_cast<std::string>(v.back());
723 }
724 res += ")";
725 return res;
726 }
727
728private:
731};
732} // namespace
733
734std::string IFunction::Attribute::value() const {
735 AttValue tmp(m_quoteValue);
736 return apply(tmp);
737}
738
743 if (m_quoteValue)
744 return asQuotedString();
745
746 try {
747 return boost::get<std::string>(m_data);
748 } catch (...) {
749 throw std::runtime_error("Trying to access a " + type() +
750 " attribute "
751 "as string");
752 }
753}
754
759 std::string attr;
760
761 try {
762 attr = boost::get<std::string>(m_data);
763 } catch (...) {
764 throw std::runtime_error("Trying to access a " + type() +
765 " attribute "
766 "as string");
767 }
768
769 if (attr.empty())
770 return "\"\"";
771
772 std::string quoted(attr);
773 if (*(attr.begin()) != '\"')
774 quoted = "\"" + attr;
775 if (*(quoted.end() - 1) != '\"')
776 quoted += "\"";
777
778 return quoted;
779}
780
785 std::string attr;
786
787 try {
788 attr = boost::get<std::string>(m_data);
789 } catch (...) {
790 throw std::runtime_error("Trying to access a " + type() +
791 " attribute "
792 "as string");
793 }
794 std::string unquoted(attr);
795 if (attr.empty())
796 return "";
797 if (*(attr.begin()) == '\"')
798 unquoted = std::string(attr.begin() + 1, attr.end() - 1);
799 if (*(unquoted.end() - 1) == '\"')
800 unquoted.resize(unquoted.size() - 1);
801
802 return unquoted;
803}
804
809 try {
810 return boost::get<int>(m_data);
811 } catch (...) {
812 throw std::runtime_error("Trying to access a " + type() +
813 " attribute "
814 "as int");
815 }
816}
817
822 try {
823 return boost::get<double>(m_data);
824 } catch (...) {
825 throw std::runtime_error("Trying to access a " + type() +
826 " attribute "
827 "as double");
828 }
829}
830
835 try {
836 return boost::get<bool>(m_data);
837 } catch (...) {
838 throw std::runtime_error("Trying to access a " + type() +
839 " attribute "
840 "as bool");
841 }
842}
843
847std::vector<double> IFunction::Attribute::asVector() const {
848 try {
849 return boost::get<std::vector<double>>(m_data);
850 } catch (...) {
851 throw std::runtime_error("Trying to access a " + type() +
852 " attribute "
853 "as vector");
854 }
855}
856
861void IFunction::Attribute::setString(const std::string &str) {
862 evaluateValidator(str);
863
864 try {
865 boost::get<std::string>(m_data) = str;
866 } catch (...) {
867 throw std::runtime_error("Trying to access a " + type() +
868 " attribute "
869 "as string");
870 }
871}
872
878 evaluateValidator(d);
879
880 try {
881 boost::get<double>(m_data) = d;
882 } catch (...) {
883 throw std::runtime_error("Trying to access a " + type() +
884 " attribute "
885 "as double");
886 }
887}
888
894 evaluateValidator(i);
895
896 try {
897 boost::get<int>(m_data) = i;
898 } catch (...) {
899 throw std::runtime_error("Trying to access a " + type() +
900 " attribute "
901 "as int");
902 }
903}
904
909void IFunction::Attribute::setBool(const bool &b) {
910 evaluateValidator(b);
911
912 try {
913 boost::get<bool>(m_data) = b;
914 } catch (...) {
915 throw std::runtime_error("Trying to access a " + type() +
916 " attribute "
917 "as bool");
918 }
919}
920
926void IFunction::Attribute::setVector(const std::vector<double> &v) {
927 evaluateValidator(v);
928
929 try {
930 auto &data = boost::get<std::vector<double>>(m_data);
931 data.assign(v.begin(), v.end());
932 } catch (...) {
933 throw std::runtime_error("Trying to access a " + type() +
934 " attribute "
935 "as vector");
936 }
937}
938
941 try {
942 return boost::get<std::string>(m_data).empty();
943 } catch (...) {
944 throw std::runtime_error("Trying to access a " + type() + " attribute as string");
945 }
946}
947
948namespace {
952class SetValue : public IFunction::AttributeVisitor<> {
953public:
959 explicit SetValue(std::string value, Mantid::Kernel::IValidator_sptr validator = Mantid::Kernel::IValidator_sptr())
960 : m_value(std::move(value)), m_validator(validator) {}
961
962protected:
964 void apply(std::string &str) const override {
965 evaluateValidator(m_value);
966 str = m_value;
967 }
969 void apply(int &i) const override {
970 int tempi = 0;
971
972 std::istringstream istr(m_value + " ");
973 istr >> tempi;
974 if (!istr.good())
975 throw std::invalid_argument("Failed to set int attribute "
976 "from string " +
977 m_value);
978
979 evaluateValidator(tempi);
980 i = tempi;
981 }
983 void apply(double &d) const override {
984 double tempd = 0;
985
986 std::istringstream istr(m_value + " ");
987 istr >> tempd;
988 if (!istr.good())
989 throw std::invalid_argument("Failed to set double attribute "
990 "from string " +
991 m_value);
992
993 evaluateValidator(tempd);
994 d = tempd;
995 }
997 void apply(bool &b) const override {
998 bool tempb = false;
999
1000 tempb = (m_value == "true" || m_value == "TRUE" || m_value == "1");
1001 evaluateValidator(tempb);
1002
1003 b = (m_value == "true" || m_value == "TRUE" || m_value == "1");
1004 }
1006 void apply(std::vector<double> &v) const override {
1007 if (m_value.empty() || m_value == "EMPTY") {
1008 v.clear();
1009 return;
1010 }
1011 if (m_value.size() > 2) {
1012 // check if the value is in brackets (...)
1013 if (m_value.front() == '(' && m_value.back() == ')') {
1014 m_value.erase(0, 1);
1015 m_value.erase(m_value.size() - 1);
1016 }
1017 }
1018 Kernel::StringTokenizer tokenizer(m_value, ",", Kernel::StringTokenizer::TOK_TRIM);
1019 size_t newSize = tokenizer.count();
1020
1021 // if visitor has an associated validator, first populate temp vec and evaluate against validator.
1022 if (m_validator != nullptr) {
1023 std::vector<double> tempVec(newSize);
1024
1025 for (size_t i = 0; i < tempVec.size(); ++i) {
1026 tempVec[i] = boost::lexical_cast<double>(tokenizer[i]);
1027 }
1028 evaluateValidator(tempVec);
1029 }
1030
1031 v.resize(newSize);
1032 for (size_t i = 0; i < v.size(); ++i) {
1033 v[i] = boost::lexical_cast<double>(tokenizer[i]);
1034 }
1035 }
1036
1038 template <typename T> void evaluateValidator(T &inputData) const {
1039 if (m_validator != nullptr) {
1040 IFunction::ValidatorEvaluator::evaluate(inputData, m_validator);
1041 }
1042 }
1043
1044private:
1045 mutable std::string m_value;
1046 mutable Kernel::IValidator_sptr m_validator;
1047};
1048} // namespace
1049
1053void IFunction::Attribute::fromString(const std::string &str) {
1054 SetValue tmp(str, m_validator);
1055 apply(tmp);
1056}
1057
1062
1067
1070double IFunction::activeParameter(size_t i) const {
1071 if (!isActive(i)) {
1072 throw std::runtime_error("Attempt to use an inactive parameter " + parameterName(i));
1073 }
1074 return getParameter(i);
1075}
1076
1079void IFunction::setActiveParameter(size_t i, double value) {
1080 if (!isActive(i)) {
1081 throw std::runtime_error("Attempt to use an inactive parameter " + parameterName(i));
1082 }
1083 setParameter(i, value);
1084}
1085
1090std::string IFunction::nameOfActive(size_t i) const {
1091 if (!isActive(i)) {
1092 throw std::runtime_error("Attempt to use an inactive parameter " + parameterName(i));
1093 }
1094 return parameterName(i);
1095}
1096
1101std::string IFunction::descriptionOfActive(size_t i) const {
1102 if (!isActive(i)) {
1103 throw std::runtime_error("Attempt to use an inactive parameter " + parameterName(i));
1104 }
1105 return parameterDescription(i);
1106}
1107
1114 /*
1115 * There is a similar more specialized method for 1D functions in IFunction1D
1116 * but the method takes different parameters and uses slightly different
1117 * function calls in places making it difficult to share code. Please also
1118 * consider that method when updating this.
1119 */
1120
1121 const size_t nParam = nParams();
1122 size_t nData = getValuesSize(domain);
1123
1124 FunctionValues minusStep(nData);
1125 FunctionValues plusStep(nData);
1126
1127 applyTies(); // just in case
1128 function(domain, minusStep);
1129
1130 if (nData == 0) {
1131 nData = minusStep.size();
1132 }
1133
1134 double step;
1135 for (size_t iP = 0; iP < nParam; iP++) {
1136 if (isActive(iP)) {
1137 const double val = activeParameter(iP);
1138 step = calculateStepSize(iP, val);
1139
1140 const double paramPstep = val + step;
1141 setActiveParameter(iP, paramPstep);
1142 applyTies();
1143 function(domain, plusStep);
1144 setActiveParameter(iP, val);
1145 applyTies();
1146
1147 step = paramPstep - val;
1148 for (size_t i = 0; i < nData; i++) {
1149 jacobian.set(i, iP, (plusStep.getCalculated(i) - minusStep.getCalculated(i)) / step);
1150 }
1151 }
1152 }
1153}
1154
1160double IFunction::calculateStepSize(const size_t parameterIndex, const double parameterValue) const {
1161 switch (m_stepSizeMethod) {
1163 return defaultStepSize(parameterValue);
1165 return sqrtEpsilonStepSize(parameterValue);
1167 return m_stepSizes.at(parameterIndex);
1168 }
1169 throw std::invalid_argument("An invalid method for calculating the step size was provided.");
1170}
1171
1176
1183void IFunction::setMatrixWorkspace(std::shared_ptr<const API::MatrixWorkspace> workspace, size_t wi, double startX,
1184 double endX) {
1185 UNUSED_ARG(startX);
1186 UNUSED_ARG(endX);
1187
1188 if (!workspace)
1189 return; // unset the workspace
1190
1191 try {
1192
1193 // check if parameter are specified in instrument definition file
1194
1195 // Note JZ oct 2011 - I'm not sure why the code uses the first detector
1196 // and not the group. Ask Roman.
1197 // Note RB oct 2026 - Roman was not asked. And now, he never will be.
1198 const auto &specDef = workspace->spectrumInfo().spectrumDefinition(wi);
1199 if (specDef.size() == 0) {
1200 g_log.information() << "MatrixWorkspace has not been set for index: " << std::to_string(wi)
1201 << " as no detector ids can be found for this workspace on the instrument\n";
1202 return;
1203 }
1204 // Detector indices in ComponentInfo match those in the SpectrumDefinition
1205 const auto &componentInfo = workspace->componentInfo();
1206 const auto &paramInfo = *(componentInfo.sharedParameterInfo());
1207 const auto detIndex = specDef[0].first;
1208
1209 for (size_t i = 0; i < nParams(); i++) {
1210 if (!isExplicitlySet(i)) {
1211 // Use the fitting-function-aware lookup: two functions on the same component can declare a
1212 // parameter with the same short name (e.g. Bk2BkExpConvPV:Gamma and IkedaCarpenterPV:Gamma).
1213 // The plain getRecursive() short-circuits on the first match and would pick the wrong one.
1215 paramInfo.getRecursiveFittingParameter(componentInfo, detIndex, parameterName(i), this->name());
1216 if (!param) {
1217 // Fall back for IDFs that omit the function prefix (no embedded function name to match).
1218 param = paramInfo.getRecursive(componentInfo, detIndex, parameterName(i), "fitting");
1219 }
1220 if (param != Geometry::Parameter_sptr()) {
1221 // get FitParameter
1222 const auto &fitParam = param->value<Geometry::FitParameter>();
1223
1224 // check first if this parameter is actually specified for this
1225 // function
1226 if (name() == fitParam.getFunction()) {
1227 // update value
1228 const auto *testWithLocation = dynamic_cast<IFunctionWithLocation *>(this);
1229 if (testWithLocation == nullptr ||
1230 (!fitParam.getLookUpTable().containData() && fitParam.getFormula().empty())) {
1231 setParameter(i, fitParam.getValue());
1232 } else {
1233 double centreValue = testWithLocation->centre();
1234 Kernel::Unit_sptr centreUnit; // unit of value used in formula or
1235 // to look up value in lookup table
1236 if (fitParam.getFormula().empty())
1237 centreUnit = fitParam.getLookUpTable().getXUnit(); // from table
1238 else {
1239 if (!fitParam.getFormulaUnit().empty()) {
1240 try {
1241 centreUnit = Kernel::UnitFactory::Instance().create(fitParam.getFormulaUnit()); // from formula
1242 } catch (...) {
1243 g_log.warning() << fitParam.getFormulaUnit() << " Is not an recognised formula unit for parameter "
1244 << fitParam.getName() << "\n";
1245 }
1246 }
1247 }
1248
1249 // if unit specified convert centre value to unit required by
1250 // formula or look-up-table
1251 if (centreUnit) {
1252 g_log.debug() << "For FitParameter " << parameterName(i)
1253 << " centre of peak before any unit conversion is " << centreValue << '\n';
1254 centreValue = convertValue(centreValue, centreUnit, workspace, wi);
1255 g_log.debug() << "For FitParameter " << parameterName(i)
1256 << " centre of peak after any unit conversion is " << centreValue << '\n';
1257 }
1258
1259 double paramValue = fitParam.getValue(centreValue);
1260
1261 // this returned param value by a formula or a look-up-table may
1262 // have
1263 // a unit of its own. If set convert param value
1264 // See section 'Using fitting parameters in
1265 // docs/source/concepts/InstrumentDefinitionFile.rst
1266 if (fitParam.getFormula().empty()) {
1267 // so from look up table
1268 Kernel::Unit_sptr resultUnit = fitParam.getLookUpTable().getYUnit(); // from table
1269 g_log.debug() << "The FitParameter " << parameterName(i) << " = " << paramValue
1270 << " before y-unit conversion\n";
1271 paramValue /= convertValue(1.0, resultUnit, workspace, wi);
1272 g_log.debug() << "The FitParameter " << parameterName(i) << " = " << paramValue
1273 << " after y-unit conversion\n";
1274 } else {
1275 // so from formula
1276
1277 std::string resultUnitStr = fitParam.getResultUnit();
1278
1279 if (!resultUnitStr.empty()) {
1280 std::vector<std::string> allUnitStr = Kernel::UnitFactory::Instance().getKeys();
1281 for (auto &iUnit : allUnitStr) {
1282 size_t found = resultUnitStr.find(iUnit);
1283 if (found != std::string::npos) {
1284 size_t len = iUnit.size();
1285 std::stringstream readDouble;
1286 Kernel::Unit_sptr unt = Kernel::UnitFactory::Instance().create(iUnit);
1287 readDouble << 1.0 / convertValue(1.0, unt, workspace, wi);
1288 resultUnitStr.replace(found, len, readDouble.str());
1289 }
1290 } // end for
1291
1292 try {
1293 mu::Parser p;
1294 p.SetExpr(resultUnitStr);
1295 g_log.debug() << "The FitParameter " << parameterName(i) << " = " << paramValue
1296 << " before result-unit conversion (using " << resultUnitStr << ")\n";
1297 paramValue *= p.Eval();
1298 g_log.debug() << "The FitParameter " << parameterName(i) << " = " << paramValue
1299 << " after result-unit conversion\n";
1300 } catch (mu::Parser::exception_type &e) {
1301 g_log.error() << "Cannot convert formula unit to workspace unit"
1302 << " Formula unit which cannot be passed is " << resultUnitStr
1303 << ". Muparser error message is: " << e.GetMsg() << '\n';
1304 }
1305 } // end if
1306 } // end trying to convert result-unit from formula or y-unit for
1307 // lookuptable
1308
1309 setParameter(i, paramValue);
1310 } // end of update parameter value
1311
1312 // add tie if specified for this parameter in instrument definition
1313 // file
1314 if (!fitParam.getTie().empty()) {
1315 std::ostringstream str;
1316 str << getParameter(i);
1317 tie(parameterName(i), str.str());
1318 }
1319
1320 // add constraint if specified for this parameter in instrument
1321 // definition file
1322 if (!fitParam.getConstraint().empty()) {
1323 IConstraint *constraint = ConstraintFactory::Instance().createInitialized(this, fitParam.getConstraint());
1324 if (!fitParam.getConstraintPenaltyFactor().empty()) {
1325 try {
1326 double penalty = std::stod(fitParam.getConstraintPenaltyFactor());
1327 constraint->setPenaltyFactor(penalty);
1328 } catch (...) {
1329 g_log.warning() << "Can't set penalty factor for constraint\n";
1330 }
1331 }
1332 addConstraint(std::unique_ptr<IConstraint>(constraint));
1333 }
1334 }
1335 }
1336 }
1337 }
1338 } catch (...) {
1339 }
1340}
1341
1351 const std::shared_ptr<const MatrixWorkspace> &ws, size_t wsIndex) const {
1352 // only required if formula or look-up-table different from ws unit
1353 const auto &wsUnit = ws->getAxis(0)->unit();
1354 if (outUnit->unitID() == wsUnit->unitID())
1355 return value;
1356
1357 // first check if it is possible to do a quick conversion and convert
1358 // slight duplication to below to avoid instantiating vector unless necessary
1359 double factor(0.0), power(0.0);
1360 if (wsUnit->quickConversion(*outUnit, factor, power)) {
1361 return factor * std::pow(value, power);
1362 } else {
1363 std::vector<double> singleValue(1, value);
1364 convertValue(singleValue, outUnit, ws, wsIndex);
1365 return singleValue.front();
1366 }
1367}
1368
1377void IFunction::convertValue(std::vector<double> &values, Kernel::Unit_sptr &outUnit,
1378 const std::shared_ptr<const MatrixWorkspace> &ws, size_t wsIndex) const {
1379 // only required if formula or look-up-table different from ws unit
1380 const auto &wsUnit = ws->getAxis(0)->unit();
1381 if (outUnit->unitID() == wsUnit->unitID())
1382 return;
1383
1384 // first check if it is possible to do a quick conversion convert
1385 double factor, power;
1386 if (wsUnit->quickConversion(*outUnit, factor, power)) {
1387 auto iend = values.end();
1388 for (auto itr = values.begin(); itr != iend; ++itr)
1389 (*itr) = factor * std::pow(*itr, power);
1390 } else {
1391 // Get l1, l2 and theta (see also RemoveBins.calculateDetectorPosition())
1392 Instrument_const_sptr instrument = ws->getInstrument();
1393 Geometry::IComponent_const_sptr sample = instrument->getSample();
1394 if (sample == nullptr) {
1395 g_log.error() << "No sample defined instrument. Cannot convert units for function\n"
1396 << "Ignore conversion.";
1397 return;
1398 }
1399 const auto &spectrumInfo = ws->spectrumInfo();
1400 double l1 = spectrumInfo.l1();
1401 // If this is a monitor then l1+l2 = source-detector distance and twoTheta=0
1402 auto emode = ws->getEMode();
1403
1405 spectrumInfo.getDetectorValues(*wsUnit, *outUnit, emode, false, wsIndex, pmap);
1406 try {
1407 std::vector<double> emptyVec;
1408 wsUnit->toTOF(values, emptyVec, l1, emode, pmap);
1409 outUnit->fromTOF(values, emptyVec, l1, emode, pmap);
1410 } catch (std::exception &) {
1411 throw std::runtime_error("Unable to perform unit conversion to " + outUnit->unitID());
1412 }
1413 }
1414}
1415
1419size_t IFunction::nAttributes() const { return m_attrs.size(); }
1420
1422bool IFunction::hasAttribute(const std::string &name) const { return m_attrs.find(name) != m_attrs.end(); }
1423
1429void IFunction::setAttributeValue(const std::string &attName, const char *value) {
1430 std::string str(value);
1431 setAttributeValue(attName, str);
1432}
1433
1439void IFunction::setAttributeValue(const std::string &attName, const std::string &value) {
1440 Attribute att = getAttribute(attName);
1441 att.setString(value);
1442 setAttribute(attName, att);
1443}
1444
1447 throw std::runtime_error("Function " + name() + " doesn't have children.");
1448}
1449
1451std::vector<std::string> IFunction::getAttributeNames() const {
1452 std::vector<std::string> names;
1453 names.reserve(nAttributes());
1454 for (size_t i = 0; i < nAttributes(); ++i) {
1455 names.emplace_back(attributeName(i));
1456 }
1457 return names;
1458}
1459
1465std::string IFunction::attributeName(size_t index) const {
1466 if (index >= nAttributes()) {
1467 throw std::out_of_range("Function attribute index out of range.");
1468 }
1469 auto itr = std::next(m_attrs.begin(), index);
1470 return itr->first;
1471}
1472
1478 if (hasAttribute(name)) {
1479 return m_attrs.at(name);
1480 } else {
1481 throw std::invalid_argument("ParamFunctionAttributeHolder::getAttribute - Unknown attribute '" + name + "'");
1482 }
1483}
1484
1495
1501void IFunction::declareAttribute(const std::string &name, const API::IFunction::Attribute &defaultValue) {
1503
1504 m_attrs.emplace(name, defaultValue);
1505}
1506
1513void IFunction::declareAttribute(const std::string &name, const API::IFunction::Attribute &defaultValue,
1514 const Kernel::IValidator &validator) {
1515 const Kernel::IValidator_sptr validatorClone = validator.clone();
1517
1518 defaultValue.setValidator(validatorClone);
1519 defaultValue.evaluateValidator();
1520
1521 m_attrs.emplace(name, defaultValue);
1522}
1523
1528void IFunction::checkAttributeName(const std::string &name) {
1529 if (m_attrs.find(name) != m_attrs.end()) {
1530 std::ostringstream msg;
1531 msg << "Attribute (" << name << ") already exists.";
1532 throw std::invalid_argument(msg.str());
1533 }
1534}
1535
1541
1548 if (hasAttribute(name)) {
1549 auto att = m_attrs[name];
1550 const Kernel::IValidator_sptr validatorClone = att.getValidator();
1551 value.setValidator(validatorClone);
1552 value.evaluateValidator();
1553
1554 m_attrs[name] = value;
1555 } else {
1556 throw std::invalid_argument("ParamFunctionAttributeHolder::setAttribute - Unknown attribute '" + name + "'");
1557 }
1558}
1559
1567 const_cast<IFunction *>(this)->storeAttributeValue(name, value);
1568}
1569
1579void IFunction::setCovarianceMatrix(const std::shared_ptr<Kernel::Matrix<double>> &covar) {
1580 // the matrix shouldn't be empty
1581 if (!covar) {
1582 throw std::invalid_argument("IFunction: Cannot set an empty covariance matrix");
1583 }
1584 // the matrix should relate to this function
1585 if (covar->numRows() != nParams() || covar->numCols() != nParams()) {
1586 throw std::invalid_argument("IFunction: Covariance matrix has a wrong size");
1587 }
1588 m_covar = covar;
1589}
1590
1593size_t IFunction::getValuesSize(const FunctionDomain &domain) const { return domain.size(); }
1594
1598void IFunction::fixParameter(const std::string &name, bool isDefault) {
1599 auto i = parameterIndex(name);
1600 fix(i, isDefault);
1601}
1602
1605void IFunction::unfixParameter(const std::string &name) {
1606 auto i = parameterIndex(name);
1607 unfix(i);
1608}
1609
1612void IFunction::fixAll(bool isDefault) {
1613 for (size_t i = 0; i < nParams(); ++i) {
1614 if (isActive(i)) {
1615 fix(i, isDefault);
1616 }
1617 }
1618}
1619
1622 for (size_t i = 0; i < nParams(); ++i) {
1623 if (isFixed(i)) {
1624 unfix(i);
1625 }
1626 }
1627}
1628
1631 for (size_t i = 0; i < nParams(); ++i) {
1633 unfix(i);
1634 }
1635 }
1636}
1637
1643void IFunction::fixAllActive(bool isDefault) {
1644 for (size_t i = 0; i < nParams(); ++i) {
1645 if (getParameterStatus(i) == Active) {
1646 fix(i, isDefault);
1647 }
1648 }
1649}
1650
1655size_t IFunction::getNumberDomains() const { return 1; }
1656
1662std::vector<IFunction_sptr> IFunction::createEquivalentFunctions() const {
1663 return std::vector<IFunction_sptr>(1, FunctionFactory::Instance().createInitialized(asString()));
1664}
1665
1669void IFunction::sortTies(const bool checkOnly) {
1670 if (!checkOnly) {
1671 m_orderedTies.clear();
1672 }
1673
1674 std::list<TieNode> orderedTieNodes;
1675 for (size_t i = 0; i < nParams(); ++i) {
1676 auto const parTie = getTie(i);
1677 if (!parTie || ignoreTie(*parTie)) {
1678 continue;
1679 }
1680
1681 TieNode newNode;
1682 newNode.left = getParameterIndex(*parTie);
1683 auto const rhsParameters = parTie->getRHSParameters();
1684 newNode.right.reserve(rhsParameters.size());
1685 for (auto &&p : rhsParameters) {
1686 newNode.right.emplace_back(this->getParameterIndex(p));
1687 }
1688 if (newNode < newNode) {
1689 throw std::runtime_error("Parameter is tied to itself: " + parTie->asString(this));
1690 }
1691 bool before(false), after(false);
1692 size_t indexBefore(0), indexAfter(0);
1693 for (auto &&node : orderedTieNodes) {
1694 if (newNode < node) {
1695 before = true;
1696 indexBefore = node.left;
1697 }
1698 if (node < newNode) {
1699 after = true;
1700 indexAfter = node.left;
1701 }
1702 }
1703 if (before) {
1704 if (after) {
1705 std::string message = "Circular dependency in ties:\n" + parTie->asString(this) + '\n';
1706 message += getTie(indexBefore)->asString(this);
1707 if (indexAfter != indexBefore) {
1708 message += '\n' + getTie(indexAfter)->asString(this);
1709 }
1710 throw std::runtime_error(message);
1711 }
1712 orderedTieNodes.push_front(newNode);
1713 } else {
1714 orderedTieNodes.emplace_back(newNode);
1715 }
1716 }
1717 if (!checkOnly) {
1718 for (auto &&node : orderedTieNodes) {
1719 auto const parTie = getTie(node.left);
1720 m_orderedTies.emplace_back(parTie);
1721 }
1722 }
1723}
1724
1725} // namespace Mantid::API
1726
1728namespace Mantid::Kernel {
1729
1730template <>
1731MANTID_API_DLL std::shared_ptr<Mantid::API::IFunction>
1732IPropertyManager::getValue<std::shared_ptr<Mantid::API::IFunction>>(const std::string &name) const {
1733 auto *prop = dynamic_cast<PropertyWithValue<std::shared_ptr<Mantid::API::IFunction>> *>(getPointerToProperty(name));
1734 if (prop) {
1735 return *prop;
1736 } else {
1737 std::string message = "Attempt to assign property " + name + " to incorrect type. Expected shared_ptr<IFunction>.";
1738 throw std::runtime_error(message);
1739 }
1740}
1741
1742template <>
1743MANTID_API_DLL std::shared_ptr<const Mantid::API::IFunction>
1744IPropertyManager::getValue<std::shared_ptr<const Mantid::API::IFunction>>(const std::string &name) const {
1745 const auto *prop =
1746 dynamic_cast<PropertyWithValue<std::shared_ptr<Mantid::API::IFunction>> *>(getPointerToProperty(name));
1747 if (prop) {
1748 return prop->operator()();
1749 } else {
1750 std::string message =
1751 "Attempt to assign property " + name + " to incorrect type. Expected const shared_ptr<IFunction>.";
1752 throw std::runtime_error(message);
1753 }
1754}
1755
1756} // namespace Mantid::Kernel
const std::string & m_value
Definition Algorithm.cpp:72
Kernel::IValidator_sptr m_validator
bool m_quoteString
Flag to quote a string value returned.
std::string name
Definition Run.cpp:60
gsl_vector * tmp
double value
The value of the point.
Definition FitMW.cpp:51
double error
IPeaksWorkspace_sptr workspace
std::map< DeltaEMode::Type, std::string > index
const double EPSILON(1.0E-10)
double left
double right
#define fabs(x)
Definition Matrix.cpp:22
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition System.h:44
const std::vector< Type > & m_data
This class represents an expression made up of names, binary operators and brackets.
Definition Expression.h:36
void parse(const std::string &str)
Parse a string and create an expression.
iterator end() const
An iterator pointing to the end of the expressions.
Definition Expression.h:86
iterator begin() const
An iterator pointing to the start of the expressions.
Definition Expression.h:84
void toList(const std::string &sep=",")
Make sure the expression is a list of expression separated by sep, eg "term1,term2,...
Base class that represents the domain of a function.
virtual size_t size() const =0
Return the number of points in the domain.
A class to store values calculated by a function.
size_t size() const
Return the number of values.
double getCalculated(size_t i) const
Get i-th calculated value.
An interface to a constraint.
Definition IConstraint.h:26
virtual void setPenaltyFactor(const double &c)=0
set the penalty factor for the constraint Set panelty factor.
An interface to a function with location, which here means a function for which the user may ask what...
Atribute validator visitor class.
Definition IFunction.h:381
Attribute is a non-fitting parameter.
Definition IFunction.h:286
std::string asUnquotedString() const
Returns a string value that is guarenteed to be unquoted.
void setString(const std::string &str)
Sets new value if attribute is a string.
std::vector< double > asVector() const
Returns vector<double> if attribute is vector<double>, throws exception otherwise.
int asInt() const
Returns int value if attribute is a int, throws exception otherwise.
void evaluateValidator() const
Evaluates the validator associated with this attribute. Returns error as a string.
std::string asString() const
Returns string value if attribute is a string, throws exception otherwise.
void setVector(const std::vector< double > &)
Sets new value if attribute is a vector.
T apply(AttributeVisitor< T > &v)
Apply an attribute visitor.
Definition IFunction.h:304
void setDouble(const double &)
Sets new value if attribute is a double.
std::string asQuotedString() const
Returns a string value that is guarenteed to be quoted for use in places where the string is used as ...
void setValidator(const Kernel::IValidator_sptr &validator) const
Set validator to enforce limits on attribute value.
std::string value() const
Returns the attribute value as a string.
void setBool(const bool &)
Sets new value if attribute is a bool.
void fromString(const std::string &str)
Set value from a string.
double asDouble() const
Returns double value if attribute is a double, throws exception otherwise.
bool isEmpty() const
Check if a string attribute is empty.
void setInt(const int &)
Sets new value if attribute is a int.
bool asBool() const
Returns bool value if attribute is a bool, throws exception otherwise.
std::string type() const
Returns type of the attribute.
Const version of AttributeVisitor.
Definition IFunction.h:245
This is an interface to a fitting function - a semi-abstarct class.
Definition IFunction.h:167
virtual void functionDeriv(const FunctionDomain &domain, Jacobian &jacobian)
Derivatives of function with respect to active parameters.
bool hasOrderedTies() const
virtual std::string descriptionOfActive(size_t i) const
Returns the name of active parameter i.
virtual size_t nParams() const =0
Total number of parameters.
void sortTies(const bool checkOnly=false)
Put all ties in order in which they will be applied correctly.
virtual void removeConstraint(const std::string &parName)
Remove a constraint.
bool isActive(size_t i) const
Check if an active parameter i is actually active.
std::string writeTies() const
Write a parameter tie to a string.
void unfixParameter(const std::string &name)
Free a parameter.
virtual Attribute getAttribute(const std::string &name) const
Return a value of attribute attName.
void setProgressReporter(std::shared_ptr< Kernel::ProgressBase > reporter)
Attach a progress reporter.
IFunction()
Constructor.
Definition IFunction.cpp:88
virtual double getParameter(size_t i) const =0
Get i-th parameter.
double convertValue(double value, Kernel::Unit_sptr &outUnit, const std::shared_ptr< const MatrixWorkspace > &ws, size_t wsIndex) const
Convert a value from one unit (inUnit) to unit defined in workspace (ws)
virtual void clearTies()
Remove all ties.
virtual void clearConstraints()
Remove all constraints.
virtual ~IFunction()
Virtual destructor.
Definition IFunction.cpp:93
std::vector< double > m_stepSizes
The custom step sizes for the derivative.
Definition IFunction.h:739
void declareAttribute(const std::string &name, const API::IFunction::Attribute &defaultValue)
Declare a single attribute.
virtual std::shared_ptr< IFunction > clone() const
Virtual copy constructor.
void setHandler(std::unique_ptr< FunctionHandler > handler)
Set a function handler.
void storeReadOnlyAttribute(const std::string &name, const API::IFunction::Attribute &value) const
A read-only ("mutable") attribute can be stored in a const method.
double calculateStepSize(size_t parameterIndex, double parameterValue) const
Calculate step size for the given parameter value.
virtual void tie(const std::string &parName, const std::string &expr, bool isDefault=false)
Tie a parameter to other parameters (or a constant)
std::map< std::string, API::IFunction::Attribute > m_attrs
The declared attributes.
Definition IFunction.h:723
virtual void declareAttributes()
Override to declare function attributes.
Definition IFunction.h:685
virtual ParameterStatus getParameterStatus(size_t i) const =0
Get status of parameter.
virtual void setMatrixWorkspace(std::shared_ptr< const API::MatrixWorkspace > workspace, size_t wi, double startX, double endX)
Set matrix workspace.
virtual void setParameter(size_t, const double &value, bool explicitlySet=true)=0
Set i-th parameter.
virtual void applyTies()
Apply the ties.
void checkAttributeName(const std::string &name)
Check Attribute to declare does not already exist.
virtual ParameterTie * getTie(size_t i) const
Get the tie of i-th parameter.
virtual void setStepSizeMethod(const StepSizeMethod method)
Sets the StepSizeMethod to use when calculation the step size.
virtual const std::string category() const
The categories the Fit function belong to.
Definition IFunction.h:444
virtual const std::string categorySeparator() const
Function to return the sperator token for the category string.
Definition IFunction.h:449
virtual std::string writeToString(const std::string &parentLocalAttributesStr="") const
Writes itself into a string.
virtual void setAttribute(const std::string &name, const Attribute &)
Set a value to attribute attName.
void unfixAllDefault()
Free all parameters fixed by default.
virtual size_t getValuesSize(const FunctionDomain &domain) const
Get number of values for a given domain.
virtual std::string nameOfActive(size_t i) const
Returns the name of active parameter i.
void fixAllActive(bool isDefault=false)
Fix all active parameters.
bool cancellationRequestReceived() const
Returns true if a progress reporter is set & evalaution has been requested to stop.
virtual double activeParameter(size_t i) const
Value of i-th active parameter.
virtual size_t getParameterIndex(const ParameterReference &ref) const =0
Return parameter index from a parameter reference.
std::pair< std::size_t, std::string > insertTie(std::unique_ptr< ParameterTie > tie)
Insert a new tie to the correct position.
virtual void setUpForFit()
Set up the function for a fit.
virtual const std::vector< std::string > categories() const
Function to return all of the categories that contain this algorithm.
virtual std::string parameterDescription(size_t i) const =0
Returns the description of parameter i.
void fixParameter(const std::string &name, bool isDefault=false)
Fix a parameter.
virtual std::vector< std::string > getAttributeNames() const
Returns a list of attribute names.
virtual std::string attributeName(size_t index) const
Get name of ith attribute.
void reportProgress(const std::string &msg="") const
Reports progress with an optional message.
virtual void setConstraintPenaltyFactor(const std::string &parName, const double &c)
Set a constraint penalty.
std::vector< ParameterTie * > m_orderedTies
Ties ordered in order of correct application.
Definition IFunction.h:733
virtual void addTies(const std::string &ties, bool isDefault=false)
Add several ties.
std::string asString() const
Writes itself into a string.
void unfix(size_t i)
Restores a declared parameter i to the active status.
virtual std::string parameterName(size_t i) const =0
Returns the name of parameter i.
virtual std::string name() const =0
Returns the function's name.
void setCovarianceMatrix(const std::shared_ptr< Kernel::Matrix< double > > &covar)
Set the covariance matrix.
std::vector< std::unique_ptr< ParameterTie > > m_ties
Holds parameter ties.
Definition IFunction.h:729
void calNumericalDeriv(const FunctionDomain &domain, Jacobian &jacobian)
Calculate numerical derivatives.
std::shared_ptr< Kernel::ProgressBase > m_progReporter
Pointer to the progress handler.
Definition IFunction.h:719
std::vector< std::unique_ptr< IConstraint > > m_constraints
Holds the constraints added to function.
Definition IFunction.h:731
virtual bool hasAttribute(const std::string &name) const
Check if attribute attName exists.
void unfixAll()
Free all parameters.
StepSizeMethod m_stepSizeMethod
The method used to calculate the step size.
Definition IFunction.h:737
virtual void setParameterStatus(size_t i, ParameterStatus status)=0
Change status of parameter.
virtual std::shared_ptr< IFunction > getFunction(size_t i) const
Returns the pointer to i-th child function.
virtual void addTie(std::unique_ptr< ParameterTie > tie)
Add a new tie. Derived classes must provide storage for ties.
virtual std::vector< std::shared_ptr< IFunction > > createEquivalentFunctions() const
Split this function (if needed) into a list of independent functions.
void setCustomStepSizes(const std::vector< double > &stepSizes)
Sets the custom step sizes.
virtual void addConstraints(const std::string &str, bool isDefault=false)
Add a list of conatraints from a string.
void fixAll(bool isDefault=false)
Fix all parameters.
virtual void function(const FunctionDomain &domain, FunctionValues &values) const =0
Evaluates the function for all arguments in the domain.
virtual void registerFunctionUsage(bool internal)
Registers the usage of the algorithm with the UsageService.
Definition IFunction.cpp:98
virtual size_t parameterIndex(const std::string &name) const =0
Returns the index of parameter name.
std::string writeConstraints() const
Write a parameter constraint to a string.
void setAttributeValue(const std::string &attName, const T &value)
Set an attribute value.
Definition IFunction.h:602
virtual void removeTie(const std::string &parName)
Removes the tie off a parameter.
virtual double getError(size_t i) const =0
Get the fitting error for a parameter.
void storeAttributeValue(const std::string &name, const API::IFunction::Attribute &value)
Store an attribute's value.
virtual void init()
Function initialization. Declare function parameters in this method.
bool isFixedByDefault(size_t i) const
Check if a parameter i is fixed by default (not by user).
std::unique_ptr< ParameterTie > createAndProcessTie(const std::string &parName, const std::string &expr, bool isDefault)
Creates and processes a single tie, handling constant expressions and validation.
virtual void declareParameters()
Override to declare function parameters.
Definition IFunction.h:687
std::vector< std::string > getParameterNames() const
Return a vector with all parameter names.
virtual bool ignoreTie(const ParameterTie &) const
Ignore a tie.
Definition IFunction.h:562
void fix(size_t i, bool isDefault=false)
Removes a parameter i from the list of active.
bool isFixed(size_t i) const
Check if a parameter i is fixed.
virtual void setActiveParameter(size_t i, double value)
Set new value of i-th active parameter.
virtual void addConstraint(std::unique_ptr< IConstraint > ic)
Add a constraint to function.
virtual size_t nAttributes() const
Returns the number of attributes associated with the function.
virtual bool isExplicitlySet(size_t i) const =0
Checks if a parameter has been set explicitly.
virtual IConstraint * getConstraint(size_t i) const
Get constraint of i-th parameter.
std::unique_ptr< FunctionHandler > m_handler
Pointer to a function handler.
Definition IFunction.h:716
virtual size_t getNumberDomains() const
Get number of domains required by this function.
StepSizeMethod
Describes the method in which the step size will be calculated: DEFAULT: Uses the traditional Mantid ...
Definition IFunction.h:665
bool m_isRegistered
whether the function usage has been registered
Definition IFunction.h:735
std::shared_ptr< Kernel::Matrix< double > > m_covar
The covariance matrix of the fitting parameters.
Definition IFunction.h:725
Represents the Jacobian in IFitFunction::functionDeriv.
Definition Jacobian.h:22
virtual void set(size_t iY, size_t iP, double value)=0
Set a value to a Jacobian matrix element.
Ties fitting parameters.
std::string asString(const IFunction *fun=nullptr) const
Return the string that can be used to recreate this tie.
Used to find ParameterTie for a parameter i.
const IFunction & m_fun
The function that has the tie.
bool operator()(const std::unique_ptr< T > &p)
Bracket operator.
ReferenceEqual(const IFunction &fun, size_t i)
Constructor.
const size_t m_i
index to find
Store information about a fitting parameter such as its value if it is constrained or tied.
IValidator is the basic interface for all validators for properties.
Definition IValidator.h:37
virtual IValidator_sptr clone() const =0
Make a copy of the present type of validator.
void debug(const std::string &msg)
Logs at debug level.
Definition Logger.cpp:145
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 information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
Numerical Matrix class.
Definition Matrix.h:41
virtual bool hasCancellationBeenRequested() const
Override so that the reporter can inform whether a cancellation request has been used.
The concrete, templated class for properties.
@ TOK_IGNORE_EMPTY
ignore empty tokens
@ TOK_TRIM
remove leading and trailing whitespace from tokens
const TokenVec & asVector()
Returns a vector of tokenized strings.
std::size_t count() const
Get the total number of tokens.
MANTID_API_DLL std::ostream & operator<<(std::ostream &, const AlgorithmHistory &)
Prints a text representation.
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
Definition IFunction.h:749
Mantid::Kernel::StringTokenizer tokenizer
std::shared_ptr< Parameter > Parameter_sptr
Typedef for the shared pointer.
Definition Parameter.h:203
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
Definition IComponent.h:165
bool operator<(const TrackDirection left, const TrackDirection right)
Definition Track.h:93
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
std::string join(ITERATOR_TYPE begin, ITERATOR_TYPE end, const std::string &separator, typename std::enable_if<!(std::is_same< typename std::iterator_traits< ITERATOR_TYPE >::iterator_category, std::random_access_iterator_tag >::value)>::type *=nullptr)
Join a set or vector of (something that turns into a string) together into one string,...
Definition Strings.h:84
std::unordered_map< UnitParams, double > UnitParametersMap
Definition Unit.h:29
std::shared_ptr< Unit > Unit_sptr
Shared pointer to the Unit base class.
Definition Unit_fwd.h:17
std::shared_ptr< IValidator > IValidator_sptr
A shared_ptr to an IValidator.
Generate a tableworkspace to store the calibration results.
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)