Version 0.4.0 ============= **Release Date:** June 2026 **Status:** Stable release New: relaxation fitting module ------------------------------ A new package, ``epyr.relaxation``, fits time-domain T1/T2 relaxation data, complementing the existing field-domain lineshape fitting in ``epyr.lineshapes.fitting``. - ``epyr.relaxation.models``: six decay/recovery functions, ``mono_exponential``, ``stretched_exponential``, ``biexponential``, ``inversion_recovery``, ``saturation_recovery``, and ``gamma_gaussian_decay`` (a combined homogeneous/spectral-diffusion echo-decay model). - ``epyr.relaxation.fit_relaxation()``: fits a single decay/recovery curve with any of the six models, returning a ``RelaxationFitResult`` with parameters, errors, R-squared, reduced chi-squared, and an optional annotated plot. Mirrors the existing ``fit_epr_signal()`` API. - ``epyr.relaxation.fit_multiple_decays()``: fits several candidate models and ranks them by reduced chi-squared (not R-squared, which is biased toward models with more free parameters) to suggest the best-supported decay model for a given dataset. - New example script ``examples/clean/06_relaxation_fitting.py`` demonstrates all three entry points on a real T2 echo decay and on synthetic bi-exponential and Gamma0/GammaG data. Relaxation fitting: readable results and rcParams-aware plots --------------------------------------------------------------- - ``RelaxationFitResult.__repr__`` now returns ``summary()``, so a single fit result prints its parameters and errors directly instead of dumping the raw dataclass fields (including the full fitted-curve and residual arrays). - ``fit_multiple_decays()`` now returns ``RelaxationFitComparison``, a ``dict`` subclass that behaves exactly like the plain dict it replaces (subscripting, ``.items()``, iteration) but whose ``__repr__`` prints a side-by-side table of R-squared, chi-squared, and every fitted parameter across all models. - Fit plots (``_plot_fit_results``, ``_plot_comparison``) no longer hard-code figure size, marker size, line width, or text size. They reuse the current figure's size if one is already open, otherwise fall back to ``matplotlib.rcParams`` defaults, and likewise read marker/line/font size from ``rcParams`` rather than overriding them. The identical change was applied to ``epyr.lineshapes.fitting`` for consistency between the two fitting modules. Tutorial notebooks rebuilt -------------------------- The ``examples/notebooks/`` directory was rebuilt into an eight-notebook series (``00`` index plus ``01``-``07``) covering loading and plotting, baseline correction, lineshape fitting, relaxation fitting, signal processing, FAIR conversion, and physics/units. Each notebook runs top to bottom on the bundled datasets and is committed without cell outputs. Superseded notebooks are archived under ``examples/notebooks/_legacy/``. Bug fix: batch FAIR conversion ------------------------------ ``batch_convert_directory()`` forwarded the wrong keyword names to ``convert_bruker_to_fair()`` (``input_file_or_dir`` and ``output_formats``), raising ``TypeError`` for every file and producing no output. It now passes ``input_file`` and ``formats`` correctly, so batch conversion writes the requested formats. A regression test covers this. No backwards-incompatible changes.