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"
28#include "MantidKernel/Logger.h"
34
35#include <boost/lexical_cast.hpp>
36
38
39#include <algorithm>
40#include <limits>
41#include <sstream>
42#include <utility>
43
44namespace {
45
46constexpr double EPSILON = std::numeric_limits<double>::epsilon();
47constexpr double MIN_DOUBLE = std::numeric_limits<double>::min();
48constexpr double STEP_PERCENTAGE = 0.001;
49
50const auto defaultStepSize = [](const double parameterValue) -> double {
51 return fabs(parameterValue) < 100.0 * MIN_DOUBLE / STEP_PERCENTAGE ? 100.0 * EPSILON
52 : parameterValue * STEP_PERCENTAGE;
53};
54
55const auto sqrtEpsilonStepSize = [](const double parameterValue) -> double {
56 return fabs(parameterValue) < 1 ? sqrt(EPSILON) : parameterValue * sqrt(EPSILON);
57};
58
59} // namespace
60
61namespace Mantid::API {
62using namespace Geometry;
63
64namespace {
66Kernel::Logger g_log("IFunction");
67
69struct TieNode {
70 // Index of the tied parameter
71 size_t left;
72 // Indices of parameters on the right-hand-side of the expression
73 std::vector<size_t> right;
74 // This tie must be applied before the other if the RHS of the other
75 // contains this (left) parameter.
76 bool operator<(TieNode const &other) const {
77 return std::find(other.right.begin(), other.right.end(), left) != other.right.end();
78 }
79};
80const std::vector<std::string> EXCLUDEUSAGE = {"CompositeFunction"};
81} // namespace
82
86IFunction ::IFunction() : m_isParallel(false), m_handler(nullptr), m_chiSquared(0.0) {}
87
92
97 if (!Kernel::UsageService::Instance().isEnabled()) {
98 return;
99 }
100 if (std::find(EXCLUDEUSAGE.cbegin(), EXCLUDEUSAGE.cend(), name()) == EXCLUDEUSAGE.cend() && !m_isRegistered) {
101 m_isRegistered = true;
102 Kernel::UsageService::Instance().registerFeatureUsage(Kernel::FeatureType::Function, name(), internal);
103 }
104}
108std::shared_ptr<IFunction> IFunction::clone() const {
109 auto clonedFunction = FunctionFactory::Instance().createInitialized(this->asString());
110 for (size_t i = 0; i < this->nParams(); i++) {
111 double error = this->getError(i);
112 clonedFunction->setError(i, error);
113 }
114 return clonedFunction;
115}
116
122void IFunction::setProgressReporter(std::shared_ptr<Kernel::ProgressBase> reporter) {
123 m_progReporter = std::move(reporter);
124 m_progReporter->setNotifyStep(0.01);
125}
126
131void IFunction::setCustomStepSizes(const std::vector<double> &stepSizes) { m_stepSizes = stepSizes; }
132
137void IFunction::reportProgress(const std::string &msg) const {
138 if (m_progReporter) {
139 const_cast<Kernel::ProgressBase *>(m_progReporter.get())->report(msg);
140 }
141}
142
149 if (m_progReporter)
151 else
152 return false;
153}
154
160void IFunction::functionDeriv(const FunctionDomain &domain, Jacobian &jacobian) { calNumericalDeriv(domain, jacobian); }
161
165bool IFunction::isActive(size_t i) const { return getParameterStatus(i) == Active; }
166
172bool IFunction::isFixed(size_t i) const {
173 auto status = getParameterStatus(i);
174 return status == Fixed || status == FixedByDefault;
175}
176
181
186void IFunction::fix(size_t i, bool isDefault) {
187 auto status = getParameterStatus(i);
188 if (status == Tied) {
189 throw std::runtime_error("Cannot fix parameter " + std::to_string(i) + " (" + parameterName(i) +
190 "): it has a tie.");
191 }
192 if (isDefault) {
194 } else {
196 }
197}
198
202void IFunction::unfix(size_t i) {
203 auto status = getParameterStatus(i);
204 if (status == Tied) {
205 throw std::runtime_error("Cannot unfix parameter " + std::to_string(i) + " (" + parameterName(i) +
206 "): it has a tie.");
207 }
209}
210
218std::unique_ptr<ParameterTie> IFunction::createAndProcessTie(const std::string &parName, const std::string &expr,
219 bool isDefault) {
220 auto newTie = std::make_unique<ParameterTie>(this, parName, expr, isDefault);
221
222 if (!isDefault && newTie->isConstant()) {
223 setParameter(parName, newTie->eval());
224 fix(getParameterIndex(*newTie));
225 return nullptr;
226 }
227
228 return newTie;
229}
230
238void IFunction::tie(const std::string &parName, const std::string &expr, bool isDefault) {
239 auto tiePtr = createAndProcessTie(parName, expr, isDefault);
240
241 if (tiePtr) {
242 addTie(std::move(tiePtr));
243 }
244}
245
255void IFunction::addTies(const std::string &ties, bool isDefault) {
256 std::map<size_t, std::pair<size_t, std::string>> oldTies;
257
258 Expression list;
259 list.parse(ties);
260 list.toList();
261 for (const auto &t : list) {
262 if (t.name() == "=" && t.size() >= 2) {
263 size_t n = t.size() - 1;
264 const std::string expr = t[n].str();
265 for (size_t i = n; i != 0;) {
266 --i;
267 const auto &parName = t[i].name();
268 auto parTie = createAndProcessTie(parName, expr, isDefault);
269
270 if (parTie) {
271 auto iPar = getParameterIndex(*parTie);
272 oldTies[iPar] = insertTie(std::move(parTie));
273 }
274 }
275 }
276 }
277
278 try {
279 sortTies(true);
280 } catch (std::runtime_error &) {
281 for (const auto &[iPar, oldTie] : oldTies) {
282 auto [oldIdx, oldExp] = oldTie;
283
284 if (!oldExp.empty()) {
285 m_ties[oldIdx] = std::make_unique<ParameterTie>(this, parameterName(iPar), oldExp);
286 } else {
287 removeTie(iPar);
288 }
289 }
290 throw;
291 }
292 applyTies();
293}
294
299void IFunction::removeTie(const std::string &parName) {
300 size_t i = parameterIndex(parName);
301 this->removeTie(i);
302}
303
306std::string IFunction::writeTies() const {
307 std::ostringstream tieStream;
308 bool first = true;
309 for (auto &parTie : m_ties) {
310 if (parTie->isDefault())
311 continue;
312 if (!first) {
313 tieStream << ',';
314 } else {
315 first = false;
316 }
317 tieStream << parTie->asString(this);
318 }
319 return tieStream.str();
320}
321
327std::pair<std::size_t, std::string> IFunction::insertTie(std::unique_ptr<ParameterTie> tie) {
328 auto iPar = getParameterIndex(*tie);
329 std::size_t existingTieIndex =
330 std::distance(m_ties.begin(), std::find_if(m_ties.begin(), m_ties.end(),
331 [&](const auto &m_tie) { return getParameterIndex(*m_tie) == iPar; }));
332 std::string oldExp = "";
333 const auto oldTie = getTie(iPar);
334 if (oldTie) {
335 const auto oldTieStr = oldTie->asString();
336 oldExp = oldTieStr.substr(oldTieStr.find("=") + 1);
337 }
338
339 if (existingTieIndex < m_ties.size()) {
340 m_ties[existingTieIndex] = std::move(tie);
341 } else {
342 m_ties.emplace_back(std::move(tie));
344 }
345
346 if (oldTie) {
347 return {existingTieIndex, oldExp};
348 } else {
349 return {existingTieIndex, ""};
350 }
351}
352
358void IFunction::addTie(std::unique_ptr<ParameterTie> tie) {
359 auto iPar = getParameterIndex(*tie);
360 const auto [oldIdx, oldExp] = insertTie(std::move(tie));
361
362 try {
363 // sortTies checks for circular and self ties
364 sortTies(true);
365 } catch (std::runtime_error &) {
366 // revert / remove tie if invalid
367 if (!oldExp.empty()) {
368 m_ties[oldIdx] = std::make_unique<ParameterTie>(this, parameterName(iPar), oldExp);
369 } else {
370 removeTie(iPar);
371 }
372 throw;
373 }
374}
375
376bool IFunction::hasOrderedTies() const { return !m_orderedTies.empty(); }
377
379 for (auto &&parTie : m_orderedTies) {
380 parTie->eval();
381 }
382}
383
388 if (hasOrderedTies()) {
390 } else {
391 for (auto &parTie : m_ties) {
392 parTie->eval();
393 }
394 }
395}
396
404 const size_t m_i;
405
406public:
408 explicit ReferenceEqual(const IFunction &fun, size_t i) : m_fun(fun), m_i(i) {}
412 template <class T> bool operator()(const std::unique_ptr<T> &p) { return m_fun.getParameterIndex(*p) == m_i; }
413};
414
419bool IFunction::removeTie(size_t i) {
420 if (i >= nParams()) {
421 throw std::out_of_range("Function parameter index out of range.");
422 }
423 auto it = std::find_if(m_ties.begin(), m_ties.end(), ReferenceEqual(*this, i));
424 if (it != m_ties.end()) {
425 m_ties.erase(it);
427 return true;
428 }
429 unfix(i);
430 return false;
431}
432
438 auto it = std::find_if(m_ties.cbegin(), m_ties.cend(), ReferenceEqual(*this, i));
439 if (it != m_ties.cend()) {
440 return it->get();
441 }
442 return nullptr;
443}
444
448 for (size_t i = 0; i < nParams(); ++i) {
450 }
451 m_ties.clear();
452}
453
457void IFunction::addConstraint(std::unique_ptr<IConstraint> ic) {
458 size_t iPar = ic->parameterIndex();
459 auto it = std::find_if(m_constraints.begin(), m_constraints.end(),
460 [&iPar](const auto &constraint) { return constraint->parameterIndex() == iPar; });
461
462 if (it != m_constraints.end()) {
463 *it = std::move(ic);
464 } else {
465 m_constraints.emplace_back(std::move(ic));
466 }
467}
468
474 auto it = std::find_if(m_constraints.cbegin(), m_constraints.cend(), ReferenceEqual(*this, i));
475 if (it != m_constraints.cend()) {
476 return it->get();
477 }
478 return nullptr;
479}
480
484void IFunction::removeConstraint(const std::string &parName) {
485 size_t iPar = parameterIndex(parName);
486 const auto it = std::find_if(m_constraints.cbegin(), m_constraints.cend(),
487 [&iPar](const auto &constraint) { return iPar == constraint->getLocalIndex(); });
488 if (it != m_constraints.cend()) {
489 m_constraints.erase(it);
490 }
491}
492
497void IFunction::setConstraintPenaltyFactor(const std::string &parName, const double &c) {
498 size_t iPar = parameterIndex(parName);
499 const auto it = std::find_if(m_constraints.cbegin(), m_constraints.cend(),
500 [&iPar](const auto &constraint) { return iPar == constraint->getLocalIndex(); });
501
502 if (it != m_constraints.cend()) {
503 (*it)->setPenaltyFactor(c);
504 } else {
505 g_log.warning() << parName << " does not have constraint so setConstraintPenaltyFactor failed"
506 << "\n";
507 }
508}
509
512
514 for (auto &constraint : m_constraints) {
515 constraint->setParamToSatisfyConstraint();
516 }
517}
518
521std::string IFunction::writeConstraints() const {
522 std::ostringstream stream;
523 bool first = true;
524 for (const auto &constrint : m_constraints) {
525 if (constrint->isDefault())
526 continue;
527 if (!first) {
528 stream << ',';
529 } else {
530 first = false;
531 }
532 stream << constrint->asString();
533 }
534 return stream.str();
535}
536
542std::string IFunction::asString() const { return writeToString(); }
543
551std::string IFunction::writeToString(const std::string &parentLocalAttributesStr) const {
552 std::ostringstream ostr;
553 ostr << "name=" << this->name();
554 // print the attributes
555 std::vector<std::string> attr = this->getAttributeNames();
556 for (const auto &attName : attr) {
557 std::string attValue = this->getAttribute(attName).value();
558 if (!attValue.empty() && attValue != "\"\"") {
559 ostr << ',' << attName << '=' << attValue;
560 }
561 }
562 std::vector<std::string> ties;
563 // print the parameters
564 for (size_t i = 0; i < nParams(); i++) {
565 std::ostringstream paramOut;
566 paramOut << parameterName(i) << '=' << getParameter(i);
567 ostr << ',' << paramOut.str();
568 // Output non-default ties only.
569 if (getParameterStatus(i) == Fixed) {
570 ties.emplace_back(paramOut.str());
571 }
572 }
573
574 // collect non-default constraints
575 std::string constraints = writeConstraints();
576 // print constraints
577 if (!constraints.empty()) {
578 ostr << ",constraints=(" << constraints << ")";
579 }
580
581 // collect the non-default ties
582 auto tiesString = writeTies();
583 if (!tiesString.empty()) {
584 ties.emplace_back(tiesString);
585 }
586 // print the ties
587 if (!ties.empty()) {
588 ostr << ",ties=(" << Kernel::Strings::join(ties.begin(), ties.end(), ",") << ")";
589 }
590 // "local" attributes of a parent composite function
591 ostr << parentLocalAttributesStr;
592 return ostr.str();
593}
594
601void IFunction::addConstraints(const std::string &str, bool isDefault) {
602 Expression list;
603 list.parse(str);
604 list.toList();
605 for (auto it = list.begin(); it != list.end(); ++it) {
606 auto expr = (*it);
607 if (expr.terms()[0].str().compare("penalty") == 0) {
608 continue;
609 }
610 if ((it + 1) != list.end()) {
611 auto next_expr = *(it + 1);
612 if (next_expr.terms()[0].str().compare("penalty") == 0) {
613 auto c = std::unique_ptr<IConstraint>(ConstraintFactory::Instance().createInitialized(this, expr, isDefault));
614 double penalty_factor = std::stof(next_expr.terms()[1].str(), NULL);
615 c->setPenaltyFactor(penalty_factor);
616 this->addConstraint(std::move(c));
617 } else {
618 auto c = std::unique_ptr<IConstraint>(ConstraintFactory::Instance().createInitialized(this, expr, isDefault));
619 this->addConstraint(std::move(c));
620 }
621 } else {
622 auto c = std::unique_ptr<IConstraint>(ConstraintFactory::Instance().createInitialized(this, expr, isDefault));
623 this->addConstraint(std::move(c));
624 }
625 }
626}
627
631std::vector<std::string> IFunction::getParameterNames() const {
632 std::vector<std::string> out;
633 for (size_t i = 0; i < nParams(); ++i) {
634 out.emplace_back(parameterName(i));
635 }
636 return out;
637}
638
642void IFunction::setHandler(std::unique_ptr<FunctionHandler> handler) {
643 if (handler && handler->function().get() != this) {
644 throw std::runtime_error("Function handler points to a different function");
645 }
646
647 m_handler = std::move(handler);
648 m_handler->init();
649}
650
658
664std::ostream &operator<<(std::ostream &ostr, const IFunction &f) {
665 ostr << f.asString();
666 return ostr;
667}
668
669namespace {
673class AttType : public IFunction::ConstAttributeVisitor<std::string> {
674protected:
676 std::string apply(const std::string & /*str*/) const override { return "std::string"; }
678 std::string apply(const int & /*i*/) const override { return "int"; }
680 std::string apply(const double & /*d*/) const override { return "double"; }
682 std::string apply(const bool & /*i*/) const override { return "bool"; }
684 std::string apply(const std::vector<double> & /*unused*/) const override { return "std::vector<double>"; }
685};
686} // namespace
687
688std::string IFunction::Attribute::type() const {
689 AttType tmp;
690 return apply(tmp);
691}
692
693namespace {
697class AttValue : public IFunction::ConstAttributeVisitor<std::string> {
698public:
699 explicit AttValue(bool quoteString = false)
700 : IFunction::ConstAttributeVisitor<std::string>(), m_quoteString(quoteString) {}
701
702protected:
704 std::string apply(const std::string &str) const override {
705 return (m_quoteString) ? std::string("\"" + str + "\"") : str;
706 }
708 std::string apply(const int &i) const override { return std::to_string(i); }
710 std::string apply(const double &d) const override { return boost::lexical_cast<std::string>(d); }
712 std::string apply(const bool &b) const override { return b ? "true" : "false"; }
714 std::string apply(const std::vector<double> &v) const override {
715 std::string res = "(";
716 if (!v.empty()) {
717 for (size_t i = 0; i < v.size() - 1; ++i) {
718 res += boost::lexical_cast<std::string>(v[i]) + ",";
719 }
720 res += boost::lexical_cast<std::string>(v.back());
721 }
722 res += ")";
723 return res;
724 }
725
726private:
729};
730} // namespace
731
732std::string IFunction::Attribute::value() const {
733 AttValue tmp(m_quoteValue);
734 return apply(tmp);
735}
736
741 if (m_quoteValue)
742 return asQuotedString();
743
744 try {
745 return boost::get<std::string>(m_data);
746 } catch (...) {
747 throw std::runtime_error("Trying to access a " + type() +
748 " attribute "
749 "as string");
750 }
751}
752
757 std::string attr;
758
759 try {
760 attr = boost::get<std::string>(m_data);
761 } catch (...) {
762 throw std::runtime_error("Trying to access a " + type() +
763 " attribute "
764 "as string");
765 }
766
767 if (attr.empty())
768 return "\"\"";
769
770 std::string quoted(attr);
771 if (*(attr.begin()) != '\"')
772 quoted = "\"" + attr;
773 if (*(quoted.end() - 1) != '\"')
774 quoted += "\"";
775
776 return quoted;
777}
778
783 std::string attr;
784
785 try {
786 attr = boost::get<std::string>(m_data);
787 } catch (...) {
788 throw std::runtime_error("Trying to access a " + type() +
789 " attribute "
790 "as string");
791 }
792 std::string unquoted(attr);
793 if (attr.empty())
794 return "";
795 if (*(attr.begin()) == '\"')
796 unquoted = std::string(attr.begin() + 1, attr.end() - 1);
797 if (*(unquoted.end() - 1) == '\"')
798 unquoted.resize(unquoted.size() - 1);
799
800 return unquoted;
801}
802
807 try {
808 return boost::get<int>(m_data);
809 } catch (...) {
810 throw std::runtime_error("Trying to access a " + type() +
811 " attribute "
812 "as int");
813 }
814}
815
820 try {
821 return boost::get<double>(m_data);
822 } catch (...) {
823 throw std::runtime_error("Trying to access a " + type() +
824 " attribute "
825 "as double");
826 }
827}
828
833 try {
834 return boost::get<bool>(m_data);
835 } catch (...) {
836 throw std::runtime_error("Trying to access a " + type() +
837 " attribute "
838 "as bool");
839 }
840}
841
845std::vector<double> IFunction::Attribute::asVector() const {
846 try {
847 return boost::get<std::vector<double>>(m_data);
848 } catch (...) {
849 throw std::runtime_error("Trying to access a " + type() +
850 " attribute "
851 "as vector");
852 }
853}
854
859void IFunction::Attribute::setString(const std::string &str) {
860 evaluateValidator(str);
861
862 try {
863 boost::get<std::string>(m_data) = str;
864 } catch (...) {
865 throw std::runtime_error("Trying to access a " + type() +
866 " attribute "
867 "as string");
868 }
869}
870
876 evaluateValidator(d);
877
878 try {
879 boost::get<double>(m_data) = d;
880 } catch (...) {
881 throw std::runtime_error("Trying to access a " + type() +
882 " attribute "
883 "as double");
884 }
885}
886
892 evaluateValidator(i);
893
894 try {
895 boost::get<int>(m_data) = i;
896 } catch (...) {
897 throw std::runtime_error("Trying to access a " + type() +
898 " attribute "
899 "as int");
900 }
901}
902
907void IFunction::Attribute::setBool(const bool &b) {
908 evaluateValidator(b);
909
910 try {
911 boost::get<bool>(m_data) = b;
912 } catch (...) {
913 throw std::runtime_error("Trying to access a " + type() +
914 " attribute "
915 "as bool");
916 }
917}
918
924void IFunction::Attribute::setVector(const std::vector<double> &v) {
925 evaluateValidator(v);
926
927 try {
928 auto &data = boost::get<std::vector<double>>(m_data);
929 data.assign(v.begin(), v.end());
930 } catch (...) {
931 throw std::runtime_error("Trying to access a " + type() +
932 " attribute "
933 "as vector");
934 }
935}
936
939 try {
940 return boost::get<std::string>(m_data).empty();
941 } catch (...) {
942 throw std::runtime_error("Trying to access a " + type() + " attribute as string");
943 }
944}
945
946namespace {
950class SetValue : public IFunction::AttributeVisitor<> {
951public:
957 explicit SetValue(std::string value, Mantid::Kernel::IValidator_sptr validator = Mantid::Kernel::IValidator_sptr())
958 : m_value(std::move(value)), m_validator(validator) {}
959
960protected:
962 void apply(std::string &str) const override {
963 evaluateValidator(m_value);
964 str = m_value;
965 }
967 void apply(int &i) const override {
968 int tempi = 0;
969
970 std::istringstream istr(m_value + " ");
971 istr >> tempi;
972 if (!istr.good())
973 throw std::invalid_argument("Failed to set int attribute "
974 "from string " +
975 m_value);
976
977 evaluateValidator(tempi);
978 i = tempi;
979 }
981 void apply(double &d) const override {
982 double tempd = 0;
983
984 std::istringstream istr(m_value + " ");
985 istr >> tempd;
986 if (!istr.good())
987 throw std::invalid_argument("Failed to set double attribute "
988 "from string " +
989 m_value);
990
991 evaluateValidator(tempd);
992 d = tempd;
993 }
995 void apply(bool &b) const override {
996 bool tempb = false;
997
998 tempb = (m_value == "true" || m_value == "TRUE" || m_value == "1");
999 evaluateValidator(tempb);
1000
1001 b = (m_value == "true" || m_value == "TRUE" || m_value == "1");
1002 }
1004 void apply(std::vector<double> &v) const override {
1005 if (m_value.empty() || m_value == "EMPTY") {
1006 v.clear();
1007 return;
1008 }
1009 if (m_value.size() > 2) {
1010 // check if the value is in brackets (...)
1011 if (m_value.front() == '(' && m_value.back() == ')') {
1012 m_value.erase(0, 1);
1013 m_value.erase(m_value.size() - 1);
1014 }
1015 }
1016 Kernel::StringTokenizer tokenizer(m_value, ",", Kernel::StringTokenizer::TOK_TRIM);
1017 size_t newSize = tokenizer.count();
1018
1019 // if visitor has an associated validator, first populate temp vec and evaluate against validator.
1020 if (m_validator != nullptr) {
1021 std::vector<double> tempVec(newSize);
1022
1023 for (size_t i = 0; i < tempVec.size(); ++i) {
1024 tempVec[i] = boost::lexical_cast<double>(tokenizer[i]);
1025 }
1026 evaluateValidator(tempVec);
1027 }
1028
1029 v.resize(newSize);
1030 for (size_t i = 0; i < v.size(); ++i) {
1031 v[i] = boost::lexical_cast<double>(tokenizer[i]);
1032 }
1033 }
1034
1036 template <typename T> void evaluateValidator(T &inputData) const {
1037 if (m_validator != nullptr) {
1038 IFunction::ValidatorEvaluator::evaluate(inputData, m_validator);
1039 }
1040 }
1041
1042private:
1043 mutable std::string m_value;
1044 mutable Kernel::IValidator_sptr m_validator;
1045};
1046} // namespace
1047
1051void IFunction::Attribute::fromString(const std::string &str) {
1052 SetValue tmp(str, m_validator);
1053 apply(tmp);
1054}
1055
1060
1065
1068double IFunction::activeParameter(size_t i) const {
1069 if (!isActive(i)) {
1070 throw std::runtime_error("Attempt to use an inactive parameter " + parameterName(i));
1071 }
1072 return getParameter(i);
1073}
1074
1077void IFunction::setActiveParameter(size_t i, double value) {
1078 if (!isActive(i)) {
1079 throw std::runtime_error("Attempt to use an inactive parameter " + parameterName(i));
1080 }
1081 setParameter(i, value);
1082}
1083
1088std::string IFunction::nameOfActive(size_t i) const {
1089 if (!isActive(i)) {
1090 throw std::runtime_error("Attempt to use an inactive parameter " + parameterName(i));
1091 }
1092 return parameterName(i);
1093}
1094
1099std::string IFunction::descriptionOfActive(size_t i) const {
1100 if (!isActive(i)) {
1101 throw std::runtime_error("Attempt to use an inactive parameter " + parameterName(i));
1102 }
1103 return parameterDescription(i);
1104}
1105
1112 /*
1113 * There is a similar more specialized method for 1D functions in IFunction1D
1114 * but the method takes different parameters and uses slightly different
1115 * function calls in places making it difficult to share code. Please also
1116 * consider that method when updating this.
1117 */
1118
1119 const size_t nParam = nParams();
1120 size_t nData = getValuesSize(domain);
1121
1122 FunctionValues minusStep(nData);
1123 FunctionValues plusStep(nData);
1124
1125 applyTies(); // just in case
1126 function(domain, minusStep);
1127
1128 if (nData == 0) {
1129 nData = minusStep.size();
1130 }
1131
1132 double step;
1133 for (size_t iP = 0; iP < nParam; iP++) {
1134 if (isActive(iP)) {
1135 const double val = activeParameter(iP);
1136 step = calculateStepSize(iP, val);
1137
1138 const double paramPstep = val + step;
1139 setActiveParameter(iP, paramPstep);
1140 applyTies();
1141 function(domain, plusStep);
1142 setActiveParameter(iP, val);
1143 applyTies();
1144
1145 step = paramPstep - val;
1146 for (size_t i = 0; i < nData; i++) {
1147 jacobian.set(i, iP, (plusStep.getCalculated(i) - minusStep.getCalculated(i)) / step);
1148 }
1149 }
1150 }
1151}
1152
1158double IFunction::calculateStepSize(const size_t parameterIndex, const double parameterValue) const {
1159 switch (m_stepSizeMethod) {
1161 return defaultStepSize(parameterValue);
1163 return sqrtEpsilonStepSize(parameterValue);
1165 return m_stepSizes.at(parameterIndex);
1166 }
1167 throw std::invalid_argument("An invalid method for calculating the step size was provided.");
1168}
1169
1174
1181void IFunction::setMatrixWorkspace(std::shared_ptr<const API::MatrixWorkspace> workspace, size_t wi, double startX,
1182 double endX) {
1183 UNUSED_ARG(startX);
1184 UNUSED_ARG(endX);
1185
1186 if (!workspace)
1187 return; // unset the workspace
1188
1189 try {
1190
1191 // check if parameter are specified in instrument definition file
1192
1193 const auto &paramMap = workspace->constInstrumentParameters();
1194
1195 Geometry::IDetector const *detectorPtr = nullptr;
1196 size_t numDetectors = workspace->getSpectrum(wi).getDetectorIDs().size();
1197 if (numDetectors > 1) {
1198 // Note JZ oct 2011 - I'm not sure why the code uses the first detector
1199 // and not the group. Ask Roman.
1200 // Use the first detector ID that is actually present in the instrument;
1201 // a spectrum may reference detector IDs that are absent from the
1202 // instrument definition, in which case getDetector() throws.
1203 const auto &detectorInfo = workspace->detectorInfo();
1204 const auto &specDef = workspace->spectrumInfo().spectrumDefinition(wi);
1205 for (size_t k = 0; k < specDef.size(); ++k) {
1206 try {
1207 // detector() throws NotFoundError if the ID is absent from the instrument
1208 detectorPtr = &detectorInfo.detector(specDef[k].first);
1209 break;
1210 } catch (const Kernel::Exception::NotFoundError &) {
1211 // This detector is not present in the instrument; try the next one
1212 }
1213 }
1214 if (!detectorPtr) {
1215 g_log.information() << "MatrixWorkspace has not been set for index: " << std::to_string(wi)
1216 << " as none of the detector ids can be found on the instrument\n";
1217 return;
1218 }
1219 } else {
1220 // Get the detector (single) at this workspace index
1221 const auto &spectrumInfo = workspace->spectrumInfo();
1222 if (!spectrumInfo.hasDetectors(wi)) {
1223 g_log.information() << "MatrixWorkspace has not been set for index: " << std::to_string(wi)
1224 << " as no detector ids can be found for this workspace on the instrument\n";
1225 return;
1226 }
1227 try {
1228 detectorPtr = &spectrumInfo.detector(wi);
1229 } catch (const Kernel::Exception::NotFoundError &) {
1230 // hasDetectors() does not validate IDs against the instrument;
1231 // the detector ID exists in the spectrum but not in the instrument.
1232 g_log.information() << "MatrixWorkspace has not been set for index: " << std::to_string(wi)
1233 << " as the detector id for this workspace can't be found on the instrument\n";
1234 return;
1235 }
1236 }
1237
1238 for (size_t i = 0; i < nParams(); i++) {
1239 if (!isExplicitlySet(i)) {
1240 // Use the fitting-function-aware lookup: two functions on the same component can declare a
1241 // parameter with the same short name (e.g. Bk2BkExpConvPV:Gamma and IkedaCarpenterPV:Gamma).
1242 // The plain getRecursive() short-circuits on the first match and would pick the wrong one.
1244 paramMap.getRecursiveFittingParameter(detectorPtr, parameterName(i), this->name());
1245 if (!param) {
1246 // Fall back for IDFs that omit the function prefix (no embedded function name to match).
1247 param = paramMap.getRecursive(detectorPtr, parameterName(i), "fitting");
1248 }
1249 if (param != Geometry::Parameter_sptr()) {
1250 // get FitParameter
1251 const auto &fitParam = param->value<Geometry::FitParameter>();
1252
1253 // check first if this parameter is actually specified for this
1254 // function
1255 if (name() == fitParam.getFunction()) {
1256 // update value
1257 const auto *testWithLocation = dynamic_cast<IFunctionWithLocation *>(this);
1258 if (testWithLocation == nullptr ||
1259 (!fitParam.getLookUpTable().containData() && fitParam.getFormula().empty())) {
1260 setParameter(i, fitParam.getValue());
1261 } else {
1262 double centreValue = testWithLocation->centre();
1263 Kernel::Unit_sptr centreUnit; // unit of value used in formula or
1264 // to look up value in lookup table
1265 if (fitParam.getFormula().empty())
1266 centreUnit = fitParam.getLookUpTable().getXUnit(); // from table
1267 else {
1268 if (!fitParam.getFormulaUnit().empty()) {
1269 try {
1270 centreUnit = Kernel::UnitFactory::Instance().create(fitParam.getFormulaUnit()); // from formula
1271 } catch (...) {
1272 g_log.warning() << fitParam.getFormulaUnit() << " Is not an recognised formula unit for parameter "
1273 << fitParam.getName() << "\n";
1274 }
1275 }
1276 }
1277
1278 // if unit specified convert centre value to unit required by
1279 // formula or look-up-table
1280 if (centreUnit) {
1281 g_log.debug() << "For FitParameter " << parameterName(i)
1282 << " centre of peak before any unit conversion is " << centreValue << '\n';
1283 centreValue = convertValue(centreValue, centreUnit, workspace, wi);
1284 g_log.debug() << "For FitParameter " << parameterName(i)
1285 << " centre of peak after any unit conversion is " << centreValue << '\n';
1286 }
1287
1288 double paramValue = fitParam.getValue(centreValue);
1289
1290 // this returned param value by a formula or a look-up-table may
1291 // have
1292 // a unit of its own. If set convert param value
1293 // See section 'Using fitting parameters in
1294 // docs/source/concepts/InstrumentDefinitionFile.rst
1295 if (fitParam.getFormula().empty()) {
1296 // so from look up table
1297 Kernel::Unit_sptr resultUnit = fitParam.getLookUpTable().getYUnit(); // from table
1298 g_log.debug() << "The FitParameter " << parameterName(i) << " = " << paramValue
1299 << " before y-unit conversion\n";
1300 paramValue /= convertValue(1.0, resultUnit, workspace, wi);
1301 g_log.debug() << "The FitParameter " << parameterName(i) << " = " << paramValue
1302 << " after y-unit conversion\n";
1303 } else {
1304 // so from formula
1305
1306 std::string resultUnitStr = fitParam.getResultUnit();
1307
1308 if (!resultUnitStr.empty()) {
1309 std::vector<std::string> allUnitStr = Kernel::UnitFactory::Instance().getKeys();
1310 for (auto &iUnit : allUnitStr) {
1311 size_t found = resultUnitStr.find(iUnit);
1312 if (found != std::string::npos) {
1313 size_t len = iUnit.size();
1314 std::stringstream readDouble;
1315 Kernel::Unit_sptr unt = Kernel::UnitFactory::Instance().create(iUnit);
1316 readDouble << 1.0 / convertValue(1.0, unt, workspace, wi);
1317 resultUnitStr.replace(found, len, readDouble.str());
1318 }
1319 } // end for
1320
1321 try {
1322 mu::Parser p;
1323 p.SetExpr(resultUnitStr);
1324 g_log.debug() << "The FitParameter " << parameterName(i) << " = " << paramValue
1325 << " before result-unit conversion (using " << resultUnitStr << ")\n";
1326 paramValue *= p.Eval();
1327 g_log.debug() << "The FitParameter " << parameterName(i) << " = " << paramValue
1328 << " after result-unit conversion\n";
1329 } catch (mu::Parser::exception_type &e) {
1330 g_log.error() << "Cannot convert formula unit to workspace unit"
1331 << " Formula unit which cannot be passed is " << resultUnitStr
1332 << ". Muparser error message is: " << e.GetMsg() << '\n';
1333 }
1334 } // end if
1335 } // end trying to convert result-unit from formula or y-unit for
1336 // lookuptable
1337
1338 setParameter(i, paramValue);
1339 } // end of update parameter value
1340
1341 // add tie if specified for this parameter in instrument definition
1342 // file
1343 if (!fitParam.getTie().empty()) {
1344 std::ostringstream str;
1345 str << getParameter(i);
1346 tie(parameterName(i), str.str());
1347 }
1348
1349 // add constraint if specified for this parameter in instrument
1350 // definition file
1351 if (!fitParam.getConstraint().empty()) {
1352 IConstraint *constraint = ConstraintFactory::Instance().createInitialized(this, fitParam.getConstraint());
1353 if (!fitParam.getConstraintPenaltyFactor().empty()) {
1354 try {
1355 double penalty = std::stod(fitParam.getConstraintPenaltyFactor());
1356 constraint->setPenaltyFactor(penalty);
1357 } catch (...) {
1358 g_log.warning() << "Can't set penalty factor for constraint\n";
1359 }
1360 }
1361 addConstraint(std::unique_ptr<IConstraint>(constraint));
1362 }
1363 }
1364 }
1365 }
1366 }
1367 } catch (...) {
1368 }
1369}
1370
1380 const std::shared_ptr<const MatrixWorkspace> &ws, size_t wsIndex) const {
1381 // only required if formula or look-up-table different from ws unit
1382 const auto &wsUnit = ws->getAxis(0)->unit();
1383 if (outUnit->unitID() == wsUnit->unitID())
1384 return value;
1385
1386 // first check if it is possible to do a quick conversion and convert
1387 // slight duplication to below to avoid instantiating vector unless necessary
1388 double factor(0.0), power(0.0);
1389 if (wsUnit->quickConversion(*outUnit, factor, power)) {
1390 return factor * std::pow(value, power);
1391 } else {
1392 std::vector<double> singleValue(1, value);
1393 convertValue(singleValue, outUnit, ws, wsIndex);
1394 return singleValue.front();
1395 }
1396}
1397
1406void IFunction::convertValue(std::vector<double> &values, Kernel::Unit_sptr &outUnit,
1407 const std::shared_ptr<const MatrixWorkspace> &ws, size_t wsIndex) const {
1408 // only required if formula or look-up-table different from ws unit
1409 const auto &wsUnit = ws->getAxis(0)->unit();
1410 if (outUnit->unitID() == wsUnit->unitID())
1411 return;
1412
1413 // first check if it is possible to do a quick conversion convert
1414 double factor, power;
1415 if (wsUnit->quickConversion(*outUnit, factor, power)) {
1416 auto iend = values.end();
1417 for (auto itr = values.begin(); itr != iend; ++itr)
1418 (*itr) = factor * std::pow(*itr, power);
1419 } else {
1420 // Get l1, l2 and theta (see also RemoveBins.calculateDetectorPosition())
1421 Instrument_const_sptr instrument = ws->getInstrument();
1422 Geometry::IComponent_const_sptr sample = instrument->getSample();
1423 if (sample == nullptr) {
1424 g_log.error() << "No sample defined instrument. Cannot convert units for function\n"
1425 << "Ignore conversion.";
1426 return;
1427 }
1428 const auto &spectrumInfo = ws->spectrumInfo();
1429 double l1 = spectrumInfo.l1();
1430 // If this is a monitor then l1+l2 = source-detector distance and twoTheta=0
1431 auto emode = ws->getEMode();
1432
1434 spectrumInfo.getDetectorValues(*wsUnit, *outUnit, emode, false, wsIndex, pmap);
1435 try {
1436 std::vector<double> emptyVec;
1437 wsUnit->toTOF(values, emptyVec, l1, emode, pmap);
1438 outUnit->fromTOF(values, emptyVec, l1, emode, pmap);
1439 } catch (std::exception &) {
1440 throw std::runtime_error("Unable to perform unit conversion to " + outUnit->unitID());
1441 }
1442 }
1443}
1444
1448size_t IFunction::nAttributes() const { return m_attrs.size(); }
1449
1451bool IFunction::hasAttribute(const std::string &name) const { return m_attrs.find(name) != m_attrs.end(); }
1452
1458void IFunction::setAttributeValue(const std::string &attName, const char *value) {
1459 std::string str(value);
1460 setAttributeValue(attName, str);
1461}
1462
1468void IFunction::setAttributeValue(const std::string &attName, const std::string &value) {
1469 Attribute att = getAttribute(attName);
1470 att.setString(value);
1471 setAttribute(attName, att);
1472}
1473
1476 throw std::runtime_error("Function " + name() + " doesn't have children.");
1477}
1478
1480std::vector<std::string> IFunction::getAttributeNames() const {
1481 std::vector<std::string> names;
1482 names.reserve(nAttributes());
1483 for (size_t i = 0; i < nAttributes(); ++i) {
1484 names.emplace_back(attributeName(i));
1485 }
1486 return names;
1487}
1488
1494std::string IFunction::attributeName(size_t index) const {
1495 if (index >= nAttributes()) {
1496 throw std::out_of_range("Function attribute index out of range.");
1497 }
1498 auto itr = std::next(m_attrs.begin(), index);
1499 return itr->first;
1500}
1501
1507 if (hasAttribute(name)) {
1508 return m_attrs.at(name);
1509 } else {
1510 throw std::invalid_argument("ParamFunctionAttributeHolder::getAttribute - Unknown attribute '" + name + "'");
1511 }
1512}
1513
1524
1530void IFunction::declareAttribute(const std::string &name, const API::IFunction::Attribute &defaultValue) {
1532
1533 m_attrs.emplace(name, defaultValue);
1534}
1535
1542void IFunction::declareAttribute(const std::string &name, const API::IFunction::Attribute &defaultValue,
1543 const Kernel::IValidator &validator) {
1544 const Kernel::IValidator_sptr validatorClone = validator.clone();
1546
1547 defaultValue.setValidator(validatorClone);
1548 defaultValue.evaluateValidator();
1549
1550 m_attrs.emplace(name, defaultValue);
1551}
1552
1557void IFunction::checkAttributeName(const std::string &name) {
1558 if (m_attrs.find(name) != m_attrs.end()) {
1559 std::ostringstream msg;
1560 msg << "Attribute (" << name << ") already exists.";
1561 throw std::invalid_argument(msg.str());
1562 }
1563}
1564
1570
1577 if (hasAttribute(name)) {
1578 auto att = m_attrs[name];
1579 const Kernel::IValidator_sptr validatorClone = att.getValidator();
1580 value.setValidator(validatorClone);
1581 value.evaluateValidator();
1582
1583 m_attrs[name] = value;
1584 } else {
1585 throw std::invalid_argument("ParamFunctionAttributeHolder::setAttribute - Unknown attribute '" + name + "'");
1586 }
1587}
1588
1596 const_cast<IFunction *>(this)->storeAttributeValue(name, value);
1597}
1598
1608void IFunction::setCovarianceMatrix(const std::shared_ptr<Kernel::Matrix<double>> &covar) {
1609 // the matrix shouldn't be empty
1610 if (!covar) {
1611 throw std::invalid_argument("IFunction: Cannot set an empty covariance matrix");
1612 }
1613 // the matrix should relate to this function
1614 if (covar->numRows() != nParams() || covar->numCols() != nParams()) {
1615 throw std::invalid_argument("IFunction: Covariance matrix has a wrong size");
1616 }
1617 m_covar = covar;
1618}
1619
1622size_t IFunction::getValuesSize(const FunctionDomain &domain) const { return domain.size(); }
1623
1627void IFunction::fixParameter(const std::string &name, bool isDefault) {
1628 auto i = parameterIndex(name);
1629 fix(i, isDefault);
1630}
1631
1634void IFunction::unfixParameter(const std::string &name) {
1635 auto i = parameterIndex(name);
1636 unfix(i);
1637}
1638
1641void IFunction::fixAll(bool isDefault) {
1642 for (size_t i = 0; i < nParams(); ++i) {
1643 if (isActive(i)) {
1644 fix(i, isDefault);
1645 }
1646 }
1647}
1648
1651 for (size_t i = 0; i < nParams(); ++i) {
1652 if (isFixed(i)) {
1653 unfix(i);
1654 }
1655 }
1656}
1657
1660 for (size_t i = 0; i < nParams(); ++i) {
1662 unfix(i);
1663 }
1664 }
1665}
1666
1672void IFunction::fixAllActive(bool isDefault) {
1673 for (size_t i = 0; i < nParams(); ++i) {
1674 if (getParameterStatus(i) == Active) {
1675 fix(i, isDefault);
1676 }
1677 }
1678}
1679
1684size_t IFunction::getNumberDomains() const { return 1; }
1685
1691std::vector<IFunction_sptr> IFunction::createEquivalentFunctions() const {
1692 return std::vector<IFunction_sptr>(1, FunctionFactory::Instance().createInitialized(asString()));
1693}
1694
1698void IFunction::sortTies(const bool checkOnly) {
1699 if (!checkOnly) {
1700 m_orderedTies.clear();
1701 }
1702
1703 std::list<TieNode> orderedTieNodes;
1704 for (size_t i = 0; i < nParams(); ++i) {
1705 auto const parTie = getTie(i);
1706 if (!parTie || ignoreTie(*parTie)) {
1707 continue;
1708 }
1709
1710 TieNode newNode;
1711 newNode.left = getParameterIndex(*parTie);
1712 auto const rhsParameters = parTie->getRHSParameters();
1713 newNode.right.reserve(rhsParameters.size());
1714 for (auto &&p : rhsParameters) {
1715 newNode.right.emplace_back(this->getParameterIndex(p));
1716 }
1717 if (newNode < newNode) {
1718 throw std::runtime_error("Parameter is tied to itself: " + parTie->asString(this));
1719 }
1720 bool before(false), after(false);
1721 size_t indexBefore(0), indexAfter(0);
1722 for (auto &&node : orderedTieNodes) {
1723 if (newNode < node) {
1724 before = true;
1725 indexBefore = node.left;
1726 }
1727 if (node < newNode) {
1728 after = true;
1729 indexAfter = node.left;
1730 }
1731 }
1732 if (before) {
1733 if (after) {
1734 std::string message = "Circular dependency in ties:\n" + parTie->asString(this) + '\n';
1735 message += getTie(indexBefore)->asString(this);
1736 if (indexAfter != indexBefore) {
1737 message += '\n' + getTie(indexAfter)->asString(this);
1738 }
1739 throw std::runtime_error(message);
1740 }
1741 orderedTieNodes.push_front(newNode);
1742 } else {
1743 orderedTieNodes.emplace_back(newNode);
1744 }
1745 }
1746 if (!checkOnly) {
1747 for (auto &&node : orderedTieNodes) {
1748 auto const parTie = getTie(node.left);
1749 m_orderedTies.emplace_back(parTie);
1750 }
1751 }
1752}
1753
1754} // namespace Mantid::API
1755
1757namespace Mantid::Kernel {
1758
1759template <>
1760MANTID_API_DLL std::shared_ptr<Mantid::API::IFunction>
1761IPropertyManager::getValue<std::shared_ptr<Mantid::API::IFunction>>(const std::string &name) const {
1762 auto *prop = dynamic_cast<PropertyWithValue<std::shared_ptr<Mantid::API::IFunction>> *>(getPointerToProperty(name));
1763 if (prop) {
1764 return *prop;
1765 } else {
1766 std::string message = "Attempt to assign property " + name + " to incorrect type. Expected shared_ptr<IFunction>.";
1767 throw std::runtime_error(message);
1768 }
1769}
1770
1771template <>
1772MANTID_API_DLL std::shared_ptr<const Mantid::API::IFunction>
1773IPropertyManager::getValue<std::shared_ptr<const Mantid::API::IFunction>>(const std::string &name) const {
1774 const auto *prop =
1775 dynamic_cast<PropertyWithValue<std::shared_ptr<Mantid::API::IFunction>> *>(getPointerToProperty(name));
1776 if (prop) {
1777 return prop->operator()();
1778 } else {
1779 std::string message =
1780 "Attempt to assign property " + name + " to incorrect type. Expected const shared_ptr<IFunction>.";
1781 throw std::runtime_error(message);
1782 }
1783}
1784
1785} // namespace Mantid::Kernel
const std::string & m_value
Definition Algorithm.cpp:71
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:380
Attribute is a non-fitting parameter.
Definition IFunction.h:285
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:303
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:244
This is an interface to a fitting function - a semi-abstarct class.
Definition IFunction.h:166
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.
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:91
std::vector< double > m_stepSizes
The custom step sizes for the derivative.
Definition IFunction.h:738
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:722
virtual void declareAttributes()
Override to declare function attributes.
Definition IFunction.h:684
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:443
virtual const std::string categorySeparator() const
Function to return the sperator token for the category string.
Definition IFunction.h:448
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:732
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:728
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:718
std::vector< std::unique_ptr< IConstraint > > m_constraints
Holds the constraints added to function.
Definition IFunction.h:730
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:736
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:96
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:601
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:686
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:561
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:715
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:664
bool m_isRegistered
whether the function usage has been registered
Definition IFunction.h:734
std::shared_ptr< Kernel::Matrix< double > > m_covar
The covariance matrix of the fitting parameters.
Definition IFunction.h:724
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.
Interface class for detector objects.
Definition IDetector.h:43
Exception for when an item is not found in a collection.
Definition Exception.h:145
IValidator is the basic interface for all validators for properties.
Definition IValidator.h:43
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:42
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:748
Mantid::Kernel::StringTokenizer tokenizer
std::shared_ptr< Parameter > Parameter_sptr
Typedef for the shared pointer.
Definition Parameter.h:194
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
Definition IComponent.h:167
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.
DLLExport 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:85
std::unordered_map< UnitParams, double > UnitParametersMap
Definition Unit.h:30
std::shared_ptr< Unit > Unit_sptr
Shared pointer to the Unit base class.
Definition Unit.h:194
std::shared_ptr< IValidator > IValidator_sptr
A shared_ptr to an IValidator.
Definition IValidator.h:26
Generate a tableworkspace to store the calibration results.
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)