Skip to content

API reference

fasteis.Element

A single circuit element.

Each variant is a subclass taking its fields as arguments. They are combined with Series() and Parallel().

R

Bases: Element

Ideal resistor, Z = r.

Parameters:

Name Type Description Default
r float

Resistance in ohm.

required

C

Bases: Element

Ideal capacitor, Z = 1 / (jwc).

Parameters:

Name Type Description Default
c float

Capacitance in F.

required

L

Bases: Element

Ideal inductor, Z = jwl.

Parameters:

Name Type Description Default
l float

Inductance in H.

required

La

Bases: Element

Modified inductance, Z = (jwl) ** alpha.

Reduces to an ideal inductor at alpha = 1.

Parameters:

Name Type Description Default
l float

Inductance in H*s.

required
alpha float

Fractional exponent in [0, 1].

required

Cpe

Bases: Element

Constant phase element, Z = 1 / (q * (jw) ** alpha).

Reduces to a capacitor of q farads at alpha = 1, and to a resistor of 1 / q ohm at alpha = 0.

Parameters:

Name Type Description Default
q float

Admittance prefactor in ohm^-1*s^alpha.

required
alpha float

Fractional exponent in [0, 1].

required

W

Bases: Element

Semi-infinite Warburg diffusion, Z = aw * (1 - j) / sqrt(w).

Parameters:

Name Type Description Default
aw float

Warburg coefficient in ohm*s^-0.5.

required

Wo

Bases: Element

Finite-length open Warburg, Z = z0 / (x * tanh(x)) with x = sqrt(jw*tau).

The reflecting boundary case, for diffusion into a blocked layer.

Parameters:

Name Type Description Default
z0 float

Impedance scale in ohm.

required
tau float

Diffusion time constant in s.

required

Ws

Bases: Element

Finite-length short Warburg, Z = z0 * tanh(x) / x with x = sqrt(jw*tau).

The transmissive boundary case, for diffusion into a reservoir.

Parameters:

Name Type Description Default
z0 float

Impedance scale in ohm.

required
tau float

Diffusion time constant in s.

required

G

Bases: Element

Gerischer element, Z = rg / sqrt(1 + jw*tg).

For diffusion coupled to a homogeneous chemical reaction. Reduces to a resistor at tg = 0.

Parameters:

Name Type Description Default
rg float

Gerischer resistance in ohm.

required
tg float

Reaction time constant in s.

required

Gs

Bases: Element

Finite-length Gerischer, Z = rg / (s * tanh(s*phi)) with s = sqrt(1 + jw*tg).

Parameters:

Name Type Description Default
rg float

Gerischer resistance in ohm.

required
tg float

Reaction time constant in s.

required
phi float

Dimensionless layer-thickness factor.

required

K

Bases: Element

Debye relaxation, Z = r / (1 + jw*tau_k).

A resistor and capacitor in parallel, as a single element.

Parameters:

Name Type Description Default
r float

Polarisation resistance in ohm.

required
tau_k float

Relaxation time constant in s.

required

Zarc

Bases: Element

Depressed semicircle, Z = r / (1 + (jw*tau_k) ** gamma).

A resistor and constant phase element in parallel, as a single element. Reduces to K at gamma = 1.

Parameters:

Name Type Description Default
r float

Polarisation resistance in ohm.

required
tau_k float

Relaxation time constant in s.

required
gamma float

Depression exponent in [0, 1].

required

Tlmq

Bases: Element

Transmission line with a constant phase element surface impedance.

Z = sqrt(r_ion*zs) / tanh(sqrt(r_ion/zs)) for a distributed pore of surface impedance zs = 1 / (qs * (jw) ** gamma).

Parameters:

Name Type Description Default
r_ion float

Ionic pore resistance in ohm.

required
qs float

Surface admittance prefactor in F*s^(gamma-1).

required
gamma float

Fractional exponent in [0, 1].

required

T

Bases: Element

General transmission line.

Z = a*coth(beta)/beta + b*cosech(beta)/beta, where beta = sqrt(k_tau + jw*tau).

From Electrochimica Acta 38, 2653 (1993), DOI: 10.1016/0013-4686(93)85083-B

Parameters:

Name Type Description Default
a float

Coefficient of the coth term, in ohm*m^2.

required
b float

Coefficient of the cosech term, in ohm*m^2.

required
k_tau float

Charge-transfer rate constant times tau, dimensionless.

required
tau float

Transport time constant in s.

required

fasteis.Circuit

An equivalent circuit: elements in series and parallel, with their values.

Build one by parsing a topology string, or by composing elements with Series() and Parallel().

__init__

__init__(s: str) -> None

Parse a circuit topology string, e.g. "R0-(R1,CPE1)".

The string carries no parameter values, so every element starts at a placeholder default. Set real values with with_values(), with_named_values(), or fit(guess_init=True).

Also accepts the name of a built-in circuit, e.g. "randles"; see ml_circuits().

Parameters:

Name Type Description Default
s str

Topology string, or the name of a built-in circuit.

required

Raises:

Type Description
ValueError

The string is not valid circuit syntax.

ml_circuits staticmethod

ml_circuits() -> dict[str, str]

Built-in circuits that have trained initial-parameter models.

These get a guessed starting point from fit() by default.

guess

guess(
    frequencies: _FloatArray | _DataFrame,
    impedances: _ComplexArray | None = None,
    *,
    weights: str | None = None,
) -> list[float]

Machine-learning guess of starting parameters for this topology.

Series and parallel elements may be written in any order and with any labels: (R1,C2)-R3 uses the same model as R0-(R1,C1). K and Zarc reach the models trained on the pairs they abbreviate, so R0-Zarc1 uses the R0-(R1,CPE1) model and gets its guess back as r, tau_k and gamma.

Parameters:

Name Type Description Default
frequencies _FloatArray | _DataFrame

Frequencies in Hz, or a battery data format dataframe with frequencies and impedances.

required
impedances _ComplexArray | None

Measured complex impedances in ohm, one per frequency. Leave as None when passing a dataframe.

None
weights str | None

Path to a custom .eisnn file to load, instead of looking for a bundled model.

None

Returns:

Type Description
list[float]

Starting values, in param_names() order.

Raises:

Type Description
ValueError

No model has been trained for this topology, or weights was trained for a different one.

param_names

param_names() -> list[str]

Parameter names, in the order used throughout this class.

with_values() consumes values in this order, and with_named_values() expects these as keys.

with_values

with_values(values: _FloatArray) -> Circuit

Rebuild this circuit with a new flat parameter vector.

Parameters:

Name Type Description Default
values _FloatArray

One value per parameter, in param_names() order.

required

Raises:

Type Description
ValueError

The wrong number of values was supplied, or a value is outside param_bounds().

with_named_values

with_named_values(values: dict[str, float]) -> Circuit

Rebuild this circuit with parameter values looked up by name.

Parameters:

Name Type Description Default
values dict[str, float]

Values keyed by param_names(). Every name must be present, and no unknown names may be supplied.

required

Raises:

Type Description
ValueError

Names are missing or unrecognised, or a value is outside param_bounds().

impedance

impedance(
    frequencies: _FloatArray | _DataFrame,
) -> NDArray[complex128]

Impedance of this circuit at each frequency.

Parameters:

Name Type Description Default
frequencies _FloatArray | _DataFrame

Frequencies in Hz, or a battery data format dataframe to take the frequency column from.

required

Returns:

Type Description
NDArray[complex128]

Complex impedances in ohm, one per frequency.

param_values

param_values() -> list[float]

Current parameter values, in param_names() order.

param_bounds

param_bounds() -> list[tuple[float, float]]

Physical-validity (lo, hi) bounds, in param_names() order.

Fractional exponents are bounded to [0, 1]; every other parameter is a positive magnitude with hi set to inf.

param_units

param_units() -> list[str]

Physical units, in param_names() order. "-" means dimensionless.

residuals

residuals(
    params: _FloatArray,
    frequencies: _FloatArray | _DataFrame,
    impedances: _ComplexArray | None = None,
    *,
    weight: Literal["modulus", "unit"] = "modulus",
) -> list[float]

Weighted residual vector for an arbitrary parameter vector.

The same building block fit() uses internally, exposed so that an external optimiser such as scipy.optimize.least_squares can be used.

Parameters:

Name Type Description Default
params _FloatArray

Parameter values, in param_names() order.

required
frequencies _FloatArray | _DataFrame

Frequencies in Hz, or a battery data format dataframe carrying the whole spectrum.

required
impedances _ComplexArray | None

Measured complex impedances in ohm. Leave as None when passing a dataframe.

None
weight Literal['modulus', 'unit']

Divide each residual by the modulus of the measured point, or leave it unweighted.

'modulus'

Returns:

Type Description
list[float]

Real and imaginary parts interleaved, [re0, im0, re1, im1, ...].

Raises:

Type Description
ValueError

params does not have one value per parameter.

jacobian

jacobian(
    params: _FloatArray,
    frequencies: _FloatArray | _DataFrame,
    impedances: _ComplexArray | None = None,
    *,
    weight: Literal["modulus", "unit"] = "modulus",
) -> list[list[float]]

Central-difference Jacobian of residuals() at params.

Parameters:

Name Type Description Default
params _FloatArray

Parameter values, in param_names() order.

required
frequencies _FloatArray | _DataFrame

Frequencies in Hz, or a battery data format dataframe with frequencies and impedances.

required
impedances _ComplexArray | None

Measured complex impedances in ohm. Leave as None when passing a dataframe.

None
weight Literal['modulus', 'unit']

Weighting scheme, matching residuals().

'modulus'

Returns:

Type Description
list[list[float]]

Shape (2 * len(frequencies), len(params)), where rows are

list[list[float]]

residuals and columns are parameters, as

list[list[float]]

scipy.optimize.least_squares(jac=...) expects.

Raises:

Type Description
ValueError

params does not have one value per parameter.

fit

fit(
    frequencies: _FloatArray | _DataFrame,
    impedances: _ComplexArray | None = None,
    *,
    guess_init: bool | None = None,
    weights: str | None = None,
    weight: Literal["modulus", "unit"] = "modulus",
    method: Literal[
        "levenberg_marquardt",
        "particle_swarm",
        "nelder_mead",
        "differential_evolution",
        "simulated_annealing",
        "basin_hopping",
    ] = "levenberg_marquardt",
    fixed: Mapping[str, float]
    | str
    | Sequence[str]
    | None = None,
    max_iterations: int = 200,
    ftol: float = 1e-08,
    xtol: float = 1e-08,
    num_particles: int = 200,
    generations: int = 1000,
    nelder_mead_iterations: int = 2000,
    de_evaluations: int = 20000,
    sa_iterations: int = 5000,
    sa_initial_temperature: float = 2.0,
    basin_hopping_hops: int = 20,
    basin_hopping_step_size: float = 1.0,
    basin_hopping_temperature: float = 1.0,
    seed: int | None = None,
) -> FitResult

Fit this circuit's parameters to a measured spectrum.

Parameters:

Name Type Description Default
frequencies _FloatArray | _DataFrame

Frequencies in Hz, or a battery data format dataframe with frequencies and impedances.

required
impedances _ComplexArray | None

Measured complex impedances in ohm. Leave as None when passing a dataframe.

None
guess_init bool | None

Left unset, start from a machine-learning guess whenever the circuit was not given explicit starting values, warning and falling back to placeholders if no model has been trained. True always guesses, and raises rather than warns when it cannot. False never guesses.

None
weights str | None

Path to a custom .eisnn file to guess with, instead of looking for a bundled model.

None
weight Literal['modulus', 'unit']

Divide each residual by the modulus of the measured point, or leave it unweighted.

'modulus'
method Literal['levenberg_marquardt', 'particle_swarm', 'nelder_mead', 'differential_evolution', 'simulated_annealing', 'basin_hopping']

Optimiser to run.

'levenberg_marquardt'
fixed Mapping[str, float] | str | Sequence[str] | None

Parameters to hold constant, keyed by param_names(). A dict holds them at the given values, a name or list of names at the circuit's current values. A machine-learning guess never overrides them.

None
max_iterations int

Iteration cap for levenberg_marquardt.

200
ftol float

Cost-change convergence tolerance for levenberg_marquardt.

1e-08
xtol float

Parameter-change convergence tolerance for levenberg_marquardt.

1e-08
num_particles int

Swarm size for particle_swarm.

200
generations int

Generation cap for particle_swarm.

1000
nelder_mead_iterations int

Iteration cap for nelder_mead.

2000
de_evaluations int

Evaluation budget for differential_evolution.

20000
sa_iterations int

Iteration cap for simulated_annealing.

5000
sa_initial_temperature float

Starting temperature for simulated_annealing.

2.0
basin_hopping_hops int

Number of hops for basin_hopping.

20
basin_hopping_step_size float

Perturbation size per hop.

1.0
basin_hopping_temperature float

Acceptance temperature for basin_hopping.

1.0
seed int | None

Fixes the random draws of the stochastic methods.

None

Returns:

Type Description
FitResult

The fitted parameters, their uncertainties, and fit diagnostics.

Raises:

Type Description
ValueError

fixed names an unknown parameter, holds a value outside param_bounds(), holds every parameter, or is a name or list on a circuit without values.

fasteis.FitResult

Outcome of Circuit.fit().

circuit instance-attribute

circuit: Circuit

The fitted circuit, carrying the optimised parameter values.

params instance-attribute

params: dict[str, float]

Fitted values keyed by Circuit.param_names().

stderr instance-attribute

stderr: dict[str, float] | None

Standard errors of parameters, or None when they cannot be estimated.

Taken from the diagonal of the inverted Gauss-Newton matrix, scaled by chi_square for each degree of freedom. None when the fit has no spare degrees of freedom, or when that matrix is singular. NaN for parameters held by fixed.

success instance-attribute

success: bool

Whether the optimiser reported convergence.

iterations instance-attribute

iterations: int

Optimiser iterations, counting residual calls only.

impedance_evals instance-attribute

impedance_evals: int

Number of impedance sweeps calculated during fit, including Jacobians and restarts.

cost instance-attribute

cost: float

Half the sum of squared weighted residuals, the quantity minimised.

chi_square instance-attribute

chi_square: float

Sum of squared weighted residuals, 2 * cost.