/**
 * Calculates the function values on the supplied domain
 *
 * This function is the core of PawleyFunction. It calculates the d-value for
 * each stored HKL from the unit cell that is the result of the parameters
 * stored in the internal PawleyParameterFunction and adds the ZeroShift
 * parameter. The value is set as center parameter on the internally stored
 * PeakFunctions.
 *
 * @param domain :: Function domain.
 * @param values :: Function values.
 */
void PawleyFunction::function(const FunctionDomain &domain,
                              FunctionValues &values) const {
  values.zeroCalculated();
  try {
    const FunctionDomain1D &domain1D =
        dynamic_cast<const FunctionDomain1D &>(domain);

    UnitCell cell = m_pawleyParameterFunction->getUnitCellFromParameters();
    double zeroShift = m_pawleyParameterFunction->getParameter("ZeroShift");
    std::string centreName =
        m_pawleyParameterFunction->getProfileFunctionCenterParameterName();

    setPeakPositions(centreName, zeroShift, cell);

    FunctionValues localValues;

    for (size_t i = 0; i < m_peakProfileComposite->nFunctions(); ++i) {
      IPeakFunction_sptr peak = boost::dynamic_pointer_cast<IPeakFunction>(
          m_peakProfileComposite->getFunction(i));

      try {
        size_t offset = calculateFunctionValues(peak, domain1D, localValues);
        values.addToCalculated(offset, localValues);
      } catch (const std::invalid_argument &) {
        // do nothing
      }
    }

    setPeakPositions(centreName, 0.0, cell);
  } catch (const std::bad_cast &) {
    // do nothing
  }
}
Beispiel #2
0
/**
 * Calculates function values for domain. In contrast to CompositeFunction, the
 *summation
 * of values is performed in a different way: The values are set to zero once at
 *the beginning,
 * then it is expected of the member functions to use
 *FunctionValues::addToCalculated or add
 * their values otherwise, without erasing the values.
 *
 * @param domain :: Function domain which is passed on to the member functions.
 * @param values :: Function values.
 */
void Poldi2DFunction::function(const FunctionDomain &domain,
                               FunctionValues &values) const {
  CompositeFunction::function(domain, values);

  if (m_iteration > 0) {
    for (size_t i = 0; i < values.size(); ++i) {
      values.setFitWeight(i, 1.0 / sqrt(values.getCalculated(i) + 0.1));
    }
  }
}
void PoldiSpectrumLinearBackground::poldiFunction1D(
    const std::vector<int> &indices, const FunctionDomain1D &domain,
    FunctionValues &values) const {
  double backgroundDetector = getParameter(0);
  double wireCount = static_cast<double>(indices.size());
  double distributionFactor = wireCount * wireCount *
                              static_cast<double>(m_timeBinCount) /
                              (2.0 * static_cast<double>(domain.size()));
  double backgroundD = backgroundDetector * distributionFactor;

  for (size_t i = 0; i < values.size(); ++i) {
    values.addToCalculated(i, backgroundD);
  }
}
Beispiel #4
0
void IFunction1D::function(const FunctionDomain &domain,
                           FunctionValues &values) const {
  auto histoDomain = dynamic_cast<const FunctionDomain1DHistogram *>(&domain);
  if (histoDomain) {
    histogram1D(values.getPointerToCalculated(0), histoDomain->leftBoundary(),
                histoDomain->getPointerAt(0), histoDomain->size());
    return;
  }
  const FunctionDomain1D *d1d = dynamic_cast<const FunctionDomain1D *>(&domain);
  if (!d1d) {
    throw std::invalid_argument("Unexpected domain in IFunction1D");
  }
  function1D(values.getPointerToCalculated(0), d1d->getPointerAt(0),
             d1d->size());
}
Beispiel #5
0
/// Takes a d-based domain and creates a Q-based MatrixWorkspace.
MatrixWorkspace_sptr
PoldiFitPeaks2D::getQSpectrum(const FunctionDomain1D &domain,
                              const FunctionValues &values) const {
  // Put result into workspace, based on Q
  MatrixWorkspace_sptr ws1D = WorkspaceFactory::Instance().create(
      "Workspace2D", 1, domain.size(), values.size());

  auto &xData = ws1D->mutableX(0);
  auto &yData = ws1D->mutableY(0);
  size_t offset = values.size() - 1;
  for (size_t i = 0; i < values.size(); ++i) {
    xData[offset - i] = Conversions::dToQ(domain[i]);
    yData[offset - i] = values[i];
  }

  ws1D->getAxis(0)->setUnit("MomentumTransfer");
  return ws1D;
}
/** Function you want to fit to.
 *  @param domain :: An instance of FunctionDomain with the function arguments.
 *  @param values :: A FunctionValues instance for storing the calculated
 * values.
 */
void CompositeFunction::function(const FunctionDomain &domain,
                                 FunctionValues &values) const {
  FunctionValues tmp(domain);
  values.zeroCalculated();
  for (size_t iFun = 0; iFun < nFunctions(); ++iFun) {
    m_functions[iFun]->function(domain, tmp);
    values += tmp;
  }
}
Beispiel #7
0
/**
 * Implements the virtual method. Tests the domain for FunctionDomain1D and calls function1D.
 * @param domain :: The domain, must be FunctionDomain1D.
 * @param values :: The output values.
 */
void IFunction1D::function(const FunctionDomain& domain,FunctionValues& values)const
{
  const FunctionDomain1D* d1d = dynamic_cast<const FunctionDomain1D*>(&domain);
  if (!d1d)
  {
    throw std::invalid_argument("Unexpected domain in IFunction1D");
  }
  function1D(values.getPointerToCalculated(0),d1d->getPointerAt(0),d1d->size());
}
/// Function you want to fit to. 
/// @param domain :: The buffer for writing the calculated values. Must be big enough to accept dataSize() values
void ProductFunction::function(const FunctionDomain& domain, FunctionValues& values)const
{
  FunctionValues tmp(domain);
  values.setCalculated(1.0);
  for(size_t iFun = 0; iFun < nFunctions(); ++iFun)
  {
    m_functions[ iFun ]->function(domain,tmp);
    values *= tmp;
  }
}
Beispiel #9
0
void IFunction1D::derivative(const FunctionDomain &domain,
                             FunctionValues &values, const size_t order) const {
  const FunctionDomain1D *d1d = dynamic_cast<const FunctionDomain1D *>(&domain);
  if (!d1d) {
    throw std::invalid_argument("Unexpected domain in IFunction1D");
  }

  derivative1D(values.getPointerToCalculated(0), d1d->getPointerAt(0),
               d1d->size(), order);
}
Beispiel #10
0
 /**
  * Performs the function evaluations on the domain
  *
  * @param domain :: The MD domain to evaluate the function
  * @param values :: The computed values
  */
 void IFunctionMD::evaluateFunction(const FunctionDomainMD& domain,FunctionValues& values) const
 {
   domain.reset();
   size_t i=0;
   for(const IMDIterator* r = domain.getNextIterator(); r != NULL; r = domain.getNextIterator())
   {
     this->reportProgress("Evaluating function for box " + boost::lexical_cast<std::string>(i+1));
     values.setCalculated(i,functionMD(*r));
     i++;
   };
 }
  /// Function you want to fit to. 
  /// @param domain :: The buffer for writing the calculated values. Must be big enough to accept dataSize() values
  void MultiDomainFunction::function(const FunctionDomain& domain, FunctionValues& values)const
  {
    // works only on CompositeDomain
    if (!dynamic_cast<const CompositeDomain*>(&domain))
    {
      throw std::invalid_argument("Non-CompositeDomain passed to MultiDomainFunction.");
    }
    const CompositeDomain& cd = dynamic_cast<const CompositeDomain&>(domain);
    // domain must not have less parts than m_maxIndex
    if (cd.getNParts() <= m_maxIndex)
    {
      throw std::invalid_argument("CompositeDomain has too few parts (" 
        + boost::lexical_cast<std::string>(cd.getNParts()) +
        ") for MultiDomainFunction (max index " + boost::lexical_cast<std::string>(m_maxIndex) + ").");
    }
    // domain and values must be consistent
    if (cd.size() != values.size())
    {
      throw std::invalid_argument("MultiDomainFunction: domain and values have different sizes.");
    }

    countValueOffsets(cd);
    // evaluate member functions
    values.zeroCalculated();
    for(size_t iFun = 0; iFun < nFunctions(); ++iFun)
    {
      // find the domains member function must be applied to
      std::vector<size_t> domains;
      getFunctionDomains(iFun, cd, domains);

      for(auto i = domains.begin(); i != domains.end(); ++i)
      {
        const FunctionDomain& d = cd.getDomain(*i);
        FunctionValues tmp(d);
        getFunction(iFun)->function( d, tmp );
        values.addToCalculated(m_valueOffsets[*i],tmp);
      }
    }
  }
/// Update the peaks parameters after recalculationof the crystal field.
/// @param spectrum :: A composite function containings the peaks to update.
///                    May contain other functions (background) fix indices
///                    < iFirst.
/// @param peakShape :: A shape of each peak as a name of an IPeakFunction.
/// @param centresAndIntensities :: A FunctionValues object containing centres
///        and intensities for the peaks. First nPeaks calculated values are the
///        centres and the following nPeaks values are the intensities.
/// @param iFirst :: The first index in the composite function (spectrum) at
///        which the peaks begin.
/// @param xVec :: x-values of a tabulated width function.
/// @param yVec :: y-values of a tabulated width function.
/// @param fwhmVariation :: A variation in the peak width allowed in a fit.
/// @param defaultFWHM :: A default value for the FWHM to use if xVec and yVec
///        are empty.
/// @param fixAllPeaks :: If true fix all peak parameters
/// @return :: The new number of fitted peaks.
size_t updateSpectrumFunction(API::CompositeFunction &spectrum,
                              const std::string &peakShape,
                              const FunctionValues &centresAndIntensities,
                              size_t iFirst, const std::vector<double> &xVec,
                              const std::vector<double> &yVec,
                              double fwhmVariation, double defaultFWHM,
                              bool fixAllPeaks) {
  size_t nGoodPeaks = calculateNPeaks(centresAndIntensities);
  size_t maxNPeaks = calculateMaxNPeaks(nGoodPeaks);
  size_t nFunctions = spectrum.nFunctions();

  for (size_t i = 0; i < maxNPeaks; ++i) {
    const bool isGood = i < nGoodPeaks;
    auto centre = isGood ? centresAndIntensities.getCalculated(i) : 0.0;
    auto intensity =
        isGood ? centresAndIntensities.getCalculated(i + nGoodPeaks) : 0.0;

    if (i < nFunctions - iFirst) {
      auto fun = spectrum.getFunction(i + iFirst);
      auto &peak = dynamic_cast<API::IPeakFunction &>(*fun);
      updatePeak(peak, centre, intensity, xVec, yVec, fwhmVariation, isGood,
                 fixAllPeaks);
    } else {
      auto peakPtr =
          createPeak(peakShape, centre, intensity, xVec, yVec, fwhmVariation,
                     defaultFWHM, isGood, fixAllPeaks);
      spectrum.addFunction(peakPtr);
    }
  }
  // If there are any peaks above the maxNPeaks, ignore them
  // but don't remove
  for (size_t i = maxNPeaks; i < nFunctions - iFirst; ++i) {
    auto fun = spectrum.getFunction(i + iFirst);
    auto &peak = dynamic_cast<API::IPeakFunction &>(*fun);
    const auto fwhm = peak.fwhm();
    ignorePeak(peak, fwhm);
  }
  return nGoodPeaks;
}
/// Function you want to fit to. 
/// @param domain :: The domain
void FunctionComposition::function(const FunctionDomain& domain, FunctionValues& values)const
{
  FunctionValues tmp(domain);
  values.setCalculated(1.0);
  for(size_t iFun = 0; iFun < nFunctions(); ++iFun)
  {
    FunctionDomain1DView view(tmp.getPointerToCalculated(0),domain.size());
    if ( iFun == 0 )
    {
      m_functions[ iFun ]->function(domain,tmp);
    }
    else
    {
    }
  }
}
void PoldiSpectrumDomainFunction::poldiFunction1D(
    const std::vector<int> &indices, const FunctionDomain1D &domain,
    FunctionValues &values) const {

  FunctionValues localValues(domain);

  m_profileFunction->functionLocal(localValues.getPointerToCalculated(0),
                                   domain.getPointerAt(0), domain.size());

  double chopperSlitCount = static_cast<double>(m_chopperSlitOffsets.size());

  for (auto index : indices) {
    std::vector<double> factors(domain.size());

    for (size_t i = 0; i < factors.size(); ++i) {
      values.addToCalculated(i, chopperSlitCount * localValues[i] *
                                    m_timeTransformer->detectorElementIntensity(
                                        domain[i], static_cast<size_t>(index)));
    }
  }
}