Commit ce905bde authored by Roman Tolchenov's avatar Roman Tolchenov
Browse files

Re #18518. Replaced isFixed flag with parameter status.

parent 583cc076
......@@ -44,6 +44,7 @@ set ( SRC_FILES
src/FunctionDomainGeneral.cpp
src/FunctionDomainMD.cpp
src/FunctionFactory.cpp
src/FunctionGenerator.cpp
src/FunctionParameterDecorator.cpp
src/FunctionProperty.cpp
src/FunctionValues.cpp
......@@ -203,6 +204,7 @@ set ( INC_FILES
inc/MantidAPI/FunctionDomainGeneral.h
inc/MantidAPI/FunctionDomainMD.h
inc/MantidAPI/FunctionFactory.h
inc/MantidAPI/FunctionGenerator.h
inc/MantidAPI/FunctionParameterDecorator.h
inc/MantidAPI/FunctionProperty.h
inc/MantidAPI/FunctionValues.h
......
......@@ -111,13 +111,6 @@ public:
/// Set the fitting error for a parameter
void setError(size_t i, double err) override;
/// Check if a parameter is active
bool isFixed(size_t i) const override;
/// Removes a parameter from the list of active
void fix(size_t i) override;
/// Restores a declared parameter i to the active status
void unfix(size_t i) override;
/// Value of i-th active parameter. Override this method to make fitted
/// parameters different from the declared
double activeParameter(size_t i) const override;
......@@ -223,6 +216,10 @@ protected:
/// Declare a new parameter
void declareParameter(const std::string &name, double initValue = 0,
const std::string &description = "") override;
/// Change status of parameter
void setParameterStatus(size_t i, ParameterStatus status) override;
/// Get status of parameter
ParameterStatus getParameterStatus(size_t i) const override;
size_t paramOffset(size_t i) const { return m_paramOffsets[i]; }
......
#ifndef MANTID_CURVEFITTING_FUNCTIONGENERATOR_H_
#define MANTID_CURVEFITTING_FUNCTIONGENERATOR_H_
#ifndef MANTID_API_FUNCTIONGENERATOR_H_
#define MANTID_API_FUNCTIONGENERATOR_H_
#include "MantidAPI/IFunction.h"
namespace Mantid {
namespace CurveFitting {
namespace Functions {
namespace API {
/**
FunctionGenerator is a partial implementation of IFunction that defines a
function consisting of two parts: the source and the target. The source
......@@ -45,10 +44,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
File change history is stored at: <https://github.com/mantidproject/mantid>
Code Documentation is available at: <http://doxygen.mantidproject.org>
*/
class DLLExport FunctionGenerator : public API::IFunction {
class DLLExport FunctionGenerator : public IFunction {
public:
/// Constructor
FunctionGenerator(API::IFunction_sptr source);
FunctionGenerator(IFunction_sptr source);
/// @name Overrides implementing composition of two functions:
/// m_source and m_target.
......@@ -83,21 +82,14 @@ public:
/// Set the fitting error for a parameter
void setError(size_t i, double err) override;
/// Check if a declared parameter i is fixed
bool isFixed(size_t i) const override;
/// Removes a declared parameter i from the list of active
void fix(size_t i) override;
/// Restores a declared parameter i to the active status
void unfix(size_t i) override;
/// Return parameter index from a parameter reference.
size_t getParameterIndex(const API::ParameterReference &ref) const override;
size_t getParameterIndex(const ParameterReference &ref) const override;
/// Set up the function for a fit.
void setUpForFit() override;
/// Get the tie for i-th parameter
API::ParameterTie *getTie(size_t i) const override;
ParameterTie *getTie(size_t i) const override;
/// Get the i-th constraint
API::IConstraint *getConstraint(size_t i) const override;
IConstraint *getConstraint(size_t i) const override;
/// Build target function.
virtual void buildTargetFunction() const = 0;
......@@ -106,6 +98,10 @@ protected:
/// Declare a new parameter
void declareParameter(const std::string &name, double initValue = 0,
const std::string &description = "") override;
/// Change status of parameter
void setParameterStatus(size_t i, ParameterStatus status) override;
/// Get status of parameter
ParameterStatus getParameterStatus(size_t i) const override;
//@}
public:
......@@ -124,8 +120,8 @@ public:
//@}
/// Evaluate the function
void function(const API::FunctionDomain &domain,
API::FunctionValues &values) const override;
void function(const FunctionDomain &domain,
FunctionValues &values) const override;
protected:
/// overwrite IFunction base class method, which declare function parameters
......@@ -138,17 +134,16 @@ protected:
/// Update target function if necessary.
void checkTargetFunction() const;
/// Function that calculates parameters of the target function.
API::IFunction_sptr m_source;
IFunction_sptr m_source;
/// Function that actually calculates the output.
mutable API::IFunction_sptr m_target;
mutable IFunction_sptr m_target;
/// Cached number of parameters in m_source.
size_t m_nOwnParams;
/// Flag indicating that updateTargetFunction() is required.
mutable bool m_dirty;
};
} // namespace Functions
} // namespace CurveFitting
} // namespace API
} // namespace Mantid
#endif /*MANTID_CURVEFITTING_FUNCTIONGENERATOR_H_*/
#endif /*MANTID_API_FUNCTIONGENERATOR_H_*/
......@@ -91,15 +91,6 @@ public:
/// Set the fitting error for a parameter of decorated function.
void setError(size_t i, double err) override;
/// Check if a declared parameter i of decorated function is active.
bool isFixed(size_t i) const override;
/// Removes a declared parameter i of decorated function from the list of
/// active.
void fix(size_t i) override;
/// Restores a declared parameter i of decorated function to the active
/// status.
void unfix(size_t i) override;
/// Return parameter index of decorated function from a parameter reference.
/// Usefull for constraints and ties in composite functions.
size_t getParameterIndex(const ParameterReference &ref) const override;
......@@ -148,6 +139,8 @@ protected:
const std::string &description) override;
void addTie(std::unique_ptr<ParameterTie>) override;
void setParameterStatus(size_t i, ParameterStatus status) override;
ParameterStatus getParameterStatus(size_t i) const override;
virtual void beforeDecoratedFunctionSet(const IFunction_sptr &fn);
void setDecoratedFunctionPrivate(const IFunction_sptr &fn);
......
......@@ -414,11 +414,11 @@ public:
virtual void setError(size_t i, double err) = 0;
/// Check if a declared parameter i is fixed
virtual bool isFixed(size_t i) const = 0;
bool isFixed(size_t i) const;
/// Removes a declared parameter i from the list of active
virtual void fix(size_t i) = 0;
void fix(size_t i);
/// Restores a declared parameter i to the active status
virtual void unfix(size_t i) = 0;
void unfix(size_t i);
/// Fix a parameter
void fixParameter(const std::string &name);
/// Free a parameter
......@@ -448,7 +448,7 @@ public:
/// Returns the name of active parameter i
virtual std::string descriptionOfActive(size_t i) const;
/// Check if an active parameter i is actually active
virtual bool isActive(size_t i) const;
bool isActive(size_t i) const;
//@}
/** @name Ties */
......@@ -468,8 +468,6 @@ public:
virtual bool removeTie(size_t i);
/// Get the tie of i-th parameter
virtual ParameterTie *getTie(size_t i) const;
/// Add a new tie. Derived classes must provide storage for ties
virtual void addTie(std::unique_ptr<ParameterTie> tie);
/// Write a parameter tie to a string
std::string writeTies() const;
//@}
......@@ -544,6 +542,12 @@ public:
FunctionHandler *getHandler() const { return m_handler; }
protected:
/// Describe parameter status in relation to fitting:
/// Active: Fit varies such parameter directly.
/// Fixed: Value doesn't change during fit.
/// Tied: Value depends on values of other parameters.
enum ParameterStatus {Active, Fixed, Tied};
/// Function initialization. Declare function parameters in this method.
virtual void init();
/// Declare a new parameter
......@@ -573,10 +577,17 @@ protected:
/// A read-only ("mutable") attribute can be stored in a const method
void storeReadOnlyAttribute(const std::string &name,
const API::IFunction::Attribute &value) const;
/// Add a new tie. Derived classes must provide storage for ties
virtual void addTie(std::unique_ptr<ParameterTie> tie);
/// Change status of parameter
virtual void setParameterStatus(size_t i, ParameterStatus status) = 0;
/// Get status of parameter
virtual ParameterStatus getParameterStatus(size_t i) const = 0;
friend class ParameterTie;
friend class CompositeFunction;
friend class FunctionParameterDecorator;
friend class FunctionGenerator;
/// Flag to hint that the function is being used in parallel computations
bool m_isParallel;
......
......@@ -81,13 +81,6 @@ public:
/// Set the fitting error for a parameter
void setError(size_t i, double err) override;
/// Check if a declared parameter i is active
bool isFixed(size_t i) const override;
/// Removes a declared parameter i from the list of active
void fix(size_t i) override;
/// Restores a declared parameter i to the active status
void unfix(size_t i) override;
/// Return parameter index from a parameter reference. Usefull for constraints
/// and ties in composite functions
size_t getParameterIndex(const ParameterReference &ref) const override;
......@@ -100,16 +93,27 @@ protected:
/// Declare a new parameter
void declareParameter(const std::string &name, double initValue = 0,
const std::string &description = "") override;
/// Get the address of the parameter. For use in UserFunction with mu::Parser
virtual double *getParameterAddress(size_t i);
/// Nonvirtual member which removes all declared parameters
void clearAllParameters();
/// Change status of parameter
void setParameterStatus(size_t i, ParameterStatus status) override;
/// Get status of parameter
ParameterStatus getParameterStatus(size_t i) const override;
private:
/// The index map. m_indexMap[i] gives the total index for active parameter i
std::vector<bool> m_isFixed;
/// Check that a parameter index is in a valid range.
/// @param i :: Index to check.
inline void checkParameterIndex(size_t i) const {
if (i >= nParams()) {
throw std::out_of_range("ParamFunction parameter index " +
std::to_string(i) + " out of range " +
std::to_string(nParams()));
}
}
/// Keeps status for each parameter.
std::vector<ParameterStatus> m_parameterStatus;
/// Keeps parameter names
std::vector<std::string> m_parameterNames;
/// Keeps parameter values
......
......@@ -325,30 +325,16 @@ std::string CompositeFunction::descriptionOfActive(size_t i) const {
return ostr.str();
}
/**
* query to see in the function is active
* @param i :: The index of a declared parameter
* @return true if parameter i is active
*/
bool CompositeFunction::isFixed(size_t i) const {
size_t iFun = functionIndex(i);
return m_functions[iFun]->isFixed(i - m_paramOffsets[iFun]);
}
/**
* @param i :: A declared parameter index to be removed from active
*/
void CompositeFunction::fix(size_t i) {
/// Change status of parameter
void CompositeFunction::setParameterStatus(size_t i, IFunction::ParameterStatus status) {
size_t iFun = functionIndex(i);
m_functions[iFun]->fix(i - m_paramOffsets[iFun]);
m_functions[iFun]->setParameterStatus(i - m_paramOffsets[iFun], status);
}
/** Makes a parameter active again. It doesn't change the parameter's tie.
* @param i :: A declared parameter index to be restored to active
*/
void CompositeFunction::unfix(size_t i) {
/// Get status of parameter
IFunction::ParameterStatus CompositeFunction::getParameterStatus(size_t i) const {
size_t iFun = functionIndex(i);
m_functions[iFun]->unfix(i - m_paramOffsets[iFun]);
return m_functions[iFun]->getParameterStatus(i - m_paramOffsets[iFun]);
}
/** Makes sure that the function is consistent.
......
#include "MantidCurveFitting/Functions/FunctionGenerator.h"
#include "MantidAPI/FunctionGenerator.h"
#include "MantidAPI/IConstraint.h"
#include "MantidAPI/ParameterTie.h"
namespace Mantid {
namespace CurveFitting {
namespace Functions {
using namespace CurveFitting;
namespace API {
using namespace Kernel;
using namespace API;
/// Constructor
FunctionGenerator::FunctionGenerator(API::IFunction_sptr source)
FunctionGenerator::FunctionGenerator(IFunction_sptr source)
: m_source(source), m_nOwnParams(source->nParams()), m_dirty(true) {
if (!m_source) {
throw std::logic_error(
......@@ -128,30 +123,23 @@ void FunctionGenerator::setError(size_t i, double err) {
}
}
/// Check if a declared parameter i is fixed
bool FunctionGenerator::isFixed(size_t i) const {
checkTargetFunction();
return i < m_nOwnParams ? m_source->isFixed(i)
: m_target->isFixed(i - m_nOwnParams);
}
/// Removes a declared parameter i from the list of active
void FunctionGenerator::fix(size_t i) {
/// Change status of parameter
void FunctionGenerator::setParameterStatus(size_t i, IFunction::ParameterStatus status) {
if (i < m_nOwnParams) {
m_source->fix(i);
m_source->setParameterStatus(i, status);
} else {
checkTargetFunction();
m_target->fix(i - m_nOwnParams);
m_target->setParameterStatus(i - m_nOwnParams, status);
}
}
/// Restores a declared parameter i to the active status
void FunctionGenerator::unfix(size_t i) {
/// Get status of parameter
IFunction::ParameterStatus FunctionGenerator::getParameterStatus(size_t i) const {
if (i < m_nOwnParams) {
m_source->unfix(i);
return m_source->getParameterStatus(i);
} else {
checkTargetFunction();
m_target->unfix(i - m_nOwnParams);
return m_target->getParameterStatus(i - m_nOwnParams);
}
}
......@@ -202,7 +190,7 @@ std::vector<std::string> FunctionGenerator::getAttributeNames() const {
}
/// Return a value of attribute attName
API::IFunction::Attribute
IFunction::Attribute
FunctionGenerator::getAttribute(const std::string &attName) const {
if (IFunction::hasAttribute(attName)) {
return IFunction::getAttribute(attName);
......@@ -244,8 +232,8 @@ bool FunctionGenerator::hasAttribute(const std::string &attName) const {
}
// Evaluates the function
void FunctionGenerator::function(const API::FunctionDomain &domain,
API::FunctionValues &values) const {
void FunctionGenerator::function(const FunctionDomain &domain,
FunctionValues &values) const {
updateTargetFunction();
if (!m_target) {
throw std::logic_error(
......@@ -276,7 +264,7 @@ void FunctionGenerator::checkTargetFunction() const {
}
/// Get the tie for i-th parameter
API::ParameterTie *FunctionGenerator::getTie(size_t i) const {
ParameterTie *FunctionGenerator::getTie(size_t i) const {
auto tie = IFunction::getTie(i);
if (tie == nullptr) {
if (i < m_nOwnParams) {
......@@ -290,7 +278,7 @@ API::ParameterTie *FunctionGenerator::getTie(size_t i) const {
}
/// Get the i-th constraint
API::IConstraint *FunctionGenerator::getConstraint(size_t i) const {
IConstraint *FunctionGenerator::getConstraint(size_t i) const {
auto constraint = IFunction::getConstraint(i);
if (constraint == nullptr) {
if (i < m_nOwnParams) {
......@@ -305,6 +293,5 @@ API::IConstraint *FunctionGenerator::getConstraint(size_t i) const {
} // namespace Functions
} // namespace CurveFitting
} // namespace API
} // namespace Mantid
......@@ -154,24 +154,6 @@ void FunctionParameterDecorator::setError(size_t i, double err) {
return m_wrappedFunction->setError(i, err);
}
bool FunctionParameterDecorator::isFixed(size_t i) const {
throwIfNoFunctionSet();
return m_wrappedFunction->isFixed(i);
}
void FunctionParameterDecorator::fix(size_t i) {
throwIfNoFunctionSet();
m_wrappedFunction->fix(i);
}
void FunctionParameterDecorator::unfix(size_t i) {
throwIfNoFunctionSet();
m_wrappedFunction->unfix(i);
}
size_t FunctionParameterDecorator::getParameterIndex(
const ParameterReference &ref) const {
throwIfNoFunctionSet();
......@@ -222,11 +204,16 @@ bool FunctionParameterDecorator::hasAttribute(
return m_wrappedFunction->hasAttribute(attName);
}
void FunctionParameterDecorator::tie(const std::string &parName,
const std::string &expr, bool isDefault) {
void FunctionParameterDecorator::setParameterStatus(
size_t i, IFunction::ParameterStatus status) {
throwIfNoFunctionSet();
m_wrappedFunction->setParameterStatus(i, status);
}
m_wrappedFunction->tie(parName, expr, isDefault);
IFunction::ParameterStatus
FunctionParameterDecorator::getParameterStatus(size_t i) const {
throwIfNoFunctionSet();
return m_wrappedFunction->getParameterStatus(i);
}
void FunctionParameterDecorator::applyTies() {
......@@ -299,6 +286,12 @@ void FunctionParameterDecorator::declareParameter(
UNUSED_ARG(description);
}
void FunctionParameterDecorator::tie(const std::string &parName,
const std::string &expr, bool isDefault) {
throwIfNoFunctionSet();
m_wrappedFunction->tie(parName, expr, isDefault);
}
/// Forwads addTie-call to the decorated function.
void FunctionParameterDecorator::addTie(std::unique_ptr<ParameterTie> tie) {
throwIfNoFunctionSet();
......
......@@ -107,7 +107,44 @@ void IFunction::functionDeriv(const FunctionDomain &domain,
* @param i :: Index of a parameter.
*/
bool IFunction::isActive(size_t i) const {
return !(isFixed(i) || getTie(i) != nullptr);
return getParameterStatus(i) == Active;
}
/**
* Query if the parameter is fixed
* @param i :: The index of a declared parameter
* @return true if parameter i is active
*/
bool IFunction::isFixed(size_t i) const {
if (i >= nParams()) {
throw std::out_of_range("Parameter index " + std::to_string(i) +
" out of range " + std::to_string(nParams()));
}
return getParameterStatus(i) == Fixed;
}
/** This method doesn't create a tie
* @param i :: A declared parameter index to be fixed
*/
void IFunction::fix(size_t i) {
auto status = getParameterStatus(i);
if (status == Tied) {
throw std::runtime_error("Cannot fix parameter " + std::to_string(i) +
" (" + parameterName(i) + "): it has a tie.");
}
setParameterStatus(i, Fixed);
}
/** Makes a parameter active again. It doesn't change the parameter's tie.
* @param i :: A declared parameter index to be restored to active
*/
void IFunction::unfix(size_t i) {
auto status = getParameterStatus(i);
if (status == Tied) {
throw std::runtime_error("Cannot unfix parameter " + std::to_string(i) +
" (" + parameterName(i) + "): it has a tie.");
}
setParameterStatus(i, Active);
}
/**
......@@ -187,6 +224,7 @@ std::string IFunction::writeTies() const {
* @param tie :: A pointer to a new tie
*/
void IFunction::addTie(std::unique_ptr<ParameterTie> tie) {
auto iPar = getParameterIndex(*tie);
bool found = false;
for (auto &m_tie : m_ties) {
......@@ -199,6 +237,7 @@ void IFunction::addTie(std::unique_ptr<ParameterTie> tie) {
}
if (!found) {
m_ties.push_back(std::move(tie));
setParameterStatus(iPar, Tied);
}
}
......@@ -242,7 +281,7 @@ bool IFunction::removeTie(size_t i) {
auto it = std::find_if(m_ties.begin(), m_ties.end(), ReferenceEqual(*this, i));
if (it != m_ties.end()) {
m_ties.erase(it);
unfix(i);
setParameterStatus(i, Active);
return true;
}
unfix(i);
......@@ -268,7 +307,7 @@ ParameterTie *IFunction::getTie(size_t i) const {
*/
void IFunction::clearTies() {
for (size_t i = 0; i < nParams(); ++i) {
unfix(i);
setParameterStatus(i, Active);
}
m_ties.clear();
}
......
......@@ -37,9 +37,7 @@ void ParamFunction::setParameter(size_t i, const double &value,
g_log.warning(errmsg.str());
}
if (i >= nParams()) {
throw std::out_of_range("ParamFunction parameter index out of range.");
}
checkParameterIndex(i);
if (explicitlySet && value != m_parameters[i]) {
m_explicitlySet[i] = true;
}
......@@ -52,9 +50,7 @@ void ParamFunction::setParameter(size_t i, const double &value,
*/
void ParamFunction::setParameterDescription(size_t i,
const std::string &description) {
if (i >= nParams()) {
throw std::out_of_range("ParamFunction parameter index out of range.");
}
checkParameterIndex(i);
m_parameterDescriptions[i] = description;
}
......@@ -63,9 +59,7 @@ void ParamFunction::setParameterDescription(size_t i,
* @return the value of the requested parameter
*/
double ParamFunction::getParameter(size_t i) const {
if (i >= nParams()) {
throw std::out_of_range("ParamFunction parameter index out of range.");
}
checkParameterIndex(i);
return m_parameters[i];
}
......@@ -164,9 +158,7 @@ size_t ParamFunction::parameterIndex(const std::string &name) const {
* @return the name of the parameter at the requested index
*/
std::string ParamFunction::parameterName(size_t i) const {
if (i >= nParams()) {
throw std::out_of_range("ParamFunction parameter index out of range.");
}
checkParameterIndex(i);
return m_parameterNames[i];
}
......@@ -175,9 +167,7 @@ std::string ParamFunction::parameterName(size_t i) const {
* @return the description of the parameter at the requested index
*/
std::string ParamFunction::parameterDescription(size_t i) const {
if (i >= nParams()) {
throw std::out_of_range("ParamFunction parameter index out of range.");
}
checkParameterIndex(i);
return m_parameterDescriptions[i];
}
......@@ -187,9 +177,7 @@ std::string ParamFunction::parameterDescription(size_t i) const {
* @return :: the error
*/