예제 #1
0
    /** 
     * Create a function from an expression.
     * @param expr :: The input expression
     * @param parentAttributes :: An output map filled with the attribute name & values of the parent function
     * @return A pointer to the created function
     */
    IFunction_sptr FunctionFactoryImpl::createSimple(const Expression& expr, std::map<std::string,std::string>& parentAttributes)const
    {
      if (expr.name() == "=" && expr.size() > 1)
      {
        return createFunction(expr.terms()[1].name());
      }

      if (expr.name() != "," || expr.size() == 0)
      {
        inputError(expr.str());
      }

      const std::vector<Expression>& terms = expr.terms();
      std::vector<Expression>::const_iterator term = terms.begin();

      if (term->name() != "=") inputError(expr.str());
      if (term->terms()[0].name() != "name" && term->terms()[0].name() != "composite")
      {
        throw std::invalid_argument("Function name must be defined before its parameters");
      }
      std::string fnName = term->terms()[1].name();

      IFunction_sptr fun = createFunction(fnName);
      for(++term;term!=terms.end();++term)
      {// loop over function's parameters/attributes
        if (term->name() != "=") inputError(expr.str());
        std::string parName = term->terms()[0].name();
        std::string parValue = term->terms()[1].str();
        if (fun->hasAttribute(parName))
        {// set attribute
          if (parValue.size() > 1 && parValue[0] == '"')
          {// remove the double quotes
            parValue = parValue.substr(1,parValue.size()-2);
          }
          IFunction::Attribute att = fun->getAttribute(parName);
          att.fromString(parValue);
          fun->setAttribute(parName,att);
        }
        else if (parName.size() >= 10 && parName.substr(0,10) == "constraint")
        {// or it can be a list of constraints
          addConstraints(fun,(*term)[1]);
        }
        else if (parName == "ties")
        {
          addTies(fun,(*term)[1]);
        }
        else if (!parName.empty() && parName[0] == '$')
        {
          parName.erase(0,1);
          parentAttributes[parName] = parValue;
        }
        else
        {// set initial parameter value
          fun->setParameter(parName,atof(parValue.c_str()));
        }
      }// for term

      fun->applyTies();
      return fun;
    }
예제 #2
0
void ChFun::setAttribute(const std::string& attName,const IFunction::Attribute& att)
{
  IFunction1D::setAttribute( attName, att );
  if ( attName == "n" )
  {
    reset( att.asInt() );
  }
  else if ( attName == "StartX" )
  {
    set( n(), att.asDouble(), endX() );
  }
  else if ( attName == "EndX" )
  {
    set( n(), startX(), att.asDouble() );
  }
}
예제 #3
0
/**
 * Set a value to a "local" attribute, ie an attribute related to a member
 *function.
 *
 * The only attribute that can be set here is "domains" which defines the
 * indices of domains a particular function is applied to. Possible values are
 *(strings):
 *
 *     1) "All" : the function is applied to all domains defined for this
 *MultiDomainFunction.
 *     2) "i"   : the function is applied to a single domain which index is
 *equal to the
 *                function's index in this MultiDomainFunction.
 *     3) "non-negative integer" : a domain index.
 *     4) "a,b,c,..." : a list of domain indices (a,b,c,.. are non-negative
 *integers).
 *     5) "a - b" : a range of domain indices (a,b are non-negative integers a
 *<= b).
 *
 * To be used with Fit algorithm at least one of the member functions must have
 *"domains" value
 * of type 2), 3), 4) or 5) because these values can tell Fit how many domains
 *need to be created.
 *
 * @param i :: Index of a function for which the attribute is being set.
 * @param attName :: Name of an attribute.
 * @param att :: Value of the attribute to set.
 */
void MultiDomainFunction::setLocalAttribute(size_t i,
                                            const std::string &attName,
                                            const IFunction::Attribute &att) {
  if (attName != "domains") {
    throw std::invalid_argument("MultiDomainFunction does not have attribute " +
                                attName);
  }
  if (i >= nFunctions()) {
    throw std::out_of_range("Function index is out of range.");
  }
  std::string value = att.asString();
  auto it = m_domains.find(i);

  if (value == "All") { // fit to all domains
    if (it != m_domains.end()) {
      m_domains.erase(it);
    }
    return;
  } else if (value ==
             "i") { // fit to domain with the same index as the function
    setDomainIndex(i, i);
    return;
  } else if (value.empty()) { // do not fit to any domain
    setDomainIndices(i, std::vector<size_t>());
    return;
  }

  // fit to a selection of domains
  std::vector<size_t> indx;
  Expression list;
  list.parse(value);
  if (list.name() == "+") {
    if (list.size() != 2 || list.terms()[1].operator_name() != "-") {
      throw std::runtime_error("MultiDomainFunction: attribute \"domains\" "
                               "expects two integers separated by a \"-\"");
    }
    // value looks like "a - b". a and b must be ints and define a range of
    // domain indices
    size_t start = boost::lexical_cast<size_t>(list.terms()[0].str());
    size_t end = boost::lexical_cast<size_t>(list.terms()[1].str()) + 1;
    if (start >= end) {
      throw std::runtime_error(
          "MultiDomainFunction: attribute \"domains\": wrong range limits.");
    }
    indx.resize(end - start);
    for (size_t i = start; i < end; ++i) {
      indx[i - start] = i;
    }
  } else {
    // value must be either an int or a list of ints: "a,b,c,..."
    list.toList();
    for (size_t k = 0; k < list.size(); ++k) {
      indx.push_back(boost::lexical_cast<size_t>(list[k].name()));
    }
  }
  setDomainIndices(i, indx);
}
/// Perform a castom action when an attribute is set.
void CrystalFieldPeaksBase::setAttribute(const std::string &name,
                                         const IFunction::Attribute &attr) {
  if (name == "Symmetry") {
    auto symmIter = SYMMETRY_MAP.find(attr.asString());
    if (symmIter == SYMMETRY_MAP.end()) {
      throw std::runtime_error("Unknown symmetry passed to CrystalFieldPeaks.");
    }
    symmIter->second(*this);
  }
  IFunction::setAttribute(name, attr);
}
예제 #5
0
  /**
   * Set a value to attribute attName
   */
  void MultiDomainFunction::setLocalAttribute(size_t i, const std::string& attName,const IFunction::Attribute& att)
  {
    if (attName != "domains")
    {
      throw std::invalid_argument("MultiDomainFunction does not have attribute " + attName);
    }
    if (i >= nFunctions())
    {
      throw std::out_of_range("Function index is out of range.");
    }
    std::string value = att.asString();
    auto it = m_domains.find(i);

    if (value == "All")
    {// fit to all domains
      if (it != m_domains.end())
      {
        m_domains.erase(it);
      }
      return;
    }
    else if (value == "i")
    {// fit to domain with the same index as the function
      setDomainIndex(i,i);
      return;
    }
    else if (value.empty())
    {// do not fit to any domain
      setDomainIndices(i,std::vector<size_t>());
    }
    // fit to a selection of domains
    std::vector<size_t> indx;
    Expression list;
    list.parse(value);
    list.toList();
    for(size_t k = 0; k < list.size(); ++k)
    {
      indx.push_back(boost::lexical_cast<size_t>(list[k].name()));
    }
    setDomainIndices(i,indx);
  }