TEST(FunctionFactoryTest, CreateCompositeFunctionTest)
{
  std::string ini = "CompositeFunction("
    "FunctionFactoryTestFunction(A=10,B=20),"
    "FunctionFactoryTestFunction(A=30,B=40)"
    ")";
  IFunction_sptr fun = FunctionFactory::instance().createFitFunction(ini);
  EXPECT_TRUE( fun.get() != nullptr );
  CompositeFunction_sptr cf = boost::dynamic_pointer_cast<CompositeFunction>(fun);
  EXPECT_TRUE( cf.get() != nullptr );
  EXPECT_EQ( cf->nFunctions(), 2 );
  auto f1 = cf->getFunction(0);
  auto f2 = cf->getFunction(1);
  EXPECT_EQ(f1->getParameter("A"),10);
  EXPECT_EQ(f1->getParameter("B"),20);
  EXPECT_EQ(f2->getParameter("A"),30);
  EXPECT_EQ(f2->getParameter("B"),40);
  EXPECT_EQ(cf->getParameter("f0.A"),10);
  EXPECT_EQ(cf->getParameter("f0.B"),20);
  EXPECT_EQ(cf->getParameter("f1.A"),30);
  EXPECT_EQ(cf->getParameter("f1.B"),40);

  std::cerr << '\n' << fun->asString(true) << '\n' << std::endl;

  IFunction_sptr fun1 = FunctionFactory::instance().createFitFunction(ini);
  EXPECT_TRUE( fun1.get() != nullptr );
  cf = boost::dynamic_pointer_cast<CompositeFunction>(fun1);
  EXPECT_TRUE( cf.get() != nullptr );
  EXPECT_EQ( cf->nFunctions(), 2 );
  EXPECT_EQ(cf->getParameter("f0.A"),10);
  EXPECT_EQ(cf->getParameter("f0.B"),20);
  EXPECT_EQ(cf->getParameter("f1.A"),30);
  EXPECT_EQ(cf->getParameter("f1.B"),40);

}
  /**
   * Initialize diagnosis table.
   */
  void MuonSequentialFitDialog::initDiagnosisTable()
  {
    QStringList headerLabels;

    // Add two static columns 
    headerLabels << "Run" << "Fit quality";

    // Add remaining columns - one for every fit function parameter
    IFunction_sptr fitFunc = m_fitPropBrowser->getFittingFunction();

    for(size_t i = 0; i < fitFunc->nParams(); i++)
    {
      QString paramName = QString::fromStdString( fitFunc->parameterName(i) ); 
      headerLabels << paramName;
      headerLabels << paramName + "_Err";
    }

    m_ui.diagnosisTable->setColumnCount( headerLabels.size() );
    m_ui.diagnosisTable->setHorizontalHeaderLabels(headerLabels);

    // Make the table fill all the available space and columns be resized to fit contents
    m_ui.diagnosisTable->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);

    // Make rows alternate bg colors for better user experience 
    m_ui.diagnosisTable->setAlternatingRowColors(true);
  }
Example #3
0
IFunction_sptr IqtFit::createUserFunction(const QString &name, bool tie) {
  IFunction_sptr result =
      FunctionFactory::Instance().createFunction("UserFunction");
  std::string formula;

  if (name.startsWith("Exp")) {
    formula = "Intensity*exp(-(x/Tau))";
  } else {
    formula = "Intensity*exp(-(x/Tau)^Beta)";
  }

  IFunction::Attribute att(formula);
  result->setAttribute("Formula", att);

  QList<QtProperty *> props = m_properties[name]->subProperties();
  for (int i = 0; i < props.size(); i++) {
    std::string name = props[i]->propertyName().toStdString();
    result->setParameter(name, m_dblManager->value(props[i]));

    // add tie if parameter is fixed
    if (tie || !props[i]->subProperties().isEmpty()) {
      std::string value = props[i]->valueText().toStdString();
      result->tie(name, value);
    }
  }

  result->applyTies();
  return result;
}
  /** Restore function parameter values saved in a (string,double) map to a function object
    * and a (string, Parameter) map
    */
  void restoreFunctionParameterValue(map<string, pair<double, double> > parvaluemap, IFunction_sptr function,
                                     map<string, Parameter>& parammap)
  {
    vector<string> parnames = function->getParameterNames();

    for (size_t i = 0; i < parnames.size(); ++i)
    {
      string& parname = parnames[i];
      map<string, pair<double, double> >::iterator miter;
      miter = parvaluemap.find(parname);

      if (miter != parvaluemap.end())
      {
        double parvalue = miter->second.first;
        double parerror = miter->second.second;

        // 1. Function
        function->setParameter(parname, parvalue);

        // 2. Parameter map
        map<string, Parameter>::iterator pariter = parammap.find(parname);
        if (pariter != parammap.end())
        {
          // Find the entry
          pariter->second.value = parvalue;
          pariter->second.error = parerror;
        }
      }
    }

    return;
  }
  /** Calculate Chi^2 of the a function with all parameters are fixed
    */
  double RefinePowderInstrumentParameters2::calculateFunctionError(IFunction_sptr function,
                                                                   Workspace2D_sptr dataws, int wsindex)
  {
    // 1. Record the fitting information
    vector<string> parnames = function->getParameterNames();
    vector<bool> vecFix(parnames.size(), false);

    for (size_t i = 0; i < parnames.size(); ++i)
    {
      bool fixed = function->isFixed(i);
      vecFix[i] = fixed;
      if (!fixed)
        function->fix(i);
    }

    // 2. Fit with zero iteration
    double chi2;
    string fitstatus;
    doFitFunction(function, dataws, wsindex, "Levenberg-MarquardtMD", 0, chi2, fitstatus);

    // 3. Restore the fit/fix setup
    for (size_t i = 0; i < parnames.size(); ++i)
    {
      if (!vecFix[i])
        function->unfix(i);
    }

    return chi2;
  }
  /**
   * Add a new entry to the diagnosis table.
   * @param runTitle       :: Title of the run fitted
   * @param fitQuality     :: Number representing a goodness of the fit
   * @param fittedFunction :: Function containing fitted parameters 
   */
  void MuonSequentialFitDialog::addDiagnosisEntry(const std::string& runTitle, double fitQuality,
      IFunction_sptr fittedFunction)
  {
    int newRow = m_ui.diagnosisTable->rowCount();

    m_ui.diagnosisTable->insertRow(newRow);

    QString runTitleDisplay = QString::fromStdString(runTitle);
    m_ui.diagnosisTable->setItem( newRow, 0, createTableWidgetItem(runTitleDisplay) );

    QString fitQualityDisplay = QString::number(fitQuality);
    m_ui.diagnosisTable->setItem( newRow, 1, createTableWidgetItem(fitQualityDisplay) );

    for(int i = 2; i < m_ui.diagnosisTable->columnCount(); i += 2)
    {
      std::string paramName = m_ui.diagnosisTable->horizontalHeaderItem(i)->text().toStdString();
      size_t paramIndex = fittedFunction->parameterIndex(paramName);

      QString value = QString::number( fittedFunction->getParameter(paramIndex) );
      QString error = QString::number( fittedFunction->getError(paramIndex) );

      m_ui.diagnosisTable->setItem(newRow, i, createTableWidgetItem(value) );
      m_ui.diagnosisTable->setItem(newRow, i + 1, createTableWidgetItem(error) );
    }

    m_ui.diagnosisTable->scrollToBottom();
  }
Example #7
0
  /** Add function's parameter names after peak function name
    */
  std::vector<std::string> GeneratePeaks::addFunctionParameterNames(std::vector<std::string> funcnames)
  {
    std::vector<std::string> vec_funcparnames;

    for (size_t i = 0; i < funcnames.size(); ++i)
    {
      // Add original name in
      vec_funcparnames.push_back(funcnames[i]);

      // Add a full function name and parameter names in
      IFunction_sptr tempfunc = FunctionFactory::Instance().createFunction(funcnames[i]);

      std::stringstream parnamess;
      parnamess << funcnames[i] << " (";
      std::vector<std::string> funcpars = tempfunc->getParameterNames();
      for (size_t j = 0; j < funcpars.size(); ++j)
      {
        parnamess << funcpars[j];
        if (j != funcpars.size()-1)
          parnamess << ", ";
      }
      parnamess << ")";

      vec_funcparnames.push_back(parnamess.str());
    }

    return vec_funcparnames;
  }
/* Propagate the attribute to its member functions.
 * NOTE: we pass this->getAttribute(name) by reference, thus the same
 * object is shared by the composite function and its members.
 */
void DiffSphere::trickleDownAttribute(const std::string &name) {
  for (size_t iFun = 0; iFun < nFunctions(); iFun++) {
    IFunction_sptr fun = getFunction(iFun);
    if (fun->hasAttribute(name)) {
      fun->setAttribute(name, this->getAttribute(name));
    }
  }
}
TEST(FunctionFactoryTest, CreateFitFunctionTest)
{
  IFunction_sptr fun = FunctionFactory::instance().createFitFunction("FunctionFactoryTestFunction(A=10,B=20)");
  EXPECT_TRUE( fun.get() != nullptr );
  EXPECT_EQ(fun->getParameter("A"),10);
  EXPECT_EQ(fun->getParameter("B"),20);
  //std::cerr << fun->asString() << std::endl;
}
/**
 * Returns the shrared pointer to the function conataining a parameter
 * @param ref :: The reference
 * @return A function containing parameter pointed to by ref
 */
IFunction_sptr
CompositeFunction::getContainingFunction(const ParameterReference &ref) const {
  for (size_t iFun = 0; iFun < nFunctions(); iFun++) {
    IFunction_sptr fun = getFunction(iFun);
    if (fun->getParameterIndex(ref) < fun->nParams()) {
      return fun;
    }
  }
  return IFunction_sptr();
}
Example #11
0
/**
 * Gets a list of parameters for a given fit function.
 *
 * @return List fo parameters
 */
QStringList JumpFit::getFunctionParameters(const QString &functionName) {
  QStringList parameters;

  IFunction_sptr func =
      FunctionFactory::Instance().createFunction(functionName.toStdString());

  for (size_t i = 0; i < func->nParams(); i++)
    parameters << QString::fromStdString(func->parameterName(i));

  return parameters;
}
  /** Fit function
    * Minimizer: "Levenberg-MarquardtMD"/"Simplex"
   */
  bool RefinePowderInstrumentParameters2::doFitFunction(IFunction_sptr function, Workspace2D_sptr dataws, int wsindex,
                                                        string minimizer, int numiters, double& chi2, string& fitstatus)
  {
    // 0. Debug output
    stringstream outss;
    outss << "Fit function: " << m_positionFunc->asString() << endl << "Data To Fit: \n";
    for (size_t i = 0; i < dataws->readX(0).size(); ++i)
      outss << dataws->readX(wsindex)[i] << "\t\t" << dataws->readY(wsindex)[i] << "\t\t"
            << dataws->readE(wsindex)[i] << "\n";
    g_log.information() << outss.str();

    // 1. Create and setup fit algorithm
    API::IAlgorithm_sptr fitalg = createChildAlgorithm("Fit", 0.0, 0.2, true);
    fitalg->initialize();

    fitalg->setProperty("Function", function);
    fitalg->setProperty("InputWorkspace", dataws);
    fitalg->setProperty("WorkspaceIndex", wsindex);
    fitalg->setProperty("Minimizer", minimizer);
    fitalg->setProperty("CostFunction", "Least squares");
    fitalg->setProperty("MaxIterations", numiters);
    fitalg->setProperty("CalcErrors", true);

    // 2. Fit
    bool successfulfit = fitalg->execute();
    if (!fitalg->isExecuted() || ! successfulfit)
    {
      // Early return due to bad fit
      g_log.warning("Fitting to instrument geometry function failed. ");
      chi2 = DBL_MAX;
      fitstatus = "Minimizer throws exception.";
      return false;
    }

    // 3. Understand solution
    chi2 = fitalg->getProperty("OutputChi2overDoF");
    string tempfitstatus = fitalg->getProperty("OutputStatus");
    fitstatus = tempfitstatus;

    bool goodfit = fitstatus.compare("success") == 0;

    stringstream dbss;
    dbss << "Fit Result (GSL):  Chi^2 = " << chi2
         << "; Fit Status = " << fitstatus << ", Return Bool = " << goodfit << std::endl;
    vector<string> funcparnames = function->getParameterNames();
    for (size_t i = 0; i < funcparnames.size(); ++i)
      dbss << funcparnames[i] << " = " << setw(20) << function->getParameter(funcparnames[i])
           << " +/- " << function->getError(i) << "\n";
    g_log.debug() << dbss.str();

    return goodfit;
  }
  /** Set parameter fitting setup (boundary, fix or unfix) to function from Parameter map
   */
  void RefinePowderInstrumentParameters2::setFunctionParameterFitSetups(IFunction_sptr function,
                                                                        map<string, Parameter> params)
  {
    // 1. Prepare
    vector<string> funparamnames = m_positionFunc->getParameterNames();

    // 2. Set up
    std::map<std::string, Parameter>::iterator paramiter;
    for (size_t i = 0; i < funparamnames.size(); ++i)
    {
      string parname = funparamnames[i];
      paramiter = params.find(parname);

      if (paramiter != params.end())
      {
        // Found, set up the parameter
        Parameter& param = paramiter->second;
        if (param.fit)
        {
          // If fit.  Unfix it and set up constraint
          function->unfix(i);

          double lowerbound = param.minvalue;
          double upperbound = param.maxvalue;
          if (lowerbound >= -DBL_MAX*0.1 || upperbound <= DBL_MAX*0.1)
          {
            // If there is a boundary
            BoundaryConstraint *bc = new BoundaryConstraint(function.get(), parname, lowerbound,
                                                            upperbound, false);
            function->addConstraint(bc);
          }
        }
        else
        {
          // If fix.
          function->fix(i);
        }
      }
      else
      {
        // Not found and thus quit
        stringstream errss;
        errss << "Peak profile parameter " << parname << " is not found in input parameters. ";
        g_log.error(errss.str());
        throw runtime_error(errss.str());
      }
    } // ENDFOR parameter name

    g_log.notice() << "Fit function:\n" << function->asString() << "\n";

    return;
  }
/** Add a function
 * @param f :: A pointer to the added function
 * @return The function index
 */
size_t CompositeFunction::addFunction(IFunction_sptr f) {
  m_IFunction.insert(m_IFunction.end(), f->nParams(), m_functions.size());
  m_functions.push_back(f);
  //?f->init();
  if (m_paramOffsets.empty()) {
    m_paramOffsets.push_back(0);
    m_nParams = f->nParams();
  } else {
    m_paramOffsets.push_back(m_nParams);
    m_nParams += f->nParams();
  }
  return m_functions.size() - 1;
}
/**
 * Gets the new attribute values to be updated in the function and in the fit
 * property browser.
 * @param function        The function containing the attributes
 * @param attributeNames  The names of the attributes to update
 */
std::unordered_map<std::string, IFunction::Attribute>
IndirectFitAnalysisTab::getAttributes(
    IFunction_sptr const &function,
    std::vector<std::string> const &attributeNames) {
  std::unordered_map<std::string, IFunction::Attribute> attributes;
  for (auto const &name : attributeNames)
    if (function->hasAttribute(name))
      attributes[name] =
          name == "WorkspaceIndex"
              ? IFunction::Attribute(m_fitPropertyBrowser->workspaceIndex())
              : function->getAttribute(name);
  return attributes;
}
Example #16
0
/// Returns a TableWorkspace with refined cell parameters and error.
ITableWorkspace_sptr PoldiFitPeaks2D::getRefinedCellParameters(
    const IFunction_sptr &fitFunction) const {
  Poldi2DFunction_sptr poldi2DFunction =
      boost::dynamic_pointer_cast<Poldi2DFunction>(fitFunction);

  if (!poldi2DFunction || poldi2DFunction->nFunctions() < 1) {
    throw std::invalid_argument(
        "Cannot process function that is not a Poldi2DFunction.");
  }

  // Create a new table for lattice parameters
  ITableWorkspace_sptr latticeParameterTable =
      WorkspaceFactory::Instance().createTable();

  latticeParameterTable->addColumn("str", "Parameter");
  latticeParameterTable->addColumn("double", "Value");
  latticeParameterTable->addColumn("double", "Error");

  // The first function should be PoldiSpectrumPawleyFunction
  boost::shared_ptr<PoldiSpectrumPawleyFunction> poldiPawleyFunction =
      boost::dynamic_pointer_cast<PoldiSpectrumPawleyFunction>(
          poldi2DFunction->getFunction(0));

  if (!poldiPawleyFunction) {
    throw std::invalid_argument("First function in Poldi2DFunction is not "
                                "PoldiSpectrumPawleyFunction.");
  }

  // Get the actual PawleyFunction to extract parameters.
  IPawleyFunction_sptr pawleyFunction =
      boost::dynamic_pointer_cast<IPawleyFunction>(
          poldiPawleyFunction->getDecoratedFunction());

  if (pawleyFunction) {
    CompositeFunction_sptr pawleyParts =
        boost::dynamic_pointer_cast<CompositeFunction>(
            pawleyFunction->getDecoratedFunction());

    // The first function in PawleyFunction contains the parameters
    IFunction_sptr pawleyParameters = pawleyParts->getFunction(0);

    for (size_t i = 0; i < pawleyParameters->nParams(); ++i) {
      TableRow newRow = latticeParameterTable->appendRow();
      newRow << pawleyParameters->parameterName(i)
             << pawleyParameters->getParameter(i)
             << pawleyParameters->getError(i);
    }
  }

  return latticeParameterTable;
}
/**
 * Returns the index of parameter if the ref points to one of the member
 * function
 * @param ref :: A reference to a parameter
 * @return Parameter index or number of nParams() if parameter not found
 */
size_t
CompositeFunction::getParameterIndex(const ParameterReference &ref) const {
  if (ref.getLocalFunction() == this && ref.getLocalIndex() < nParams()) {
    return ref.getLocalIndex();
  }
  for (size_t iFun = 0; iFun < nFunctions(); iFun++) {
    IFunction_sptr fun = getFunction(iFun);
    size_t iLocalIndex = fun->getParameterIndex(ref);
    if (iLocalIndex < fun->nParams()) {
      return m_paramOffsets[iFun] + iLocalIndex;
    }
  }
  return nParams();
}
TEST(FunctionFactoryTest, CreateFitFunction_with_brackets_Test)
{
  IFunction_sptr fun = FunctionFactory::instance().createFitFunction("FunctionFactoryTestFunction()");
  EXPECT_TRUE( fun.get() != nullptr );
  //Function1DTestFunction fun;
  FunctionDomain1DVector domain(0.0,1.0,10);
  FunctionValues values(domain);
  fun->function(domain,values);
  for(size_t i = 0; i < domain.size(); ++i)
  {
    double x = domain[i];
    EXPECT_EQ( 1.0 * x - 3.0, values.getCalculated(i));
  }
}
/**
 * Add a new workspace to the fit. The workspace is in the property named
 * workspacePropertyName.
 * @param workspacePropertyName :: A workspace property name (eg InputWorkspace
 *   or InputWorkspace_2). The property must already exist in the algorithm.
 * @param addProperties :: allow for declaration of properties that specify the
 *   dataset within the workspace to fit to.
 */
void IFittingAlgorithm::addWorkspace(const std::string &workspacePropertyName,
                                     bool addProperties) {
  // get the workspace
  API::Workspace_const_sptr ws = getProperty(workspacePropertyName);
  // m_function->setWorkspace(ws);
  const size_t n = std::string("InputWorkspace").size();
  const std::string suffix =
      (workspacePropertyName.size() > n) ? workspacePropertyName.substr(n) : "";
  const size_t index =
      suffix.empty() ? 0 : boost::lexical_cast<size_t>(suffix.substr(1));

  IFunction_sptr fun = getProperty("Function");
  setDomainType();

  IDomainCreator *creator = createDomainCreator(
      fun.get(), ws.get(), workspacePropertyName, this, m_domainType);

  if (!m_domainCreator) {
    if (m_workspacePropertyNames.empty()) {
      // this defines the function and fills in m_workspacePropertyNames with
      // names of the sort InputWorkspace_#
      setFunction();
    }
    auto multiFun = boost::dynamic_pointer_cast<API::MultiDomainFunction>(fun);
    if (multiFun) {
      auto multiCreator =
          new MultiDomainCreator(this, m_workspacePropertyNames);
      multiCreator->setCreator(index, creator);
      m_domainCreator.reset(multiCreator);
      creator->declareDatasetProperties(suffix, addProperties);
    } else {
      m_domainCreator.reset(creator);
      creator->declareDatasetProperties(suffix, addProperties);
    }
  } else {
    boost::shared_ptr<MultiDomainCreator> multiCreator =
        boost::dynamic_pointer_cast<MultiDomainCreator>(m_domainCreator);
    if (!multiCreator) {
      auto &reference = *m_domainCreator.get();
      throw std::runtime_error(
          std::string("MultiDomainCreator expected, found ") +
          typeid(reference).name());
    }
    if (!multiCreator->hasCreator(index)) {
      creator->declareDatasetProperties(suffix, addProperties);
    }
    multiCreator->setCreator(index, creator);
  }
}
  /** Store function parameter values to a map
    */
  void storeFunctionParameterValue(IFunction_sptr function, map<string, pair<double, double> >& parvaluemap)
  {
    parvaluemap.clear();

    vector<string> parnames = function->getParameterNames();
    for (size_t i = 0; i < parnames.size(); ++i)
    {
      string& parname = parnames[i];
      double parvalue = function->getParameter(i);
      double parerror = function->getError(i);
      parvaluemap.insert(make_pair(parname, make_pair(parvalue, parerror)));
    }

    return;
  }
Example #21
0
    /**
      * Set any WorkspaceIndex attributes in the fitting function. If the function is composite
      * try all its members.
      * @param fun :: The fitting function
      * @param wsIndex :: Value for WorkspaceIndex attributes to set.
      */
    void PlotPeakByLogValue::setWorkspaceIndexAttribute(IFunction_sptr fun, int wsIndex) const
    {
        const std::string attName = "WorkspaceIndex";
        if ( fun->hasAttribute(attName) )
        {
            fun->setAttributeValue(attName,wsIndex);
        }

        API::CompositeFunction_sptr cf = boost::dynamic_pointer_cast<API::CompositeFunction>( fun );
        if ( cf )
        {
            for(size_t i = 0; i < cf->nFunctions(); ++i)
            {
                setWorkspaceIndexAttribute( cf->getFunction(i), wsIndex );
            }
        }
    }
/// Execute
void EstimatePeakErrors::exec() {

  IFunction_sptr function = getProperty("Function");

  ITableWorkspace_sptr results =
      WorkspaceFactory::Instance().createTable("TableWorkspace");
  results->addColumn("str", "Parameter");
  results->addColumn("double", "Value");
  results->addColumn("double", "Error");

  auto matrix = function->getCovarianceMatrix();
  if (!matrix) {
    g_log.warning() << "Function doesn't have covariance matrix.\n";
    setProperty("OutputWorkspace", results);
    return;
  }

  IPeakFunction *peak = dynamic_cast<IPeakFunction *>(function.get());

  if (peak) {
    GSLMatrix covariance(*matrix);
    calculatePeakValues(*peak, *results, covariance, "");
  } else {
    CompositeFunction *cf = dynamic_cast<CompositeFunction *>(function.get());
    if (cf) {
      size_t ip = 0;
      for (size_t i = 0; i < cf->nFunctions(); ++i) {
        IFunction *fun = cf->getFunction(i).get();
        size_t np = fun->nParams();
        peak = dynamic_cast<IPeakFunction *>(fun);
        if (peak) {
          std::string prefix = "f" + std::to_string(i) + ".";
          GSLMatrix covariance(*matrix, ip, ip, np, np);
          calculatePeakValues(*peak, *results, covariance, prefix);
        }
        ip += np;
      }
    } else {
      g_log.warning() << "Function has no peaks.\n";
    }
  }

  setProperty("OutputWorkspace", results);
}
/** Remove a function
 * @param i :: The index of the function to remove
 */
void CompositeFunction::removeFunction(size_t i) {
  if (i >= nFunctions()) {
    throw std::out_of_range("Function index (" + std::to_string(i) +
                            ") out of range (" + std::to_string(nFunctions()) +
                            ").");
  }

  IFunction_sptr fun = getFunction(i);
  // Reduction in parameters
  size_t dnp = fun->nParams();

  for (size_t j = 0; j < nParams();) {
    ParameterTie *tie = getTie(j);
    if (tie && tie->findParametersOf(fun.get())) {
      removeTie(j);
    } else {
      j++;
    }
  }

  // Shift down the function indeces for parameters
  for (auto it = m_IFunction.begin(); it != m_IFunction.end();) {

    if (*it == i) {
      it = m_IFunction.erase(it);
    } else {
      if (*it > i) {
        *it -= 1;
      }
      ++it;
    }
  }

  m_nParams -= dnp;
  // Shift the parameter offsets down by the total number of i-th function's
  // params
  for (size_t j = i + 1; j < nFunctions(); j++) {
    m_paramOffsets[j] -= dnp;
  }
  m_paramOffsets.erase(m_paramOffsets.begin() + i);

  m_functions.erase(m_functions.begin() + i);
}
/** Replace a function with a new one. The old function is deleted.
 * @param i :: The index of the function to replace
 * @param f :: A pointer to the new function
 */
void CompositeFunction::replaceFunction(size_t i, IFunction_sptr f) {
  if (i >= nFunctions()) {
    throw std::out_of_range("Function index (" + std::to_string(i) +
                            ") out of range (" + std::to_string(nFunctions()) +
                            ").");
  }

  IFunction_sptr fun = getFunction(i);
  size_t np_old = fun->nParams();

  size_t np_new = f->nParams();

  // Modify function indeces: The new function may have different number of
  // parameters
  {
    auto itFun = std::find(m_IFunction.begin(), m_IFunction.end(), i);
    if (itFun != m_IFunction.end()) // functions must have at least 1 parameter
    {
      if (np_old > np_new) {
        m_IFunction.erase(itFun, itFun + np_old - np_new);
      } else if (np_old < np_new) {
        m_IFunction.insert(itFun, np_new - np_old, i);
      }
    } else if (np_new > 0) // it could happen if the old function is an empty
                           // CompositeFunction
    {
      itFun = std::find_if(m_IFunction.begin(), m_IFunction.end(),
                           std::bind2nd(std::greater<size_t>(), i));
      m_IFunction.insert(itFun, np_new, i);
    }
  }

  size_t dnp = np_new - np_old;
  m_nParams += dnp;
  // Shift the parameter offsets down by the total number of i-th function's
  // params
  for (size_t j = i + 1; j < nFunctions(); j++) {
    m_paramOffsets[j] += dnp;
  }

  m_functions[i] = f;
}
Example #25
0
/**
 * @param fun :: The function
 * @param expr :: The tie expression: parName = TieString
 */
void FunctionFactoryImpl::addTie(IFunction_sptr fun,
                                 const Expression &expr) const {
  if (expr.size() > 1) { // if size > 2 it is interpreted as setting a tie (last
    // expr.term) to multiple parameters, e.g
    // f1.alpha = f2.alpha = f3.alpha = f0.beta^2/2
    const std::string value = expr[expr.size() - 1].str();
    for (size_t i = expr.size() - 1; i != 0;) {
      --i;
      fun->tie(expr[i].name(), value);
    }
  }
}
Example #26
0
/**
 * Adds background functions for the background if applicable
 *
 * If specified by the user via the corresponding algorithm parameters,
 * this function adds a constant and a linear background term to the
 * supplied Poldi2DFunction.
 *
 * @param poldi2DFunction :: Poldi2DFunction to which the background is added.
 */
void PoldiFitPeaks2D::addBackgroundTerms(
    Poldi2DFunction_sptr poldi2DFunction) const {
  bool addConstantBackground = getProperty("FitConstantBackground");
  if (addConstantBackground) {
    IFunction_sptr constantBackground =
        FunctionFactory::Instance().createFunction(
            "PoldiSpectrumConstantBackground");
    constantBackground->setParameter(
        0, getProperty("ConstantBackgroundParameter"));
    poldi2DFunction->addFunction(constantBackground);
  }

  bool addLinearBackground = getProperty("FitLinearBackground");
  if (addLinearBackground) {
    IFunction_sptr linearBackground =
        FunctionFactory::Instance().createFunction(
            "PoldiSpectrumLinearBackground");
    linearBackground->setParameter(0, getProperty("LinearBackgroundParameter"));
    poldi2DFunction->addFunction(linearBackground);
  }
}
Example #27
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;
    }
Example #28
0
/// Returns a vector of peak collections extracted from the function
std::vector<PoldiPeakCollection_sptr> PoldiFitPeaks2D::getCountPeakCollections(
    const API::IFunction_sptr &fitFunction) {
  Poldi2DFunction_sptr poldiFunction =
      boost::dynamic_pointer_cast<Poldi2DFunction>(fitFunction);

  if (!poldiFunction) {
    throw std::runtime_error("Can only extract peaks from Poldi2DFunction.");
  }

  // Covariance matrix - needs to be assigned to the member functions for error
  // calculation
  boost::shared_ptr<const Kernel::DblMatrix> covarianceMatrix =
      poldiFunction->getCovarianceMatrix();

  std::vector<PoldiPeakCollection_sptr> countPeakCollections;

  size_t offset = 0;
  for (size_t i = 0; i < poldiFunction->nFunctions(); ++i) {
    IFunction_sptr localFunction = poldiFunction->getFunction(i);
    size_t nLocalParams = localFunction->nParams();

    // Assign local covariance matrix.
    boost::shared_ptr<Kernel::DblMatrix> localCov =
        getLocalCovarianceMatrix(covarianceMatrix, offset, nLocalParams);
    localFunction->setCovarianceMatrix(localCov);

    try {
      PoldiPeakCollection_sptr normalizedPeaks =
          getPeakCollectionFromFunction(localFunction);

      countPeakCollections.push_back(getCountPeakCollection(normalizedPeaks));
    } catch (const std::invalid_argument &) {
      // not a Poldi2DFunction - skip (the background functions)
    }

    offset += nLocalParams;
  }

  return countPeakCollections;
}
  /** Set parameter values to function from Parameter map
   */
  void RefinePowderInstrumentParameters2::setFunctionParameterValues(IFunction_sptr function,
                                                                     map<string, Parameter> params)
  {
    // 1. Prepare
    vector<string> funparamnames = function->getParameterNames();

    // 2. Set up
    stringstream msgss;
    msgss << "Set Instrument Function Parameter : " << endl;

    std::map<std::string, Parameter>::iterator paramiter;
    for (size_t i = 0; i < funparamnames.size(); ++i)
    {
      string parname = funparamnames[i];
      paramiter = params.find(parname);

      if (paramiter != params.end())
      {
        // Found, set up the parameter
        Parameter& param = paramiter->second;
        function->setParameter(parname, param.value);

        msgss << setw(10) << parname << " = " << param.value << endl;
      }
      else
      {
        // Not found and thus quit
        stringstream errss;
        errss << "Peak profile parameter " << parname << " is not found in input parameters. ";
        g_log.error(errss.str());
        throw runtime_error(errss.str());
      }
    } // ENDFOR parameter name

    g_log.information(msgss.str());

    return;
  }
Example #30
0
/**
 * @brief Returns a string with ties that is passed to Fit
 *
 * This method uses the GlobalParameters property, which may contain a comma-
 * separated list of parameter names that should be the same for all peaks.
 *
 * Parameters that do not exist are silently ignored, but a warning is written
 * to the log so that users have a chance to find typos.
 *
 * @param poldiFn :: Function with some parameters.
 * @return :: String to pass to the Ties-property of Fit.
 */
std::string
PoldiFitPeaks2D::getUserSpecifiedTies(const IFunction_sptr &poldiFn) {
  std::string tieParameterList = getProperty("GlobalParameters");

  if (!tieParameterList.empty()) {
    std::vector<std::string> tieParameters;

    boost::split(tieParameters, tieParameterList, boost::is_any_of(",;"));

    std::vector<std::string> parameters = poldiFn->getParameterNames();

    std::vector<std::string> tieComponents;
    for (auto &tieParameter : tieParameters) {
      if (!tieParameter.empty()) {
        std::vector<std::string> matchedParameters;

        for (auto &parameter : parameters) {
          if (boost::algorithm::ends_with(parameter, tieParameter)) {
            matchedParameters.push_back(parameter);
          }
        }

        switch (matchedParameters.size()) {
        case 0:
          g_log.warning("Function does not have a parameter called '" +
                        tieParameter + "', ignoring.");
          break;
        case 1:
          g_log.warning("There is only one peak, no ties necessary.");
          break;
        default: {
          std::string reference = matchedParameters.front();

          for (auto par = matchedParameters.begin() + 1;
               par != matchedParameters.end(); ++par) {
            tieComponents.push_back(*par + "=" + reference);
          }
          break;
        }
        }
      }
    }

    if (!tieComponents.empty()) {
      return boost::algorithm::join(tieComponents, ",");
    }
  }

  return "";
}