What’s New in Revision 0.12.0
These are the changes in SpectroChemPy-0.12.0. See Release notes for a full changelog, including other versions of SpectroChemPy.
New Features
MCRALS now supports three dimensionless stopping tolerances:
tol_residual_change(default1e-3),tol_reconstruction_error, andtol_profile_change. The latter two are disabled by default. The optimisation stops when any enabled criterion is satisfied, andresult.diagnosticsreports all three values together withconvergence_reason. The INFO log now displaysreconstruction_error,residual_change,profile_change, and the residual trend, followed by the exact value and tolerance responsible for convergence. The formerRSE / PCA,RSE / Exp, and%changecolumns have been removed because they did not map clearly to the stopping criteria.NMR support has been significantly expanded. SpectroChemPy now provides
scp.nmr.Experimentas a state-aware NMR scientific model, alongside new official readers for Agilent/Varian, JEOL JDF, TecMag TNT, and SIMPSON datasets. These readers integrate with the plugin I/O namespaces (scp.nmr.read(...),scp.topspin.read(...),scp.agilent.read(...)) while preserving the familiar root-level compatibility aliases. The currently validated public workflow is centered on 1D NMR data; the 2D workflow remains under separate scientific characterization. Extra NMR validation datasets can also now be fetched on demand withdownload_extra_testdata().TopSpin datasets now preserve a descriptive vendor processing profile in
dataset.meta.nmr_processing, and the result ofscp.nmr.Experiment.process()now records a structured SpectroChemPy-owned processing trace inresult.meta.nmr_processing["scp_processing"]. Vendorprocsvalues remain descriptive, the source dataset remains unchanged,requestedkeeps only arguments explicitly provided by the user,appliedkeeps only operations that actually ran, andphase="metadata"still does not replay TopSpinPHC0/PHC1.read_matlab()now reconstructsNDDatasetobjects from the minimal MATLAB exchange payload written bywrite_matlab(), restoring the dataset’s name, title, units, description, dimension names, and coordinates (values, units, and titles). (#1270)Plotting and analysis displays are more informative by default. Score-plot labels can now use
adjustTextfor collision-aware placement, and PCA components are displayed withPC1,PC2, … labels in legends and coordinate displays instead of generic#0,#1, … identifiers.
Bug Fixes
scp.nmr.Experiment.process()now forwards the full explicit public apodization contract for the modes it already exposes:em(lb=...),gm(lb=..., gb=...), andsp(ssb=..., pow=...). Incompatible parameter combinations such asapodization=\"em\", gb=...orapodization=None, lb=...now raise explicit errors instead of being silently ignored.read_matlab()no longer crashes onmatfiles containing a plain MATLAB cell-array variable. It previously raised an unguardedTypeError(surfaced only as a swallowedUserWarning, with the function silently returningNone), or, for files with other variables alongside the cell array, anAttributeErrorin the dataset-merging step. Such variables are now safely skipped with a warning. (#1270)NMR reader and processing reliability has improved substantially. TopSpin metadata handling is more robust,
scp.nmr.Experimentnow correctly classifies non-Bruker datasets, and JEOL time-domain coordinates are created with the proper units so operations such asem()no longer fail on JEOL time-domain data.em(lb=0)andem(lb=0.0 * ur.Hz)are now treated as valid no-op calls instead of raising aZeroDivisionError.Public NMR documentation and examples no longer imply that 2D processing is already a stable supported workflow. The public API, gallery and maintainer messaging are now aligned on a temporary recentring to validated 1D NMR processing while the 2D pipeline continues as a separate characterization effort. The gallery no longer publishes the unstable CP and 2D workflows, the apodization and relaxation examples were clarified visually, and inverse FFT reconstruction now restores a correct NMR time axis in the 1D Fourier tutorial.
Plotting behavior has been corrected in several visible edge cases:
plot()andplot_multiple()no longer crash whenmarker=Noneorls=Noneis passed explicitly, 2Dplot_map()/plot()now keep a readable layout when X and Y share units but span very different numeric ranges, explicitfigsize=...overrides are honored more reliably withclear=False, andlegend=Trueagain works as expected for 2D lines/stack plots with coordinate-derived labels. (#1460, #1462)
Breaking Changes
The public NMR scope is now stated more narrowly and more honestly. The TopSpin reader (
scp.nmr.read_topspin) now supports 1D and 2D data only, with 3D/4D reads raisingNotImplementedError, and the publicscp.nmr.Experiment.process()workflow is intentionally limited to validated 1D NMR experiments. Multi-dimensional datasets may still be read, classified and inspected, but 2D processing is temporarily out of the public supported scope while the scientific characterization work continues.MCRALS.constraintsis now a validated traitlet, enabling both constructor and post-construction assignment while preserving the distinction betweenNone(built-in defaults) and[](explicitly unconstrained fit). Assignment ofconstraintsafter fitting invalidates the fitted state. Theconstraintsparameter is not config-file serializable.MCRALS public outputs
C,Stand residuals now correspond to the constrained factor pair(C_constrained, St_constrained)instead of the previous mixed pair(C_LS, St_constrained), and the unconstrained least-squares estimate is now exposed separately viaC_ls. The internal ALS iteration loop was also realigned with the standard Tauler formulation so each iteration performs one C solve plus constraint pass and one St solve plus constraint pass. Together these changes align SpectroChemPy more closely with Tauler MATLAB MCR-ALS, pyMCR, and PLS_Toolbox, but they can change convergence speed, iteration counts, and numerical results under active constraints while preserving the documentedC @ St ≈ Xreconstruction invariant. (#1453)
Deprecations
MCRALS public documentation now exposes only dimensionless convergence tolerances, profile-specific solvers, and the unified
constraintsAPI.Plotting names are being regularized:
AnalysisBase.plotmeritis deprecated in favor ofplot_merit, andparityplotis deprecated in favor ofplot_parity. The old aliases remain available for now and are scheduled for removal in version 0.13.0.
Developer
Added comprehensive regression coverage for the
write_matlab()/read_matlab()minimal exchange payload: non-default dimension names, a true 1D round trip, an empty-coordinate edge case, and adversarial cases where a file shares the right variable names but the wrong structure. (#1270)The NMR test suite has been modernized and made substantially more reliable: skipped legacy FFT tests were reactivated, visual-only tests were replaced with numerical assertions, and targeted plugin tests now check observable processing behavior instead of manual inspection only.
Plotting internals, examples, and plugin infrastructure were also cleaned up: shared figure/axes lifecycle helpers now reduce duplicated boilerplate, composite plotting APIs are more consistent, the non-functional Plotly/Dash backend has been removed from the maintained code path, examples now favor SpectroChemPy-native idioms over raw NumPy patterns, generic NMRGlue helpers were factored into a shared base module, and the official plugin marker used by CI and publishing now relies on the private
[tool.spectrochempy] official-plugin = truefield instead of an invalid Trove classifier.