Fitting CHESS temperature dependent linecuts#

Import functions#

from nxs_analysis_tools.datareduction import load_data, Scissors
from nxs_analysis_tools.chess import *

from lmfit.models import GaussianModel, LinearModel

Create TempDependece object and load data#

sample = TempDependence()
sample.load_datasets(folder='example_data/sample_name')
Found temperature folders:
[0] 15
[1] 100
[2] 300
-----------------------------------------------
Loading 15 K indexed .nxs files...
Found example_data/sample_name/15/example_hkli.nxs
data:NXdata
  @axes = ['H', 'K', 'L']
  @signal = 'counts'
  H = float64(100)
  K = float64(150)
  L = float64(200)
  counts = float64(100x150x200)
-----------------------------------------------
Loading 100 K indexed .nxs files...
Found example_data/sample_name/100/example_hkli.nxs
data:NXdata
  @axes = ['H', 'K', 'L']
  @signal = 'counts'
  H = float64(100)
  K = float64(150)
  L = float64(200)
  counts = float64(100x150x200)
-----------------------------------------------
Loading 300 K indexed .nxs files...
Found example_data/sample_name/300/example_hkli.nxs
data:NXdata
  @axes = ['H', 'K', 'L']
  @signal = 'counts'
  H = float64(100)
  K = float64(150)
  L = float64(200)
  counts = float64(100x150x200)

Perform linecuts#

sample.cut_data(center=(0,0,0), window=(0.1,0.5,0.1))
-------------------------------
Cutting T = 15 K data...
Linecut axis: K
Integrated axes: ['H', 'L']
-------------------------------
Cutting T = 100 K data...
Linecut axis: K
Integrated axes: ['H', 'L']
-------------------------------
Cutting T = 300 K data...
Linecut axis: K
Integrated axes: ['H', 'L']
{'15': NXdata('data'), '100': NXdata('data'), '300': NXdata('data')}

The LinecutModel class#

Each TempDependence object has a LinecutModel for each temperature, stored in the .linecutmodels attribute.

sample.linecutmodels
{'15': <nxs_analysis_tools.fitting.LinecutModel at 0x7f90be581300>,
 '100': <nxs_analysis_tools.fitting.LinecutModel at 0x7f90866fa260>,
 '300': <nxs_analysis_tools.fitting.LinecutModel at 0x7f90866fa230>}

Create lmfit model#

Use the .set_model_components() method to set the model to be used for fitting the linecut. The model_components parameter must be a Model or list of Model objects.

sample.set_model_components([GaussianModel(prefix='peak'), LinearModel(prefix='background')])

Set model constraints#

Set constraints on the model using .set_param_hint().

sample.set_param_hint('peakcenter', min=-0.1, max=0.1)

After the model and the hints have been specified, use the .make_params() method to initialize the parameters.

The constraints can be different for each temperature - for example, here we set the constraints of the Gaussian sigma at 300 K only.

sample.linecutmodels['300'].set_param_hint('peaksigma', min=-1, max=1)

Initialize parameters#

sample.make_params()

Perform initial guess#

Use the .guess() method to perform an initial guess.

sample.guess()

The initial values of the parameters that result can be viewed using the .print_initial_params() method.

sample.print_initial_params()
peaksigma
	min: -1
	max: 1
peakfwhm
	expr: 2.3548200*peaksigma
peakheight
	expr: 0.3989423*peakamplitude/max(1e-15, peaksigma)
peakcenter
	min: -0.1
	max: 0.1
peaksigma
	min: -1
	max: 1
peakfwhm
	expr: 2.3548200*peaksigma
peakheight
	expr: 0.3989423*peakamplitude/max(1e-15, peaksigma)
peakcenter
	min: -0.1
	max: 0.1
peaksigma
	min: -1
	max: 1
peakfwhm
	expr: 2.3548200*peaksigma
peakheight
	expr: 0.3989423*peakamplitude/max(1e-15, peaksigma)
peakcenter
	min: -0.1
	max: 0.1

These can also be accessed through the individual LinecutModel objects.

sample.linecutmodels['15'].params

Visualize the initial guesses#

sample.plot_initial_guess()
../_images/e948b1e02578fa8440f620ad9ff1f16dc903ec9dd9a4df3eb494faf7a2ca17b1.png ../_images/ba4ea84c7ae82a49521c1db8aa7033b2fb074b3d5670aa9be3d294ad6f01e5d7.png ../_images/6e5e17fca1b6202e0bee086352cb9616cffcd889e907dc00bdd7ffe76e668588.png

Perform the fit#

sample.fit()
Fitting 15 K  data...
Done.
Fitting 100 K  data...
Done.
Fitting 300 K  data...
Done.
Fits completed.

Visualize all fits#

The .plot_fit function prints fit results for all temperatures. The parameter fit_report (default True) determines whether the fit report is also printed.

Additionally, an optional Markdown heading can be displayed using the mdheadings parameter (default False).

sample.plot_fit(mdheadings=True)

15 K Fit Results

../_images/25908c612611fcdbf34152826bd42dbf0815c485059cf8ded1b20eccb0cd4f5d.png
[[Model]]
    (Model(gaussian, prefix='peak') + Model(linear, prefix='background'))
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 25
    # data points      = 76
    # variables        = 5
    chi-square         = 1.3162e-16
    reduced chi-square = 1.8539e-18
    Akaike info crit   = -3098.19567
    Bayesian info crit = -3086.54200
    R-squared          = 1.00000000
##  Warning: uncertainties could not be estimated:
    backgroundslope:      at initial value
[[Variables]]
    peakamplitude:        183.644087 (init = 219.8854)
    peakcenter:          -9.7004e-15 (init = 0)
    peaksigma:            0.06000000 (init = 0.06040268)
    backgroundslope:     -5.2966e-11 (init = 2.385307e-14)
    backgroundintercept: -5.6044e-10 (init = 180.0195)
    peakfwhm:             0.14128920 == '2.3548200*peaksigma'
    peakheight:           1221.05658 == '0.3989423*peakamplitude/max(1e-15, peaksigma)'
    peakcorrlength:       44.4703863 == '(2 * 3.141592653589793) / peakfwhm'
[[Model]]
    (Model(gaussian, prefix='peak') + Model(linear, prefix='background'))
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 34
    # data points      = 76
    # variables        = 5
    chi-square         = 5.9182e-05
    reduced chi-square = 8.3356e-07
    Akaike info crit   = -1058.98702
    Bayesian info crit = -1047.33335
    R-squared          = 1.00000000
[[Variables]]
    peakamplitude:        291.982900 +/- 1.1230e-04 (0.00%) (init = 397.8052)
    peakcenter:          -3.6249e-12 +/- 3.0297e-08 (835795.34%) (init = -6.167906e-18)
    peaksigma:            0.09999993 +/- 3.5765e-08 (0.00%) (init = 0.114094)
    backgroundslope:      3.5175e-14 +/- 3.7545e-04 (1067379877973.20%) (init = 3.517481e-14)
    backgroundintercept:  5.6407e-04 +/- 1.5350e-04 (27.21%) (init = 286.2205)
    peakfwhm:             0.23548184 +/- 8.4221e-08 (0.00%) == '2.3548200*peaksigma'
    peakheight:           1164.84410 +/- 3.2639e-04 (0.00%) == '0.3989423*peakamplitude/max(1e-15, peaksigma)'
    peakcorrlength:       26.6822500 +/- 9.5430e-06 (0.00%) == '(2 * 3.141592653589793) / peakfwhm'
[[Correlations]] (unreported correlations are < 0.100)
    C(peakamplitude, backgroundintercept)   = -0.7268
    C(peakamplitude, peaksigma)             = +0.7173
    C(peaksigma, backgroundintercept)       = -0.5215
    C(backgroundslope, backgroundintercept) = -0.1658
    C(peakamplitude, backgroundslope)       = +0.1205
[[Model]]
    (Model(gaussian, prefix='peak') + Model(linear, prefix='background'))
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 31
    # data points      = 76
    # variables        = 5
    chi-square         = 85.5499422
    reduced chi-square = 1.20492876
    Akaike info crit   = 18.9958908
    Bayesian info crit = 30.6495575
    R-squared          = 0.99998814
##  Warning: uncertainties could not be estimated:
    peakcenter:           at initial value
    backgroundslope:      at initial value
[[Variables]]
    peakamplitude:        349.382304 (init = 469.3782)
    peakcenter:          -4.2492e-10 (init = -1.982541e-17)
    peaksigma:            0.15931867 (init = 0.1812081)
    backgroundslope:      1.1764e-14 (init = 1.176368e-14)
    backgroundintercept:  3.23456528 (init = 345.2546)
    peakfwhm:             0.37516679 == '2.3548200*peaksigma'
    peakheight:           874.871598 == '0.3989423*peakamplitude/max(1e-15, peaksigma)'
    peakcorrlength:       16.7477118 == '(2 * 3.141592653589793) / peakfwhm'

100 K Fit Results

../_images/5ccba65b4763381b82c4f63f9dd0ca46918fc72f2422e349e5158285ab2f2f8b.png

300 K Fit Results

../_images/036a3c6d1e00a5e27d28484b6c4777ef5cca2ee6f4d9b5c37085088ee869e7db.png

Access the fit values#

The x and y values of the fit are stored in the .x (identical to the raw x values) and the .y_fit attributes.

sample.linecutmodels['15'].x
array([-0.503356, -0.489933, -0.47651 , ...,  0.47651 ,  0.489933,
        0.503356])
sample.linecutmodels['15'].y_fit
array([-5.331438e-10, -5.304346e-10, -5.106177e-10, ..., -5.610952e-10,
       -5.823341e-10, -5.864651e-10])

The residuals are stored within the ModelResult class of the lmfit package, which is stored in the .modelresult attribute of the LinecutModel class.

sample.linecutmodels['15'].modelresult.residual
array([-5.353978e-10, -5.347390e-10, -5.352385e-10, ..., -5.857160e-10,
       -5.866385e-10, -5.887192e-10])

Viewing the fit report#

Use the .print_fit_report() method to print out the fit report for all temperatures.

sample.print_fit_report()
[[[15 K Fit Report]]]
[[Model]]
    (Model(gaussian, prefix='peak') + Model(linear, prefix='background'))
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 25
    # data points      = 76
    # variables        = 5
    chi-square         = 1.3162e-16
    reduced chi-square = 1.8539e-18
    Akaike info crit   = -3098.19567
    Bayesian info crit = -3086.54200
    R-squared          = 1.00000000
##  Warning: uncertainties could not be estimated:
    backgroundslope:      at initial value
[[Variables]]
    peakamplitude:        183.644087 (init = 219.8854)
    peakcenter:          -9.7004e-15 (init = 0)
    peaksigma:            0.06000000 (init = 0.06040268)
    backgroundslope:     -5.2966e-11 (init = 2.385307e-14)
    backgroundintercept: -5.6044e-10 (init = 180.0195)
    peakfwhm:             0.14128920 == '2.3548200*peaksigma'
    peakheight:           1221.05658 == '0.3989423*peakamplitude/max(1e-15, peaksigma)'
    peakcorrlength:       44.4703863 == '(2 * 3.141592653589793) / peakfwhm'
[[[100 K Fit Report]]]
[[Model]]
    (Model(gaussian, prefix='peak') + Model(linear, prefix='background'))
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 34
    # data points      = 76
    # variables        = 5
    chi-square         = 5.9182e-05
    reduced chi-square = 8.3356e-07
    Akaike info crit   = -1058.98702
    Bayesian info crit = -1047.33335
    R-squared          = 1.00000000
[[Variables]]
    peakamplitude:        291.982900 +/- 1.1230e-04 (0.00%) (init = 397.8052)
    peakcenter:          -3.6249e-12 +/- 3.0297e-08 (835795.34%) (init = -6.167906e-18)
    peaksigma:            0.09999993 +/- 3.5765e-08 (0.00%) (init = 0.114094)
    backgroundslope:      3.5175e-14 +/- 3.7545e-04 (1067379877973.20%) (init = 3.517481e-14)
    backgroundintercept:  5.6407e-04 +/- 1.5350e-04 (27.21%) (init = 286.2205)
    peakfwhm:             0.23548184 +/- 8.4221e-08 (0.00%) == '2.3548200*peaksigma'
    peakheight:           1164.84410 +/- 3.2639e-04 (0.00%) == '0.3989423*peakamplitude/max(1e-15, peaksigma)'
    peakcorrlength:       26.6822500 +/- 9.5430e-06 (0.00%) == '(2 * 3.141592653589793) / peakfwhm'
[[Correlations]] (unreported correlations are < 0.100)
    C(peakamplitude, backgroundintercept)   = -0.7268
    C(peakamplitude, peaksigma)             = +0.7173
    C(peaksigma, backgroundintercept)       = -0.5215
    C(backgroundslope, backgroundintercept) = -0.1658
    C(peakamplitude, backgroundslope)       = +0.1205
[[[300 K Fit Report]]]
[[Model]]
    (Model(gaussian, prefix='peak') + Model(linear, prefix='background'))
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 31
    # data points      = 76
    # variables        = 5
    chi-square         = 85.5499422
    reduced chi-square = 1.20492876
    Akaike info crit   = 18.9958908
    Bayesian info crit = 30.6495575
    R-squared          = 0.99998814
##  Warning: uncertainties could not be estimated:
    peakcenter:           at initial value
    backgroundslope:      at initial value
[[Variables]]
    peakamplitude:        349.382304 (init = 469.3782)
    peakcenter:          -4.2492e-10 (init = -1.982541e-17)
    peaksigma:            0.15931867 (init = 0.1812081)
    backgroundslope:      1.1764e-14 (init = 1.176368e-14)
    backgroundintercept:  3.23456528 (init = 345.2546)
    peakfwhm:             0.37516679 == '2.3548200*peaksigma'
    peakheight:           874.871598 == '0.3989423*peakamplitude/max(1e-15, peaksigma)'
    peakcorrlength:       16.7477118 == '(2 * 3.141592653589793) / peakfwhm'

To obtain a fit report for just one temperature, use the .fit_report() method of the ModelResult object stored in the .linecutmodels attr

Or, to access a single temperature fit report:

sample.linecutmodels['15'].print_fit_report()
[[Model]]
    (Model(gaussian, prefix='peak') + Model(linear, prefix='background'))
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 25
    # data points      = 76
    # variables        = 5
    chi-square         = 1.3162e-16
    reduced chi-square = 1.8539e-18
    Akaike info crit   = -3098.19567
    Bayesian info crit = -3086.54200
    R-squared          = 1.00000000
##  Warning: uncertainties could not be estimated:
    backgroundslope:      at initial value
[[Variables]]
    peakamplitude:        183.644087 (init = 219.8854)
    peakcenter:          -9.7004e-15 (init = 0)
    peaksigma:            0.06000000 (init = 0.06040268)
    backgroundslope:     -5.2966e-11 (init = 2.385307e-14)
    backgroundintercept: -5.6044e-10 (init = 180.0195)
    peakfwhm:             0.14128920 == '2.3548200*peaksigma'
    peakheight:           1221.05658 == '0.3989423*peakamplitude/max(1e-15, peaksigma)'
    peakcorrlength:       44.4703863 == '(2 * 3.141592653589793) / peakfwhm'