Commit 8dc18645 authored by Stephen's avatar Stephen
Browse files

Add ability to set prefixed attributes

parent e37c6821
......@@ -83,9 +83,13 @@ public:
bool hasAttribute(const std::string &name) const override;
/// Return a value of attribute attName
Attribute getAttribute(const std::string &name) const override;
// Set an attribute value
void setAttribute(const std::string &name,
const API::IFunction::Attribute &value) override;
/// Total number of parameters
size_t nParams() const override;
// Total number of attributes, which includes global and local function attributes
// Total number of attributes, which includes global and local function
// attributes
size_t nAttributes() const override;
// Total number of global attributes, defined at the composite function level
size_t nGlobalAttributes() const noexcept { return IFunction::nAttributes(); }
......@@ -172,7 +176,7 @@ public:
/// Remove all member functions
void clear();
//std::vector < std::string> getAttributeNames() const override;
// std::vector < std::string> getAttributeNames() const override;
/// Returns the number of attributes associated with the function
virtual size_t nLocalAttributes() const { return 0; }
/// Returns a list of attribute names
......@@ -216,9 +220,9 @@ protected:
void declareParameter(const std::string &name, double initValue = 0,
const std::string &description = "") override;
/// Declare a single attribute
/// Declare a single attribute
void declareAttribute(const std::string &name,
const API::IFunction::Attribute &defaultValue) override;
const API::IFunction::Attribute &defaultValue) override;
/// Writes itself into a string
std::string writeToString(
const std::string &parentLocalAttributesStr = "") const override;
......
......@@ -295,20 +295,34 @@ CompositeFunction::getAttribute(const std::string &name) const {
try {
if (std::find(m_globalAttributeNames.begin(), m_globalAttributeNames.end(),
name) != m_globalAttributeNames.end()) {
// Attribute is defined on the composite function, call parent method
return IFunction::getAttribute(name);
}
// Else assume that attribute is of the form fk.Attribute, so we need to
// parse the name
auto [attributeName, index] = parseName(name);
return m_functions[index]->getAttribute(attributeName);
} catch (...) {
} catch (std::invalid_argument &) {
throw std::invalid_argument(
"ParamFunctionAttributeHolder::getAttribute - Unknown attribute '" +
name + "'");
}
}
/**
* Set a value to a named attribute. Can be overridden in the inheriting class,
* the default
* just stores the value
* @param name :: The name of the attribute
* @param value :: The value of the attribute
*/
void CompositeFunction::setAttribute(const std::string &name,
const API::IFunction::Attribute &value) {
if (std::find(m_globalAttributeNames.begin(), m_globalAttributeNames.end(),
name) != m_globalAttributeNames.end()) {
return IFunction::setAttribute(name, value);
}
auto [attributeName, index] = parseName(name);
return m_functions[index]->setAttribute(attributeName, value);
}
/// Total number of parameters
size_t CompositeFunction::nParams() const { return m_nParams; }
......
......@@ -1342,9 +1342,9 @@ void IFunction::setAttributeValue(const std::string &attName,
*/
void IFunction::setAttributeValue(const std::string &attName,
const std::string &value) {
Attribute att = getAttribute(attName);
Attribute att = this->getAttribute(attName);
att.setString(value);
setAttribute(attName, att);
this->setAttribute(attName, att);
}
/// Returns the pointer to a child function
......
......@@ -92,8 +92,7 @@ private:
size_t m_blocksize;
};
template<bool withAttributes=false>
class Gauss : public IPeakFunction {
template <bool withAttributes = false> class Gauss : public IPeakFunction {
public:
Gauss() {
declareParameter("c");
......@@ -1256,7 +1255,7 @@ public:
TS_ASSERT_EQUALS(fun->parameterLocalName(6, true), "a");
}
void test_attributes_generated_with_correct_prefix() {
void test_attributes_generated_with_correct_prefix() {
auto mfun = std::make_unique<CompositeFunction>();
auto gauss = std::make_shared<Gauss<true>>();
auto background = std::make_shared<Linear<true>>();
......@@ -1310,7 +1309,6 @@ public:
TS_ASSERT_EQUALS(names[1], "f0.GaussAttribute");
TS_ASSERT_EQUALS(names[2], "f1.LinearAttribute");
TS_ASSERT_EQUALS(names[3], "f2.CubicAttribute");
}
void test_as_string_preserves_attributes() {
......@@ -1330,4 +1328,55 @@ public:
TS_ASSERT_EQUALS(mfun->asString(), str);
}
void test_set_attribute_supports_prefixed_attributes() {
auto mfun = std::make_unique<CompositeFunction>();
auto gauss = std::make_shared<Gauss<true>>();
auto background = std::make_shared<Linear<true>>();
auto cubic = std::make_shared<Cubic<true>>();
mfun->addFunction(gauss);
mfun->addFunction(background);
mfun->addFunction(cubic);
mfun->setAttribute("f2.CubicAttribute",
IFunction::Attribute("NewCubicAttribute"));
mfun->setAttribute("f1.LinearAttribute",
IFunction::Attribute("NewLinearAttribute"));
TS_ASSERT_EQUALS(mfun->getAttribute("f2.CubicAttribute").asString(),
"NewCubicAttribute");
TS_ASSERT_EQUALS(mfun->getAttribute("f1.LinearAttribute").asString(),
"NewLinearAttribute");
}
void test_set_attribute_supports_unprefixed_attributes() {
auto mfun = std::make_unique<CompositeFunction>();
auto gauss = std::make_shared<Gauss<true>>();
auto background = std::make_shared<Linear<true>>();
auto cubic = std::make_shared<Cubic<true>>();
mfun->addFunction(gauss);
mfun->addFunction(background);
mfun->addFunction(cubic);
// Set the global NumDeriv attribute
mfun->setAttribute("NumDeriv", IFunction::Attribute(true));
TS_ASSERT_EQUALS(mfun->getAttribute("NumDeriv").asBool(), true);
}
void test_set_attribute_thorws_if_attribute_not_recongized() {
auto mfun = std::make_unique<CompositeFunction>();
auto gauss = std::make_shared<Gauss<true>>();
auto background = std::make_shared<Linear<true>>();
auto cubic = std::make_shared<Cubic<true>>();
mfun->addFunction(gauss);
mfun->addFunction(background);
mfun->addFunction(cubic);
TS_ASSERT_THROWS(
mfun->setAttribute("f0.CubicAttribute",
IFunction::Attribute("NewCubicAttribute")),
std::invalid_argument &);
}
};
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment