Skip to content

jdmax/DeuteronPeakFit

Repository files navigation

Deuteron Peak Fit for NMR Signal Analysis

Fitting routine for spin-1 NMR signals with quadrupolar splitting Pake doublets, based on C code by C. Dulya [1]. Utilized to analyze signals from continuous-wave NMR Q-meter systems [2].

Uses Non-Linear Least-Squares Minimization and Curve-Fitting for Python (LMFIT), https://lmfit.github.io/lmfit-py/

Functions

Three fitting functions are provided, each returning an lmfit ModelResult object (https://lmfit.github.io/lmfit-py/model.html#lmfit.model.ModelResult).

fit(freqs, signal, initial_params) Absorption-only fit to the Dulya lineshape, as in the original C code.

fit_complex(freqs, signal, initial_params) Fits the complex signal — absorption and dispersion mixed by a phase angle. Adds parameter phase. The dispersion component is computed analytically as the Kramers-Kronig partner of the absorption lineshape, following Kisselev et al. (1995) [3] and McClellan (2025). [4]

fit_complex_cubic(freqs, signal, initial_params) Complex lineshape with a cubic polynomial baseline correction. Adds parameters c3, c2, c1, c0.

Usage

from deuteron_fit import fit

initial_params = {
    'A':  0.5,
    'G':  1.0,
    'r':  1.0,
    'wQ': 1e5,
    'wL': 2.13e8,
    'eta': 0.0,
    'xi': 0.0,
}

result = fit(freqs, signal, initial_params)

The success of the fit is highly dependent on the initial parameters passed.

Polarization from fit results

The fitted r parameter is the Boltzmann population ratio between the m=+1 and m=-1 spin states. Vector polarization P and tensor polarization A or Pzz can be calculated from it directly:

Vector polarization:

$$P = \frac{r^2 - 1}{r^2 + r + 1}$$

Tensor polarization:

$$P_{zz} = \frac{(r-1)^2}{r^2 + r + 1}$$

lmfit reports the standard error on each parameter as result.params['r'].stderr. Propagating this through both formulas:

$$\sigma_P = \frac{r^2 + 4r + 1}{(r^2 + r + 1)^2} \cdot \sigma_r$$

$$\sigma_{P_{zz}} = \frac{3|r^2 - 1|}{(r^2 + r + 1)^2} \cdot \sigma_r$$

In code:

r      = result.params['r'].value
r_err  = result.params['r'].stderr
denom  = r**2 + r + 1

P      = (r**2 - 1) / denom
Pzz    = (r - 1)**2 / denom

P_err   = (r**2 + 4*r + 1) / denom**2 * r_err
Pzz_err = 3 * abs(r**2 - 1)  / denom**2 * r_err

Other fitted values and their uncertainties are accessed the same way, e.g. result.params['wQ'].value and result.params['wQ'].stderr. The full lmfit result object also provides fit statistics, covariance matrix, and a fit report via result.fit_report().

Parameters

Parameters follow Dulya's convention:

Parameter Description
A Width due to dipolar broadening
G Scale factor
r Asymmetry parameter — relative sizes of the two peaks
wQ Quadrupolar splitting frequency width
wL Nuclear Larmor frequency (same units as freqs)
eta Peak asymmetry factor
xi False asymmetry correction from mistuning
phase Phase angle (complex fits only)
c3,c2,c1,c0 Cubic baseline coefficients (cubic fit only)

Bounds and constraints

Bounds and other per-parameter constraints are set inline in initial_params using lmfit's dict format:

initial_params = {
    'A':  {'value': 0.5, 'min': 0.0, 'max': 1.0},
    'wQ': {'value': 1e5, 'min': 0.0},
    'G':  1.0,   # plain scalar, no bounds
}

See the lmfit documentation for additional options such as vary and expr.

Example

An example signal is included for fitting. example.py gives an example usage which will plot the signal to test your installation.

Example Fit of 40% Polarized Deuteron Signal at 5T

Example fit of 40% polarized deuteron signal at 5T taken on ND3 during Run Group C at Jefferson Lab.

Author

Written in 2021 by J. Maxwell (https://orcid.org/0000-0003-2710-4646). Added complex fitting in 2026.

References

[1] Dulya, C. et. al. "A line-shape analysis for spin-1 NMR signals" NIM A, 398, 109-125 (1997). (https://doi.org/10.1016/S0168-9002(97)00317-3)

[2] Maxwell, J. et. al. "A new cw-NMR Q-meter for dynamically polarized targets for particle physics" NIM A, 1087, 171417 (2026). (https://doi.org/10.1016/j.nima.2026.171417)

[3] Kisselev, Yu.F., Dulya, C.M., Niinikoski, T.O. "Measurement of complex RF susceptibility using a series Q-meter" NIM A, 354, 249-261 (1995). (https://doi.org/10.1016/0168-9002(94)01066-8)

[4] McClellan, M. "Complex deuteron NMR signals" Eur. Phys. J. A, 61, 176 (2025). (https://doi.org/10.1140/epja/s10050-025-01644-z)

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors