Пример #1
0
/**
 * Returns a Poldi2DFunction that encapsulates individual peaks
 *
 * This function takes all peaks from the supplied peak collection and
 * generates an IPeakFunction of the type given in the name parameter, wraps
 * them in a Poldi2DFunction and returns it.
 *
 * @param profileFunctionName :: Profile function name.
 * @param peakCollection :: Peak collection with peaks to be used in the fit.
 * @return :: A Poldi2DFunction with peak profile functions.
 */
Poldi2DFunction_sptr PoldiFitPeaks2D::getFunctionIndividualPeaks(
    std::string profileFunctionName,
    const PoldiPeakCollection_sptr &peakCollection) const {
  auto mdFunction = boost::make_shared<Poldi2DFunction>();

  for (size_t i = 0; i < peakCollection->peakCount(); ++i) {
    PoldiPeak_sptr peak = peakCollection->peak(i);

    boost::shared_ptr<PoldiSpectrumDomainFunction> peakFunction =
        boost::dynamic_pointer_cast<PoldiSpectrumDomainFunction>(
            FunctionFactory::Instance().createFunction(
                "PoldiSpectrumDomainFunction"));

    if (!peakFunction) {
      throw std::invalid_argument(
          "Cannot process null pointer poldi function.");
    }

    peakFunction->setDecoratedFunction(profileFunctionName);

    IPeakFunction_sptr wrappedProfile =
        boost::dynamic_pointer_cast<IPeakFunction>(
            peakFunction->getProfileFunction());

    if (wrappedProfile) {
      wrappedProfile->setCentre(peak->d());
      wrappedProfile->setFwhm(peak->fwhm(PoldiPeak::AbsoluteD));
      wrappedProfile->setIntensity(peak->intensity());
    }

    mdFunction->addFunction(peakFunction);
  }

  return mdFunction;
}
Пример #2
0
IFunction_sptr
PoldiFitPeaks1D2::getPeakProfile(const PoldiPeak_sptr &poldiPeak) const {
  IPeakFunction_sptr clonedProfile = boost::dynamic_pointer_cast<IPeakFunction>(
      FunctionFactory::Instance().createFunction(m_profileTemplate));
  clonedProfile->setCentre(poldiPeak->q());
  clonedProfile->setFwhm(poldiPeak->fwhm(PoldiPeak::AbsoluteQ));
  clonedProfile->setHeight(poldiPeak->intensity());

  return clonedProfile;
}
Пример #3
0
/**
 * Returns a Poldi2DFunction that encapsulates a PawleyFunction
 *
 * This function creates a PawleyFunction using the supplied profile function
 * name and the crystal system as well as initial cell from the input
 * properties of the algorithm and wraps it in a Poldi2DFunction.
 *
 * The cell is refined using LatticeFunction to get better starting values.
 *
 * Because the peak intensities are integral at this step but PawleyFunction
 * expects peak heights, a profile function is created and
 * setIntensity/height-methods are used to convert.
 *
 * @param profileFunctionName :: Profile function name for PawleyFunction.
 * @param peakCollection :: Peak collection with peaks to be used in the fit.
 * @return :: A Poldi2DFunction with a PawleyFunction.
 */
Poldi2DFunction_sptr PoldiFitPeaks2D::getFunctionPawley(
    std::string profileFunctionName,
    const PoldiPeakCollection_sptr &peakCollection) {
  auto mdFunction = boost::make_shared<Poldi2DFunction>();

  boost::shared_ptr<PoldiSpectrumPawleyFunction> poldiPawleyFunction =
      boost::dynamic_pointer_cast<PoldiSpectrumPawleyFunction>(
          FunctionFactory::Instance().createFunction(
              "PoldiSpectrumPawleyFunction"));

  if (!poldiPawleyFunction) {
    throw std::invalid_argument("Could not create pawley function.");
  }

  poldiPawleyFunction->setDecoratedFunction("PawleyFunction");

  IPawleyFunction_sptr pawleyFunction =
      poldiPawleyFunction->getPawleyFunction();
  pawleyFunction->setProfileFunction(profileFunctionName);

  // Extract crystal system from peak collection
  PointGroup_sptr pointGroup = peakCollection->pointGroup();
  if (!pointGroup) {
    throw std::invalid_argument("Can not initialize pawley function properly - "
                                "peaks do not have point group.");
  }

  std::string latticeSystem = getLatticeSystemFromPointGroup(pointGroup);
  pawleyFunction->setLatticeSystem(latticeSystem);

  UnitCell cell = peakCollection->unitCell();
  // Extract unit cell from peak collection
  pawleyFunction->setUnitCell(getRefinedStartingCell(
      unitCellToStr(cell), latticeSystem, peakCollection));

  IPeakFunction_sptr pFun = boost::dynamic_pointer_cast<IPeakFunction>(
      FunctionFactory::Instance().createFunction(profileFunctionName));

  for (size_t i = 0; i < peakCollection->peakCount(); ++i) {
    PoldiPeak_sptr peak = peakCollection->peak(i);

    pFun->setCentre(peak->d());
    pFun->setFwhm(peak->fwhm(PoldiPeak::AbsoluteD));
    pFun->setIntensity(peak->intensity());

    pawleyFunction->addPeak(peak->hkl().asV3D(),
                            peak->fwhm(PoldiPeak::AbsoluteD), pFun->height());
  }

  pawleyFunction->fix(pawleyFunction->parameterIndex("f0.ZeroShift"));
  mdFunction->addFunction(poldiPawleyFunction);

  return mdFunction;
}
Пример #4
0
/// Sets the profile function and replaces already existing functions in the
/// internally stored CompositeFunction.
void PawleyFunction::setProfileFunction(const std::string &profileFunction) {
  m_pawleyParameterFunction->setAttributeValue("ProfileFunction",
                                               profileFunction);

  /* At this point PawleyParameterFunction guarantees that it's an IPeakFunction
   * and all existing profile functions are replaced.
   */
  for (size_t i = 0; i < m_peakProfileComposite->nFunctions(); ++i) {
    IPeakFunction_sptr oldFunction = boost::dynamic_pointer_cast<IPeakFunction>(
        m_peakProfileComposite->getFunction(i));

    IPeakFunction_sptr newFunction = boost::dynamic_pointer_cast<IPeakFunction>(
        FunctionFactory::Instance().createFunction(
            m_pawleyParameterFunction->getProfileFunctionName()));

    newFunction->setCentre(oldFunction->centre());
    try {
      newFunction->setFwhm(oldFunction->fwhm());
    } catch (...) {
      // do nothing.
    }
    newFunction->setHeight(oldFunction->height());

    m_peakProfileComposite->replaceFunction(i, newFunction);
  }

  // Update exposed parameters.
  m_compositeFunction->checkFunction();
}
Пример #5
0
/// Tries to extract and store the center parameter name from the function.
void PawleyParameterFunction::setCenterParameterNameFromFunction(
    const IPeakFunction_sptr &profileFunction) {
  m_profileFunctionCenterParameterName.clear();
  if (profileFunction) {
    m_profileFunctionCenterParameterName =
        profileFunction->getCentreParameterName();
  }
}
Пример #6
0
/// Creates a PoldiPeak from the given profile function/hkl pair.
PoldiPeak_sptr
PoldiFitPeaks2D::getPeakFromPeakFunction(IPeakFunction_sptr profileFunction,
                                         const V3D &hkl) {

  // Use EstimatePeakErrors to calculate errors of FWHM and so on
  IAlgorithm_sptr errorAlg = createChildAlgorithm("EstimatePeakErrors");
  errorAlg->setProperty(
      "Function", boost::dynamic_pointer_cast<IFunction>(profileFunction));
  errorAlg->setPropertyValue("OutputWorkspace", "Errors");
  errorAlg->execute();

  double centre = profileFunction->centre();
  double fwhmValue = profileFunction->fwhm();

  ITableWorkspace_sptr errorTable = errorAlg->getProperty("OutputWorkspace");
  double centreError = errorTable->cell<double>(0, 2);
  double fwhmError = errorTable->cell<double>(2, 2);

  UncertainValue d(centre, centreError);
  UncertainValue fwhm(fwhmValue, fwhmError);

  UncertainValue intensity;

  bool useIntegratedIntensities = getProperty("OutputIntegratedIntensities");
  if (useIntegratedIntensities) {
    double integratedIntensity = profileFunction->intensity();
    double integratedIntensityError = errorTable->cell<double>(3, 2);
    intensity = UncertainValue(integratedIntensity, integratedIntensityError);
  } else {
    double height = profileFunction->height();
    double heightError = errorTable->cell<double>(1, 2);
    intensity = UncertainValue(height, heightError);
  }

  // Create peak with extracted parameters and supplied hkl
  PoldiPeak_sptr peak =
      PoldiPeak::create(MillerIndices(hkl), d, intensity, UncertainValue(1.0));
  peak->setFwhm(fwhm, PoldiPeak::FwhmRelation::AbsoluteD);

  return peak;
}
Пример #7
0
IFunction_sptr
PoldiFitPeaks1D::getPeakProfile(const PoldiPeak_sptr &poldiPeak) const {
  IPeakFunction_sptr clonedProfile = boost::dynamic_pointer_cast<IPeakFunction>(
      FunctionFactory::Instance().createFunction(m_profileTemplate));
  clonedProfile->setCentre(poldiPeak->q());
  clonedProfile->setFwhm(poldiPeak->fwhm(PoldiPeak::AbsoluteQ));
  clonedProfile->setHeight(poldiPeak->intensity());

  IFunction_sptr clonedBackground = m_backgroundTemplate->clone();

  auto totalProfile = boost::make_shared<CompositeFunction>();
  totalProfile->initialize();
  totalProfile->addFunction(clonedProfile);
  totalProfile->addFunction(clonedBackground);

  if (!m_profileTies.empty()) {
    totalProfile->addTies(m_profileTies);
  }

  return totalProfile;
}
Пример #8
0
/// Adds a peak with the supplied FWHM and height.
void PawleyFunction::addPeak(const Kernel::V3D &hkl, double fwhm,
                             double height) {
  m_hkls.push_back(hkl);

  IPeakFunction_sptr peak = boost::dynamic_pointer_cast<IPeakFunction>(
      FunctionFactory::Instance().createFunction(
          m_pawleyParameterFunction->getProfileFunctionName()));

  peak->fix(peak->parameterIndex(
      m_pawleyParameterFunction->getProfileFunctionCenterParameterName()));

  try {
    peak->setFwhm(fwhm);
  } catch (...) {
    // do nothing.
  }

  peak->setHeight(height);

  m_peakProfileComposite->addFunction(peak);

  m_compositeFunction->checkFunction();
}
Пример #9
0
void PoldiFitPeaks1D2::setValuesFromProfileFunction(
    PoldiPeak_sptr poldiPeak, const IFunction_sptr &fittedFunction) const {
  IPeakFunction_sptr peakFunction =
      boost::dynamic_pointer_cast<IPeakFunction>(fittedFunction);

  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)));
  }
}
Пример #10
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;
}
Пример #11
0
/**
 * Return peak collection with integrated peaks
 *
 * This method takes a PoldiPeakCollection where the intensity is represented
 * by the maximum. Then it takes the profile function stored in the peak
 * collection, which must be the name of a registered
 * IPeakFunction-implementation. The parameters height and fwhm are assigned,
 * centre is set to 0 to avoid problems with the parameter transformation for
 * the integration from -inf to inf. The profiles are integrated using
 * a PeakFunctionIntegrator to the precision of 1e-10.
 *
 * The original peak collection is not modified, a new instance is created.
 *
 * @param rawPeakCollection :: PoldiPeakCollection
 * @return PoldiPeakCollection with integrated intensities
 */
PoldiPeakCollection_sptr PoldiFitPeaks2D::getIntegratedPeakCollection(
    const PoldiPeakCollection_sptr &rawPeakCollection) const {
  if (!rawPeakCollection) {
    throw std::invalid_argument(
        "Cannot proceed with invalid PoldiPeakCollection.");
  }

  if (!isValidDeltaT(m_deltaT)) {
    throw std::invalid_argument("Cannot proceed with invalid time bin size.");
  }

  if (!m_timeTransformer) {
    throw std::invalid_argument(
        "Cannot proceed with invalid PoldiTimeTransformer.");
  }

  if (rawPeakCollection->intensityType() == PoldiPeakCollection::Integral) {
    /* Intensities are integral already - don't need to do anything,
     * except cloning the collection, to make behavior consistent, since
     * integrating also results in a new peak collection.
     */
    return rawPeakCollection->clone();
  }

  /* If no profile function is specified, it's not possible to get integrated
   * intensities at all and we try to use the one specified by the user
   * instead.
   */
  std::string profileFunctionName = rawPeakCollection->getProfileFunctionName();

  if (!rawPeakCollection->hasProfileFunctionName()) {
    profileFunctionName = getPropertyValue("PeakProfileFunction");
  }

  std::vector<std::string> allowedProfiles =
      FunctionFactory::Instance().getFunctionNames<IPeakFunction>();

  if (std::find(allowedProfiles.begin(), allowedProfiles.end(),
                profileFunctionName) == allowedProfiles.end()) {
    throw std::runtime_error(
        "Cannot integrate peak profiles with invalid profile function.");
  }

  PoldiPeakCollection_sptr integratedPeakCollection =
      boost::make_shared<PoldiPeakCollection>(PoldiPeakCollection::Integral);
  integratedPeakCollection->setProfileFunctionName(profileFunctionName);

  // Preserve unit cell, point group
  assignCrystalData(integratedPeakCollection, rawPeakCollection);

  for (size_t i = 0; i < rawPeakCollection->peakCount(); ++i) {
    PoldiPeak_sptr peak = rawPeakCollection->peak(i);

    IPeakFunction_sptr profileFunction =
        boost::dynamic_pointer_cast<IPeakFunction>(
            FunctionFactory::Instance().createFunction(profileFunctionName));

    profileFunction->setHeight(peak->intensity());
    profileFunction->setFwhm(peak->fwhm(PoldiPeak::AbsoluteD));

    PoldiPeak_sptr integratedPeak = peak->clone();
    integratedPeak->setIntensity(UncertainValue(profileFunction->intensity()));
    integratedPeakCollection->addPeak(integratedPeak);
  }

  return integratedPeakCollection;
}
Пример #12
0
  /** Generate peaks in the given output workspace
    * @param functionmap :: map to contain the list of functions with key as their spectra
    * @param dataWS :: output matrix workspace
    */
  void GeneratePeaks::generatePeaks(const std::map<specid_t, std::vector<std::pair<double, API::IFunction_sptr> > >& functionmap,
                                    API::MatrixWorkspace_sptr dataWS)
  {
    // Calcualte function
    std::map<specid_t, std::vector<std::pair<double, API::IFunction_sptr> > >::const_iterator mapiter;
    for (mapiter = functionmap.begin(); mapiter != functionmap.end(); ++mapiter)
    {
      // Get spec id and translated to wsindex in the output workspace
      specid_t specid = mapiter->first;
      specid_t wsindex;
      if (m_newWSFromParent) wsindex = specid;
      else wsindex = m_SpectrumMap[specid];

      const std::vector<std::pair<double, API::IFunction_sptr> >& vec_centrefunc = mapiter->second;
      size_t numpeaksinspec = mapiter->second.size();

      for (size_t ipeak = 0; ipeak < numpeaksinspec; ++ipeak)
      {
        const std::pair<double, API::IFunction_sptr>& centrefunc = vec_centrefunc[ipeak];

        // Determine boundary
        API::IPeakFunction_sptr thispeak = getPeakFunction(centrefunc.second);
        double centre = centrefunc.first;
        double fwhm = thispeak->fwhm();

        //
        const MantidVec& X = dataWS->dataX(wsindex);
        double leftbound = centre - m_numPeakWidth*fwhm;
        if (ipeak > 0)
        {
          // Not left most peak.
          API::IPeakFunction_sptr leftPeak = getPeakFunction(vec_centrefunc[ipeak-1].second);

          double middle = 0.5*(centre + leftPeak->centre());
          if (leftbound < middle)
            leftbound = middle;
        }
        std::vector<double>::const_iterator left = std::lower_bound(X.begin(), X.end(), leftbound);
        if (left == X.end())
          left = X.begin();

        double rightbound = centre + m_numPeakWidth*fwhm;
        if (ipeak != numpeaksinspec-1)
        {
          // Not the rightmost peak
          IPeakFunction_sptr rightPeak = getPeakFunction(vec_centrefunc[ipeak+1].second);
          double middle = 0.5*(centre + rightPeak->centre());
          if (rightbound > middle)
            rightbound = middle;
        }
        std::vector<double>::const_iterator right = std::lower_bound(left + 1, X.end(), rightbound);

        // Build domain & function
        API::FunctionDomain1DVector domain(left, right); //dataWS->dataX(wsindex));

        // Evaluate the function
        API::FunctionValues values(domain);
        centrefunc.second->function(domain, values);

        // Put to output
        std::size_t offset = (left-X.begin());
        std::size_t numY = values.size();
        for (std::size_t i = 0; i < numY; i ++)
        {
          dataWS->dataY(wsindex)[i + offset] += values[i];
        }

      } // ENDFOR(ipeak)

    }

    return;
  }
Пример #13
0
double
PoldiFitPeaks1D::getFwhmWidthRelation(IPeakFunction_sptr peakFunction) const {
  return peakFunction->fwhm() / peakFunction->getParameter(2);
}