LCFit module¶
Linear combination fitting (LCF) refers to the interpretation of an unknown XAFS signal as a summation of known XAFS reference signals.
For the case of the XANES region of an unknown spectrum \(\mu_s(E)\), LCF translates into obtaining the amplitude coefficients \(\alpha_i\) that minimize the residuals of the following equation:
Considering the following set of constraints:
Where
\(E\) : photoelectron energy.
\(\mu_s(E)\) : normalized absorption of the fitted spectrum.
\(\mu_i(E)\) : normalized absorption of reference spectrum “i”.
\(\alpha_i\) : amplitude coefficient for reference spectrum “i”.
\(\epsilon(E)\): residuals.
\(n\) : number of reference spectra.
Analogously, for the case of the EXAFS region of an unknown spectrum \(\chi(k)\), LCF translates into minimizing the residuals of the following equation:
Considering the following set of constraints:
Where
\(k\) : photoelectron wavenumber.
\(\chi_s(k)\) : EXAFS modulation of the fitted spectrum.
\(\chi_i(E)\) : EXAFS modulation of the reference spectrum “i”.
\(\epsilon(k)\): residuals.
\(kw\) : weighting coefficient for the photoelectron wavenumber.
The lcf
module offers the following functions to perform linear
combintation fitting (LCF):
Function |
Description |
---|---|
Performs LCF on a XAFS spectrum. |
|
Returns a formatted LCF report. |
|
Sum of weighted references. |
|
Calculates residuals for LCF. |
- araucaria.fit.lcfit.lcf(collection, fit_region='xanes', fit_range=[- inf, inf], scantag='scan', reftag='ref', kweight=2, sum_one=True, method='leastsq')[source]¶
Performs linear combination fitting on a XAFS spectrum.
- Parameters
collection (
Collection
) – Collection containing the group for LCF analysis and the groups with the reference scans.fit_region (
str
) – XAFS region to perform the LCF. Accepted values are ‘dxanes’, ‘xanes’, or ‘exafs’. The default is ‘xanes’.fit_range (
list
) – Domain range in absolute values. Energy units are expected for ‘dxanes’ or ‘xanes’, while wavenumber (k) units are expected for ‘exafs’. The default is [-inf
,inf
].scantag (
str
) – Key to filter the scan group in the collection based on thetags
attribute. The default is ‘scan’.reftag (
str
) – Key to filter the reference groups in the collection based on thetags
attribute. The default is ‘scan’.kweight (
int
) – Exponent for weighting chi(k) by k^kweight. Only valid forfit_region='exafs'
. The default is 2.sum_one (
bool
) – Conditional to force sum of fractions to be one. The default is True.method (
str
) – Fitting method. Currently only local optimization methods are supported. See theminimize()
function oflmfit
for a list of valid methods. The default isleastsq
.
- Return type
- Returns
Fit group with the following arguments:
energy
: array with energy values. Returned only iffit_region='xanes'
orfit_region='dxanes'
.k
: array with wavenumber values. Returned only iffit_region='exafs'
.scangroup
: name of the group containing the fitted spectrum.refgroups
: list with names of groups containing reference spectra.scan
: array with values of the fitted spectrum.ref
: array with interpolated values for each reference spectrum.fit
: array with fit result.min_pars
: object with the optimized parameters and goodness-of-fit statistics.lcf_pars
: dictionary with lcf parameters.
- Raises
TypeError – If
collection
is not a valid Collection instance.AttributeError – If
collection
has notags
attribute.AttributeError – If groups have no
energy
ornorm
attribute. Only verified iffit_region='dxanes'
orfit_region='xanes'
.AttributeError – If groups have no
k
orchi
attribute. Only verified if andfit_region='exafs'
.KeyError – If
scantag
orrefttag
are not keys of thetags
attribute.ValueError – If
fit_region
is not recognized.ValueError – If
fit_range
is outside the doamin of a reference group.
Important
If more than one group in
collection
is tagged withscantag
, a warning will be raised and only the first group will be fitted.Notes
The
min_pars
object is returned by theminimize()
function oflmfit
, and contains the following attributes (non-exhaustive list):params
: dictionary with the optimized parameters.var_names
: ordered list of parameter names used in optimization.covar
: covariance matrix from minimization.init_vals
: list of initial values for variable parameters usingvar_names
.success
: True if the fit succeeded, otherwise False.nvarys
: number of variables.ndata
: number of data points.chisqr
: chi-square.redchi
: reduced chi-square.residual
: array with fit residuals.
Example
>>> from numpy.random import seed, normal >>> from numpy import arange, sin, pi >>> from araucaria import Group, Dataset, Collection >>> from araucaria.fit import lcf >>> from araucaria.utils import check_objattrs >>> seed(1234) # seed of random values >>> k = arange(0, 12, 0.05) >>> eps = normal(0, 0.1, len(k)) >>> f1 = 1.2 # freq 1 >>> f2 = 2.6 # freq 2 >>> amp1 = 0.4 # amp 1 >>> amp2 = 0.6 # amp 2 >>> group1 = Group(**{'name': 'group1', 'k': k, 'chi': sin(2*pi*f1*k)}) >>> group2 = Group(**{'name': 'group2', 'k': k, 'chi': sin(2*pi*f2*k)}) >>> group3 = Group(**{'name': 'group3', 'k': k, ... 'chi' : amp1 * group1.chi + amp2 * group2.chi + eps}) >>> collection = Collection() >>> tags = ['ref', 'ref', 'scan'] >>> for i, group in enumerate((group1,group2, group3)): ... collection.add_group(group, tag=tags[i]) >>> # performing lcf >>> out = lcf(collection, fit_region='exafs', fit_range=[3,10], ... kweight=0, sum_one=False) >>> check_objattrs(out, Dataset, ... attrlist=['k', 'scangroup', 'refgroups', ... 'scan', 'ref1', 'ref2', 'fit', 'min_pars', 'lcf_pars']) [True, True, True, True, True, True, True, True, True] >>> for key, val in out.min_pars.params.items(): ... print('%1.4f +/- %1.4f' % (val.value, val.stderr)) 0.4003 +/- 0.0120 0.5943 +/- 0.0120
- araucaria.fit.lcfit.lcf_report(out)[source]¶
Returns a formatted LCF Report to
sys.stdout
.- Parameters
- Return type
- Returns
LCF report.
- Raises
TypeError – If
out
is not a valid Dataset instance.AttributeError – If attribute
min_pars
,lcf_pars
,scangroup
, orrefgroups
does not exist ingroup
.
Notes
lcf_report()
is a wrapper forfit_report()
oflmfit
, that writes additional information on group names and calling parameters.Example
>>> from numpy.random import seed, normal >>> from numpy import arange, sin, pi >>> from araucaria import Group, Collection >>> from araucaria.fit import lcf, lcf_report >>> seed(1234) # seed of random values >>> k = arange(0, 12, 0.05) >>> eps = normal(0, 0.1, len(k)) >>> f1 = 1.2 # freq 1 >>> f2 = 2.6 # freq 2 >>> amp1 = 0.4 # amp 1 >>> amp2 = 0.6 # amp 2 >>> group1 = Group(**{'name': 'group1', 'k': k, 'chi': sin(2*pi*f1*k)}) >>> group2 = Group(**{'name': 'group2', 'k': k, 'chi': sin(2*pi*f2*k)}) >>> group3 = Group(**{'name': 'group3', 'k': k, ... 'chi' : amp1 * group1.chi + amp2 * group2.chi + eps}) >>> collection = Collection() >>> tags = ['ref', 'ref', 'scan'] >>> for i,group in enumerate((group1,group2, group3)): ... collection.add_group(group, tag=tags[i]) >>> # performing lcf >>> out = lcf(collection, fit_region='exafs', fit_range=[3,10], ... kweight=0, sum_one=False) >>> print(lcf_report(out)) [[Parameters]] fit_region = exafs fit_range = [3, 10] sum_one = False kweight = 0 [[Groups]] scan = group3 ref1 = group1 ref2 = group2 [[Fit Statistics]] # fitting method = leastsq # function evals = 10 # data points = 141 # variables = 2 chi-square = 1.40551323 reduced chi-square = 0.01011161 Akaike info crit = -645.778389 Bayesian info crit = -639.880869 [[Variables]] amp1: 0.40034377 +/- 0.01195335 (2.99%) (init = 0.5) amp2: 0.59428689 +/- 0.01199230 (2.02%) (init = 0.5)
- araucaria.fit.lcfit.sum_references(pars, data)[source]¶
Returns the sum of references weighted by amplitude coefficients.
- Parameters
- Return type
- Returns
Sum of references weighted by amplitude coefficients.
Important
The number of ‘amp’ attributes in
pars
should match the number of ‘ref’ keys indata
.Example
>>> from numpy import allclose >>> from lmfit import Parameters >>> from araucaria.fit import sum_references >>> pars = Parameters() >>> pars.add('amp1', value=0.4) >>> pars.add('amp2', value=0.7) >>> data = {'ref1': 1.0, 'ref2': 2.0} >>> allclose(sum_references(pars, data), 1.8) True
- araucaria.fit.lcfit.residuals(pars, data)[source]¶
Residuals between a spectrum and a linear combination of references.
- Parameters
- Return type
- Returns
Array with residuals.
Important
The number of ‘amp’ attributes in
pars
should match the number of ‘ref’ keys indata
.Example
>>> from numpy import allclose >>> from lmfit import Parameters >>> from araucaria.fit import residuals >>> pars = Parameters() >>> pars.add('amp1', value=0.4) >>> pars.add('amp2', value=0.7) >>> data = {'scan': 2, 'ref1': 1.0, 'ref2': 2.0} >>> allclose(residuals(pars, data), 0.2) True >>> data['scan'] = 1.6 >>> allclose(residuals(pars, data), -0.2) True