/** * 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 } }
/** * 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); } }
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()); }
/// 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; } }
/** * 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; } }
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); }
/** * 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 ¢resAndIntensities, 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))); } } }