Releases: tum-ees/PyDMA
Release list
v2.1.0
Changed
- Python 3.10 and 3.11 are supported again;
requires-pythondrops from 3.12
to 3.10. The entire 3.12 requirement came down to the two PEP 695type
aliases inpydma.utils.roi, which now usetyping.TypeAliasand parse on
every supported interpreter. Runtime behavior is unchanged. - The pinned-minimum CI leg runs on Python 3.10 and black targets 3.10. mypy
keeps the 3.12 grammar, because current numpy stubs use PEP 695 syntax that
mypy refuses to parse under an older target; the floor itself is enforced by
the 3.10 CI leg. On 3.10 the resolver serves at mostnumpy2.2 /
scipy1.15, since newer releases of both dropped 3.10 wheels.
v2.0.0
Major release with breaking changes: removed exports, keyword-only
fit_* signatures, and hard errors where earlier versions silently
degraded. popsize now means what it says, and the full-cell
reconstruction gained an optional fitted series resistance (default
off).
Added
-
Fitted series-resistance correction for the full-cell reconstruction (default
off):DMAConfig.allow_resistance_offsetwithpocv_current_a,
resistance_offset_limit_ohm_ah, andallow_negative_resistance_offset.
Parameter slot 9 (r_offset_ohm, in Ohm) lifts the model OCV by
sign(direction) * R * |I|. DVA and ICA never read the slot; a constant would
drop out of their derivatives anyway. With the flag off the slot is pinned to
zero, and every stored 8-parameter vector expands to the same reconstruction as
before. -
apply_aginginpydma.utils.balancing: derives an aged electrode balancing at
fixedc_maxby scalingeps_swith1 - LAM. The former docstring recipe
cancelled LAM out ofQ_nand is documented as such. -
FittedParams.from_dict,DMAResult.config_snapshotfor fit provenance, and
the accepted-run parameter scatter (param_std) onDMAResult. -
csv_kwargspassthrough in the loaders (for example{"sep": ";", "decimal": ","}),cathode_conventionin the OCP-model window functions,x_is_socin
the comparison plots,include_geometryinpybamm_overrides. -
Loud validation: blend electrodes must match
use_anode_blend/use_cathode_blend,
OCP curves must be finite, ROI bounds must be SOC fractions,DMAConfigrejects
unknown attributes and re-validates on assignment,CellGeometryrejects
non-positive fields. -
An expanded regression suite: hand-derived LAM/LLI expectations, direct PAV
pooling checks, plot smoke tests with an rcParams invariance check, aging-study
gap discovery, and a resistance-offset acceptance suite.
Changed
-
popsizenow sets the actual differential-evolution population size regardless
of pinned parameter slots; the effective population no longer shrinks as
features are disabled. -
lfp_presetselects the intended split OCV ROI (0-15 % and 85-100 % SOC)
instead of the full range. -
load_aging_studydiscovers every present check-up by listing the directory and
warns about missing indices instead of stopping at the first gap. -
Objective failures raise or warn once instead of silently returning the penalty
value for every exception; an empty ROI is a configuration error and raises. -
Plot functions no longer mutate global
plt.rcParams; styles are scoped per
call. -
Electrode and blend interpolation clamps at the support edges instead of
returning 0.0 outside the support. -
derive_balancing_from_resultdefaults toon_out_of_range="raise"and reports
clipping explicitly. -
fit_ocv/fit_dva/fit_ica/combined_objectivetake ROI and flag arguments
keyword-only; the inertinhom_pointsparameter is gone. The three fit terms
share precomputed electrode potentials with bit-identical results.
Fixed
-
Type checking passes across matplotlib releases. matplotlib 3.11 types the
rc_contextmapping by the literal set of rcParams names it ships with, which
a plain string-keyed dict does not satisfy, so the plotting module applies its
style through a single wrapper. Plot output is unchanged. -
voltage_anchored_windowsinverts only the strictly monotonic part of the
reconstruction, keeping interpolation fill artefacts out of the anchored
windows. -
DVA/ICA edge guards (zero denominators, fewer than two points, NaN inputs),
.matNaN filtering, direction-symmetric pOCV file matching, and
calculate_msereturninginffor an empty mask.
Removed
- Dead API:
calculate_full_cell_ocv,create_optimizer_from_config,
run_single_fast,SiliconCurveParams,calculate_inhomogeneity_for_electrode,
DMAConfig.get_bounds,DMAConfig.calculate_roi_bounds, and the
never-populatedis_cyclic/fit_reversefields,get_potential_at_scaled_soc.
v1.1.2: fix silent voltage-support loss in the plateau collapse
Patch release.
Fixed
_collapse_plateausno longer loses voltage support silently. Shifts are
bounded by the neighbouring level gap, boundary plateaus shift inward only,
the range clamp is gone, and a fully pooled curve keeps both exact range
edges.- The function states its contract explicitly. ValueError for non-finite
input, constant curves and overflowing ranges. RuntimeError if the output is
non-finite, not strictly monotone or does not preserve both range endpoints
exactly.
Changed
- Default outputs, the raw-PAV PCHIP path and the committed M35A tables are
unchanged and verified bit-identical. Only opt-incollapse_plateaus=True
calls change, intentionally. - Ruff pinned to the 0.15 release line for the lint gate.
Details in the CHANGELOG.
v1.1.1 — citation metadata, reproducible release gates, loader fix
Maintenance release focused on software citation, reproducible release tooling,
and cross-platform reliability. No scientific algorithms or public APIs changed.
Highlights
- Software citation metadata. Added
CITATION.cffwith the three PyDMA
creators and the Journal of Power Sources framework paper as the preferred
citation, ready for Zenodo ingestion. - Reproducible release gates. Added GitLab CI and public GitHub Actions
checks covering Python 3.12 minimum dependencies and Python 3.14 current
dependencies, formatting, linting, typing, tests, scientific regressions,
and package builds. - Repository cleanup. Applied the pinned Black and isort formatting,
aligned development dependencies and pre-commit hooks, and removed
workstation-specific notebook output. - Current typing compatibility. Updated NumPy and Matplotlib typing without
changing runtime behavior. - Cross-platform loader fix. Fixed charge/discharge CSV selection in
aging-study directories so it no longer depends on filesystem iteration
order.
Verification
- 37 normal tests passed
- 2 scientific regression tests passed
- Python 3.12 and 3.14 CI passed
- Wheel and source distribution passed
twine check - Clean PyPI installation and loader smoke test passed
Install
pip install --upgrade pydma==1.1.1v1.1.0 — Python 3.12 floor, PyBaMM-safe Si OCP, seeded golden tests
v1.1.0 — Python 3.12 floor, PyBaMM-safe Si OCP, seeded golden tests
Major release. Drops Python 3.9-3.11, modernizes typing, adds a PyBaMM-stable silicon OCP filter, and locks scientific behavior with a seeded regression suite.
Highlights
- PyBaMM-safe silicon OCP filter. New
pydma.silicon.strict_sto.pchip_resample_for_pybammproduces a smooth strictly-monotone Si OCP on a uniform sto grid with an optional endpoint-V snap. More stable for PyBaMM's CasADi/IDAS interpolant. Replaces the previousstrict_sto_eps_spreadhelper. - LOWESS-on-PCHIP gotcha documented. When re-fitting a PCHIP-output curve through PyDMA itself, set
DMAConfig(smoothing_points=1)— the default30over-smooths the already-smoothed input and the optimizer basin-escapes (measured on Molicel M35A in discharge direction: RMSE 3.3 → 21 mV, γ_Si 0.293 → 0.18; M35A dataset not included). - Python ≥ 3.12 required. Drops 3.9–3.11 and the
from __future__ import annotationsshims. Runtime floors bumped to the lowest 3.12-wheel releases:numpy>=1.26,scipy>=1.11.4,pandas>=2.1.1,matplotlib>=3.8,statsmodels>=0.14. - Deterministic optimizer + scientific regression suite.
DMAConfig.random_seedis now a real settable field (defaultNonepreserves prior nondeterministic behavior). New opt-inpytest -m scientificsuite locks down a seeded P45B/NCA fit against golden RMSE / parameter / degradation-mode numbers, and skips cleanly from an unpacked sdist when its data files aren't present. - Maintainer ops. Added
RELEASING.mdchecklist; both tutorial notebooks (getting_started.ipynb,pybamm_integration.ipynb) are now release artifacts. Internal: typing modernized to PEP 585/604/695 andmypy src/pydmais clean.
Install
pip install --upgrade pydma==1.1.0
PyPI: https://pypi.org/project/pydma/1.1.0/ · Full notes: CHANGELOG.md
v1.0.2 — PyDMA → PyBaMM balancing bridge
A PyDMA fit now plugs directly into a PyBaMM ParameterValues.
Highlights
- PyDMA → PyBaMM bridge. The new
pydma.utils.balancingmodule derivesc_maxandc_init(SoC)directly from a voltage-anchored PyDMA fit plus the user-supplied cell geometry.ElectrodeBalancing.pybamm_overrides(soc)returns a dict keyed by PyBaMM's exact parameter names, ready forpybamm.ParameterValues.update(...). - New notebook
notebooks/pybamm_integration.ipynb: end-to-end bridge for the Molicel INR21700-P45B, verified by a C/500 DFN charge round-trip. All material/geometry values come from Frank et al. (2025), Table III (DOI 10.1149/1945-7111/adc03c). Chen2020 is used only as a public Li-ion fallback base for parameters Frank et al. do not document. - New data file
notebooks/parameter_data/frank2025_p45b_table_iii.json: 24 Frank et al. Table III constants as{value, unit, source}. notebooks/getting_started.ipynbis now purely a DMA-analysis tutorial.
Install
pip install --upgrade pydma==1.0.2PyPI: https://pypi.org/project/pydma/1.0.2/ · Full notes: CHANGELOG.md
v1.0.1 — corrected voltage-anchored stoichiometry export
Highlights
- Stoichiometry windows now match the requested voltage cutoffs. Anode and cathode stoichiometry windows are anchored to the fitted reconstructed cell voltage at the requested voltage limits, via
DMAResult.voltage_anchored_windows(...). The previous output used raw internal fit-window endpoints, which in most cases did not correspond to the measured pseudo-OCV voltage cutoffs — exported values were systematically off for downstream consumers. For inhomogeneous fits, the anchored values are the central/nominal stoichiometries of the fitted trajectory. - Composite anode phase mapping.
BlendElectrode.get_component_stoichiometries(...)andBlendElectrode.get_component_stoichiometry_window(...)map a fitted blend coordinate to per-phase graphite/silicon stoichiometries, so anchored blend coordinates are also exported as Gr/Si stoichiometry windows. - Per-phase inspection helper.
FittedParams.sto_window_an_per_phase(...)exposes raw per-phase windows when needed. - Strictly monotone silicon OCP.
generate_si_curve(monotone_filter=True)now returns strictly monotone output, making the filtered curve safe for downstream spline interpolation (e.g. PyBaMM preprocessing) without changing fitting results. - Updated
getting_started.ipynbto demonstrate fitted-reconstruction voltage anchoring and anchored Gr/Si phase windows.
See the full CHANGELOG.md for details.
v1.0.0
Highlights
- New: inhomogeneity offset (
inhom_anode_offset,inhom_cathode_offset) — MATLABinhomOffsetFractionparity. - Numerical:
q0restored to MATLAB parity (span of the normalized SOC axis). Fits withweight_dva > 0and/orweight_ica > 0may differ slightly from PyDMA ≤ 0.1.0. OCV-only fits are unaffected.
Install: pip install pydma==1.0.0
Added
- Inhomogeneity offset for anode and cathode (
DMAConfig.inhom_anode_offset,
DMAConfig.inhom_cathode_offset, default0.0, validated[0, 1]). A
positive offset allows a fraction of the maximum inhomogeneity spread to
be present already at SOC = 0 instead of starting from zero. Setting the
offset to1.0reproduces SOC-independent inhomogeneity, which is
analogous to earlier degradation mode analysis frameworks in literature.
Matches MATLAB's newinhomOffsetFractionargument
(calculate_inhomogeneity.m). DMAAnalyzer.analyze_aging_study(path, ...)convenience API that accepts
a directory or single.matfile, loads it using the configured
direction, and runs every CU.- Top-level
load_aging_studyexport and support for single-file multi-CU
.matpayloads in the loader. - Isotonic-regression-based silicon OCP filtering in
generate_si_curve,
producing strictly monotonic curves while keeping the maximum amount of
information. - Regression tests pinning MATLAB-parity invariants (q0, fitted-bounds,
degradation-mode delegation, inhomogeneity offset formula, loader CU
handling, reset-state completeness,FittedParamsNonehandling).
Changed
- Numerical:
q0now matches MATLAB (span of the normalized SOC axis,
≈ 1.0) instead of the raw Ah span. Because the DVA and ICA cost
contributions scale asq0², this may produce small numerical
differences compared with older PyDMA versions whenweight_dvaand/or
weight_icaare non-zero. In return, fits are now cell-size independent
and consistent with the MATLAB-tunedweight_dva/weight_icadefaults.
OCV-only fits (weight_dva = 0,weight_ica = 0) are unaffected. - Breaking:
compare_with_referencenow delegates to
calculate_degradation_modes, so blend LAMs
(lam_anode_blend1/2,lam_cathode_blend1/2) are populated rather
than silently zero. Constructor keyword arguments forDegradationModes
renamedlam_an/lam_ca→lam_anode/lam_cathode(the short
names remain available as read-only property aliases). DMAConfig.algorithmis now actually consumed by the optimizer, and
DMAConfig.get_initial_guess()now includes blend-weight initial values.- Aging-study runs now populate real
fit_ocv_mse/fit_dva_mse/
fit_ica_mseand theis_accepted/status/algorithmmetadata
on everyDMAResultinstead of placeholder values. - Aging-study loader honors the configured
directionwhen choosing
per-CU folders.
Fixed
- Inhomogeneity out-of-range clamping now uses
np.interp(..., left=voltage[0], right=voltage[-1]), matching MATLAB
griddedInterpolant(..., 'linear', 'nearest'). The previous code
clamped both OOB sides tovoltage[-1], a latent mismatch that affected
fits even wheninhom_offset = 0. compare_with_referencenow falls back to
self.reference_data.reference_capacity, and its capacity-loss guard
protects against division by zero (reference_capacity == 0).FittedParamstype annotations andto_array()correctly handleNone
for disabled blend/inhomogeneity parameters and always return a
float64numpy array.DMAAnalyzer.reset_statenow also clears_capacity_historyand the
normalized-SOC warning flag, so repeated aging studies start clean.- Loader now handles nested
.matstructs (mat_struct) and single-file
multi-CU.matpayloads, and falls back to direction-based folder
matching when no explicit CU markers are present. - Reoriented-OCV warning is now one-shot and only fires when
auto-correction implies a direction opposite toconfig.direction. DMAConfignow validates blend initial guesses against their upper
bounds and rejects out-of-range inhomogeneity offsets at construction
time.
Removed
- Dead
DMAConfigfields and the unused internaldirectionthreading
in the loader's CU matcher.