Math Modules¶
Helper modules for offline data analysis: least-squares curve fitting, 1D
signal processing (apodization, zero filling, smoothing, baseline subtraction,
echo-centre detection), FFT and phase correction, and DEER/PDS
distance-distribution analysis. They take
and return plain NumPy arrays, so a result can be pushed straight to LivePlot
with plot_1d() or saved with
save_data().
scipy is an optional dependency
The fitting routines, Savitzky–Golay smoothing, and the whole DEER engine
require scipy, which is part of the math extra:
The modules import scipy lazily, so importing them never fails on a
minimal install — only the functions that need scipy raise a
RuntimeError when it is missing.
Least-squares fitting¶
import atomize.math_modules.least_square_fitting_modules as math_modules
| Function | Description |
|---|---|
math() |
Create a fitter exposing the model registry |
fit(model, x, y, guess=None, no_offset=False) |
Fit (x, y) with a named model; returns a result dict |
model_names() |
List the available model keys |
param_names(model) |
Parameter names of a model |
default_guess(model, x, y) |
Heuristic initial guess for a model |
one_exp_fit(curve, guess_array) |
Legacy single-exponential fit |
Signal processing¶
import atomize.math_modules.signal_processing as sigproc
| Function | Description |
|---|---|
apodization_window(n, name, param=8.6) |
Build an apodization window of length n |
zerofill_length(length, choice) |
Target FFT length for a zero-fill choice |
echo_center(envelope, window=0) |
Echo-centre index from a magnitude envelope |
Signal_Processing() |
Smoothing / baseline / normalization helpers |
savitzky_golay(y, window=11, order=3) |
Savitzky–Golay smoothing (needs scipy) |
moving_average(y, window=5) |
Centred moving-average smoothing |
baseline_poly(x, y, order=1, region='all', npts=0) |
Subtract a polynomial baseline |
normalize(y, mode='minmax') |
Normalize a curve |
FFT / phase correction¶
import atomize.math_modules.fft as fft_module
| Function | Description |
|---|---|
Fast_Fourier() |
Create the FFT / phase-correction helper |
auto_phase_zero(spectrum, threshold=0.1) |
Zero-order auto-phase (degrees) maximising the magnitude-weighted real part |
ph_correction(freq, data_i, data_q, cor1, cor2, cor3) |
Apply a zero/first/second-order phase polynomial to I+iQ |
fft(x_axis, data_i, data_q, sample_spacing, re='False') |
FFT of I+iQ; magnitude or real/imag parts (ns → MHz) |
DEER / PDS analysis¶
import atomize.math_modules.deer as deer
Distance-distribution analysis for pulsed-dipolar spectroscopy (DEER/PELDOR, RIDME, DQC, SIFTER): background correction + inversion of the orientation-averaged dipolar kernel by Tikhonov/NNLS (GCV or L-curve regularization, sequential or joint DeerLab-style background) or a model-free analytic Mellin transform. Times in µs, distances in nm.
| Function | Description |
|---|---|
deer_invert(t, V, …) |
One-call pipeline: background-correct → kernel → P(r) (engine/method) |
deer_invert_joint(t, V, …) |
Joint fit of background + λ (λ-pinned) together with P(r) |
deer_invert_mellin(t, V, …) |
Model-free analytic Mellin-transform inversion (auto cutoff, MC CI) |
deer_validate(t, V, …) |
Ensemble validation: background-sweep → median P(r) + uncertainty band |
residual_whiteness(resid, …) |
Residual goodness-of-fit (Durbin–Watson, lag-1 autocorrelation, ACF) |
fit_zero_time(t, V, …) |
Fit the dipolar zero-time t₀ (reference time) |
tikhonov_ci(K, F, alpha, P, …) |
Covariance 95% confidence band on the Tikhonov P(r) |
dipolar_kernel(t, r, …) |
Orientation-averaged kernel K(t, r) (Fresnel closed form) |
dipolar_frequency(r, …) |
Perpendicular dipolar frequency ν⊥(r) = ν_dd/r³ |
background_fit(t, V, bg_start, bg_end=None, …) |
Fit intermolecular background on a tail window (sequential) |
joint_background(t, V, …) |
λ-pinned joint background only (coarse, hardened; backs the Mellin engine) |
tikhonov_nnls(K, F, alpha, L=None) |
Non-negative Tikhonov solve K P = F |
regularization_matrix(n, order=2) |
Derivative operator L for smoothing |
l_curve(K, F, alphas, L=None, method='gcv') |
Regularization scan; α by GCV (default) or Menger L-corner |
mellin_kernel_spectrum(tau, …) |
Mellin image Φ(½+iτ) of the dipolar kernel (closed form) |
mellin_signal_spectrum(t, F, tau, delta, …) |
Mellin image Ṽ(½+iτ) of the form factor (δ-split) |
mellin_inverse(P_tau, tau, w) |
Inverse Mellin transform → p(w) |
mellin_delta(t, F, level=0.95) |
Auto Mellin split point δ (F(δ) ≈ 0.95) |
default_r_axis(rmin=1.5, rmax=8.0, n=200) |
Default distance grid (nm) |
simulate(t, r, P, …) |
Forward-simulate a DEER trace from P(r) |
Coherence pathways & phase cycling¶
import atomize.math_modules.coherence_pathways as coh
Pure-Python (no scipy) bookkeeping for pulse-EPR phase cycles: expand short phase-cycle notation, then enumerate every coherence transfer pathway and see which the cycle keeps vs phases out, where each surviving echo lands, and which FIDs survive. Selection rule, not amplitudes (Stoll 2008; Prisner 2016).
| Function | Description |
|---|---|
expand_phase_cycling(recv, *pulse_phases) |
Expand short notation (x)/[x]/lists/coeffs into per-step pulse + receiver phases |
analyze_pathways(recv, pulse_phases, positions, det_pos) |
Enumerate pathways; classify kept/suppressed, echo positions, FIDs |
pathway_report(recv, pulse_phases, positions, det_pos) |
Ready-to-print summary table of the above |
positions_from_taus(taus, base=0.0, grid=None) |
Cumulative pulse positions from inter-pulse delays (optional grid snap) |
Pulse excitation profiles¶
import atomize.math_modules.pulse_excitation as pe
Excitation/inversion profiles of shaped pulses (rectangular, gaussian, sinc,
sine, WURST, sech/tanh) across resonance offset, by full Bloch/propagator spin
dynamics of a single S=1/2 — the EasySpin exciteprofile approach, correct for
adiabatic pulses, not just the FFT approximation. Pure NumPy (no scipy).
Frequencies/offsets in GHz, times in ns; shape params in MHz.
| Function | Description |
|---|---|
excitation_profile(shape, tp, nu1, offsets, params, …) |
Single-pulse Mx/My/Mz vs offset from an initial state |
waveform(shape, t, tp, params) |
Amplitude envelope + instantaneous frequency of a shape |
flip_angle(shape, tp, nu1, params, dt=0.5) |
On-resonance flip angle (pulse area) |
propagate_pulse(M, shape, tp, nu1, offsets, params, …) |
Apply one pulse to a Bloch-vector array (chain for sequences) |
free_evolution(M, offsets, tau) |
Free precession for tau ns (z-rotation by offset) |