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);

}
Beispiel #2
0
void IqtFit::plotGuess(QtProperty *) {
  // Do nothing if there is no sample data curve
  if (!m_uiForm.ppPlot->hasCurve("Sample"))
    return;

  CompositeFunction_sptr function = createFunction(true);

  // Create the double* array from the input workspace
  const size_t binIndxLow =
      m_ffInputWS->binIndexOf(m_ffRangeManager->value(m_properties["StartX"]));
  const size_t binIndxHigh =
      m_ffInputWS->binIndexOf(m_ffRangeManager->value(m_properties["EndX"]));
  const size_t nData = binIndxHigh - binIndxLow;

  std::vector<double> inputXData(nData);

  const Mantid::MantidVec &XValues = m_ffInputWS->readX(0);

  const bool isHistogram = m_ffInputWS->isHistogramData();

  for (size_t i = 0; i < nData; i++) {
    if (isHistogram)
      inputXData[i] =
          0.5 * (XValues[binIndxLow + i] + XValues[binIndxLow + i + 1]);
    else
      inputXData[i] = XValues[binIndxLow + i];
  }

  FunctionDomain1DVector domain(inputXData);
  FunctionValues outputData(domain);
  function->function(domain, outputData);

  QVector<double> dataX;
  QVector<double> dataY;

  for (size_t i = 0; i < nData; i++) {
    dataX.append(inputXData[i]);
    dataY.append(outputData.getCalculated(i));
  }
  IAlgorithm_sptr createWsAlg =
      AlgorithmManager::Instance().create("CreateWorkspace");
  createWsAlg->initialize();
  createWsAlg->setChild(true);
  createWsAlg->setLogging(false);
  createWsAlg->setProperty("OutputWorkspace", "__GuessAnon");
  createWsAlg->setProperty("NSpec", 1);
  createWsAlg->setProperty("DataX", dataX.toStdVector());
  createWsAlg->setProperty("DataY", dataY.toStdVector());
  createWsAlg->execute();
  MatrixWorkspace_sptr guessWs = createWsAlg->getProperty("OutputWorkspace");

  m_uiForm.ppPlot->addSpectrum("Guess", guessWs, 0, Qt::green);
}
Beispiel #3
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;
}
/** Makes sure that the function is consistent.
 */
void CompositeFunction::checkFunction() {
  m_nParams = 0;
  m_paramOffsets.clear();
  m_IFunction.clear();

  std::vector<IFunction_sptr> functions(m_functions.begin(), m_functions.end());
  m_functions.clear();

  for (auto &f : functions) {
    CompositeFunction_sptr cf =
        boost::dynamic_pointer_cast<CompositeFunction>(f);
    if (cf)
      cf->checkFunction();
    addFunction(f);
  }
}
Beispiel #5
0
void PoldiFitPeaks1D::setValuesFromProfileFunction(
    PoldiPeak_sptr poldiPeak, const IFunction_sptr &fittedFunction) const {
  CompositeFunction_sptr totalFunction =
      boost::dynamic_pointer_cast<CompositeFunction>(fittedFunction);

  if (totalFunction) {
    IPeakFunction_sptr peakFunction =
        boost::dynamic_pointer_cast<IPeakFunction>(
            totalFunction->getFunction(0));

    if (peakFunction) {
      poldiPeak->setIntensity(
          UncertainValue(peakFunction->height(), peakFunction->getError(0)));
      poldiPeak->setQ(
          UncertainValue(peakFunction->centre(), peakFunction->getError(1)));
      poldiPeak->setFwhm(UncertainValue(peakFunction->fwhm(),
                                        getFwhmWidthRelation(peakFunction) *
                                            peakFunction->getError(2)));
    }
  }
}
/**
 * Split this function into independent functions. The number of functions in
 * the
 * returned vector must be equal to the number
 * of domains. The result of evaluation of the i-th function on the i-th domain
 * must be
 * the same as if this MultiDomainFunction was evaluated.
 */
std::vector<IFunction_sptr>
MultiDomainFunction::createEquivalentFunctions() const {
  size_t nDomains = m_maxIndex + 1;
  std::vector<CompositeFunction_sptr> compositeFunctions(nDomains);
  for (size_t iFun = 0; iFun < nFunctions(); ++iFun) {
    // find the domains member function must be applied to
    std::vector<size_t> domains;
    getDomainIndices(iFun, nDomains, domains);

    for (auto i = domains.begin(); i != domains.end(); ++i) {
      size_t j = *i;
      CompositeFunction_sptr cf = compositeFunctions[j];
      if (!cf) {
        // create a composite function for each domain
        cf = CompositeFunction_sptr(new CompositeFunction());
        compositeFunctions[j] = cf;
      }
      // add copies of all functions applied to j-th domain to a single
      // compositefunction
      cf->addFunction(FunctionFactory::Instance().createInitialized(
          getFunction(iFun)->asString()));
    }
  }
  std::vector<IFunction_sptr> outFunctions(nDomains);
  // fill in the output vector
  // check functions containing a single member and take it out of the composite
  for (size_t i = 0; i < compositeFunctions.size(); ++i) {
    auto fun = compositeFunctions[i];
    if (!fun || fun->nFunctions() == 0) {
      throw std::runtime_error("There is no function for domain " +
                               boost::lexical_cast<std::string>(i));
    }
    if (fun->nFunctions() > 1) {
      outFunctions[i] = fun;
    } else {
      outFunctions[i] = fun->getFunction(0);
    }
  }
  return outFunctions;
}
Beispiel #7
0
PoldiPeakCollection_sptr
PoldiFitPeaks1D2::fitPeaks(const PoldiPeakCollection_sptr &peaks) {
  g_log.information() << "Peaks to fit: " << peaks->peakCount() << std::endl;

  std::vector<RefinedRange_sptr> rawRanges = getRefinedRanges(peaks);
  std::vector<RefinedRange_sptr> reducedRanges = getReducedRanges(rawRanges);

  g_log.information() << "Ranges used for fitting: " << reducedRanges.size()
                      << std::endl;

  Workspace2D_sptr dataWorkspace = getProperty("InputWorkspace");
  m_fitplots->removeAll();

  for (size_t i = 0; i < reducedRanges.size(); ++i) {
    RefinedRange_sptr currentRange = reducedRanges[i];
    int nMin = getBestChebyshevPolynomialDegree(dataWorkspace, currentRange);

    if (nMin > -1) {
      IAlgorithm_sptr fit = getFitAlgorithm(dataWorkspace, currentRange, nMin);
      fit->execute();

      IFunction_sptr fitFunction = fit->getProperty("Function");
      CompositeFunction_sptr composite =
          boost::dynamic_pointer_cast<CompositeFunction>(fitFunction);

      if (!composite) {
        throw std::runtime_error("Not a composite function!");
      }

      std::vector<PoldiPeak_sptr> peaks = currentRange->getPeaks();
      for (size_t i = 0; i < peaks.size(); ++i) {
        setValuesFromProfileFunction(peaks[i], composite->getFunction(i));
        MatrixWorkspace_sptr fpg = fit->getProperty("OutputWorkspace");
        m_fitplots->addWorkspace(fpg);
      }
    }
  }

  return getReducedPeakCollection(peaks);
}
Beispiel #8
0
/**
 * Construct a PoldiPeakCollection from a Poldi2DFunction
 *
 * This method performs the opposite operation of
 *getFunctionFromPeakCollection.
 * It takes a function, checks if it's of the proper type and turns the
 * information into a PoldiPeakCollection.
 *
 * @param  Poldi2DFunction with one PoldiSpectrumDomainFunction per peak
 * @return PoldiPeakCollection containing peaks with normalized intensities
 */
PoldiPeakCollection_sptr PoldiFitPeaks2D::getPeakCollectionFromFunction(
    const IFunction_sptr &fitFunction) {
  Poldi2DFunction_sptr poldi2DFunction =
      boost::dynamic_pointer_cast<Poldi2DFunction>(fitFunction);

  if (!poldi2DFunction) {
    throw std::invalid_argument(
        "Cannot process function that is not a Poldi2DFunction.");
  }

  PoldiPeakCollection_sptr normalizedPeaks =
      boost::make_shared<PoldiPeakCollection>(PoldiPeakCollection::Integral);

  boost::shared_ptr<const Kernel::DblMatrix> covarianceMatrix =
      poldi2DFunction->getCovarianceMatrix();

  size_t offset = 0;

  for (size_t i = 0; i < poldi2DFunction->nFunctions(); ++i) {
    boost::shared_ptr<PoldiSpectrumPawleyFunction> poldiPawleyFunction =
        boost::dynamic_pointer_cast<PoldiSpectrumPawleyFunction>(
            poldi2DFunction->getFunction(i));

    // If it's a Pawley function, there are several peaks in one function.
    if (poldiPawleyFunction) {
      IPawleyFunction_sptr pawleyFunction =
          poldiPawleyFunction->getPawleyFunction();

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

        offset = decoratedFunction->getFunction(0)->nParams();

        for (size_t j = 0; j < pawleyFunction->getPeakCount(); ++j) {
          IPeakFunction_sptr profileFunction =
              pawleyFunction->getPeakFunction(j);

          size_t nLocalParams = profileFunction->nParams();
          boost::shared_ptr<Kernel::DblMatrix> localCov =
              getLocalCovarianceMatrix(covarianceMatrix, offset, nLocalParams);
          profileFunction->setCovarianceMatrix(localCov);

          // Increment offset for next function
          offset += nLocalParams;

          V3D peakHKL = pawleyFunction->getPeakHKL(j);

          PoldiPeak_sptr peak =
              getPeakFromPeakFunction(profileFunction, peakHKL);

          normalizedPeaks->addPeak(peak);
        }
      }
      break;
    }

    // Otherwise, it's just one peak in this function.
    boost::shared_ptr<PoldiSpectrumDomainFunction> peakFunction =
        boost::dynamic_pointer_cast<PoldiSpectrumDomainFunction>(
            poldi2DFunction->getFunction(i));

    if (peakFunction) {
      IPeakFunction_sptr profileFunction =
          boost::dynamic_pointer_cast<IPeakFunction>(
              peakFunction->getProfileFunction());

      // Get local covariance matrix
      size_t nLocalParams = profileFunction->nParams();
      boost::shared_ptr<Kernel::DblMatrix> localCov =
          getLocalCovarianceMatrix(covarianceMatrix, offset, nLocalParams);
      profileFunction->setCovarianceMatrix(localCov);

      // Increment offset for next function
      offset += nLocalParams;

      PoldiPeak_sptr peak =
          getPeakFromPeakFunction(profileFunction, V3D(0, 0, 0));

      normalizedPeaks->addPeak(peak);
    }
  }

  return normalizedPeaks;
}
Beispiel #9
0
/**
 * Create a composite 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
 */
CompositeFunction_sptr FunctionFactoryImpl::createComposite(
    const Expression &expr,
    std::map<std::string, std::string> &parentAttributes) const {
  if (expr.name() != ";")
    inputError(expr.str());

  if (expr.size() == 0) {
    return CompositeFunction_sptr();
  }

  const std::vector<Expression> &terms = expr.terms();
  auto it = terms.cbegin();
  const Expression &term = it->bracketsRemoved();

  CompositeFunction_sptr cfun;
  if (term.name() == "=") {
    if (term.terms()[0].name() == "composite") {
      cfun = boost::dynamic_pointer_cast<CompositeFunction>(
          createFunction(term.terms()[1].name()));
      if (!cfun)
        inputError(expr.str());
      ++it;
    } else if (term.terms()[0].name() == "name") {
      cfun = boost::dynamic_pointer_cast<CompositeFunction>(
          createFunction("CompositeFunction"));
      if (!cfun)
        inputError(expr.str());
    } else {
      inputError(expr.str());
    }
  } else if (term.name() == ",") {
    auto firstTerm = term.terms().cbegin();
    if (firstTerm->name() == "=") {
      if (firstTerm->terms()[0].name() == "composite") {
        cfun = boost::dynamic_pointer_cast<CompositeFunction>(
            createSimple(term, parentAttributes));
        if (!cfun)
          inputError(expr.str());
        ++it;
      } else if (firstTerm->terms()[0].name() == "name") {
        cfun = boost::dynamic_pointer_cast<CompositeFunction>(
            createFunction("CompositeFunction"));
        if (!cfun)
          inputError(expr.str());
      } else {
        inputError(expr.str());
      }
    }
  } else if (term.name() == ";") {
    cfun = boost::dynamic_pointer_cast<CompositeFunction>(
        createFunction("CompositeFunction"));
    if (!cfun)
      inputError(expr.str());
  } else {
    inputError(expr.str());
  }

  if (!cfun)
    inputError(expr.str());

  for (; it != terms.end(); ++it) {
    const Expression &term = it->bracketsRemoved();
    IFunction_sptr fun;
    std::map<std::string, std::string> pAttributes;
    if (term.name() == ";") {
      fun = createComposite(term, pAttributes);
      if (!fun)
        continue;
    } else {
      std::string parName = term[0].name();
      if (parName.size() >= 10 && parName.substr(0, 10) == "constraint") {
        addConstraints(cfun, term[1]);
        continue;
      } else if (parName == "ties") {
        addTies(cfun, term[1]);
        continue;
      } else {
        fun = createSimple(term, pAttributes);
      }
    }
    cfun->addFunction(fun);
    size_t i = cfun->nFunctions() - 1;
    for (auto &pAttribute : pAttributes) {
      // Apply parent attributes of the child function to this function. If this
      // function doesn't have those attributes, they get passed up the chain to
      // this function's parent.
      if (cfun->hasLocalAttribute(pAttribute.first)) {
        cfun->setLocalAttributeValue(i, pAttribute.first, pAttribute.second);
      } else {
        parentAttributes[pAttribute.first] = pAttribute.second;
      }
    }
  }

  if (cfun) {
    cfun->applyTies();
  }
  return cfun;
}
Beispiel #10
0
void IqtFit::constrainIntensities(CompositeFunction_sptr func) {
  std::string paramName = "f1.Intensity";
  size_t index = func->parameterIndex(paramName);

  switch (m_uiForm.cbFitType->currentIndex()) {
  case 0: // 1 Exp
  case 2: // 1 Str
    if (!func->isFixed(index)) {
      func->tie(paramName, "1-f0.A0");
    } else {
      std::string paramValue =
          boost::lexical_cast<std::string>(func->getParameter(paramName));
      func->tie(paramName, paramValue);
      func->tie("f0.A0", "1-" + paramName);
    }
    break;
  case 1: // 2 Exp
  case 3: // 1 Exp & 1 Str
    if (!func->isFixed(index)) {
      func->tie(paramName, "1-f2.Intensity-f0.A0");
    } else {
      std::string paramValue =
          boost::lexical_cast<std::string>(func->getParameter(paramName));
      func->tie(paramName, "1-f2.Intensity-f0.A0");
      func->tie(paramName, paramValue);
    }
    break;
  }
}
Beispiel #11
0
    /** 
     * Create a composite 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
     */
    CompositeFunction_sptr FunctionFactoryImpl::createComposite(const Expression& expr, std::map<std::string,std::string>& parentAttributes)const
    {
      if (expr.name() != ";") inputError(expr.str());

      if (expr.size() == 0)
      {
        return CompositeFunction_sptr();
      }

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

      CompositeFunction_sptr cfun;
      if (term.name() == "=")
      {
        if (term.terms()[0].name() == "composite")
        {
          cfun = boost::dynamic_pointer_cast<CompositeFunction>(createFunction(term.terms()[1].name()));
          if (!cfun) inputError(expr.str());
          ++it;
        }
        else if (term.terms()[0].name() == "name")
        {
          cfun = boost::dynamic_pointer_cast<CompositeFunction>(createFunction("CompositeFunction"));
          if (!cfun) inputError(expr.str());
        }
        else
        {
          inputError(expr.str());
        }
      }
      else if (term.name() == ",")
      {
        std::vector<Expression>::const_iterator firstTerm = term.terms().begin();
        if (firstTerm->name() == "=")
        {
          if (firstTerm->terms()[0].name() == "composite")
          {
            cfun = boost::dynamic_pointer_cast<CompositeFunction>(createSimple(term,parentAttributes));
            if (!cfun) inputError(expr.str());
            ++it;
          }
          else if (firstTerm->terms()[0].name() == "name")
          {
            cfun = boost::dynamic_pointer_cast<CompositeFunction>(createFunction("CompositeFunction"));
            if (!cfun) inputError(expr.str());
          }
          else
          {
            inputError(expr.str());
          }
        }
      }
      else if (term.name() == ";")
      {
        cfun = boost::dynamic_pointer_cast<CompositeFunction>(createFunction("CompositeFunction"));
        if (!cfun) inputError(expr.str());
      }
      else
      {
        inputError(expr.str());
      }

      for(;it!=terms.end();++it)
      {
        const Expression& term = it->bracketsRemoved();
        IFunction_sptr fun;
        std::map<std::string,std::string> pAttributes;
        if (term.name() == ";")
        {
          fun = createComposite(term,pAttributes);
          if (!fun) continue;
        }
        else
        {
          std::string parName = term[0].name();
          if (parName.size() >= 10 && parName.substr(0,10) == "constraint")
          {
            addConstraints(cfun,term[1]);
            continue;
          }
          else if (parName == "ties")
          {
            addTies(cfun,term[1]);
            continue;
          }
          else
          {
            fun = createSimple(term,pAttributes);
          }
        }
        cfun->addFunction(fun);
        size_t i = cfun->nFunctions() - 1;
        for(auto att = pAttributes.begin(); att != pAttributes.end(); ++att)
        {
          cfun->setLocalAttributeValue(i,att->first,att->second);
        }
      }

      cfun->applyTies();
      return cfun;
    }