Source code for psc_sim.compare_metrics
"""Metrics for comparing Python vs LTspice I–V curves."""
from __future__ import annotations
import numpy as np
[docs]
def interpolate_current_at(
v_grid: np.ndarray,
v_samples: np.ndarray,
i_samples: np.ndarray,
) -> np.ndarray:
"""Linear interpolation of I(V) onto v_grid; NaN outside sample range."""
v_grid = np.asarray(v_grid, dtype=float)
v_samples = np.asarray(v_samples, dtype=float)
i_samples = np.asarray(i_samples, dtype=float)
ok = np.isfinite(v_samples) & np.isfinite(i_samples)
if ok.sum() < 2:
return np.full_like(v_grid, np.nan, dtype=float)
order = np.argsort(v_samples[ok])
vs = v_samples[ok][order]
is_ = i_samples[ok][order]
return np.interp(v_grid, vs, is_, left=np.nan, right=np.nan)
[docs]
def iv_curve_rmse(
v_ref: np.ndarray,
i_ref: np.ndarray,
v_other: np.ndarray,
i_other: np.ndarray,
) -> tuple[float, float]:
"""Return (rmse_A, max_abs_error_A) of i_other interpolated onto v_ref."""
i_interp = interpolate_current_at(v_ref, v_other, i_other)
ok = np.isfinite(v_ref) & np.isfinite(i_ref) & np.isfinite(i_interp)
if ok.sum() == 0:
return float("nan"), float("nan")
diff = i_ref[ok] - i_interp[ok]
rmse = float(np.sqrt(np.mean(diff**2)))
max_err = float(np.max(np.abs(diff)))
return rmse, max_err
[docs]
def eis_z_rmse(
zre_a: np.ndarray,
zim_a: np.ndarray,
zre_b: np.ndarray,
zim_b: np.ndarray,
) -> float:
"""RMSE on Re/Im components (same-length arrays)."""
d = (zre_a - zre_b) ** 2 + (zim_a - zim_b) ** 2
return float(np.sqrt(np.mean(d)))
[docs]
def eis_impedance_rmse(
freq_ref: np.ndarray,
zre_ref: np.ndarray,
zim_ref: np.ndarray,
freq_other: np.ndarray,
zre_other: np.ndarray,
zim_other: np.ndarray,
) -> float:
"""RMSE of complex impedance (Re/Im) with other interpolated onto freq_ref."""
zre_i = interpolate_current_at(freq_ref, freq_other, zre_other)
zim_i = interpolate_current_at(freq_ref, freq_other, zim_other)
ok = (
np.isfinite(freq_ref)
& np.isfinite(zre_ref)
& np.isfinite(zim_ref)
& np.isfinite(zre_i)
& np.isfinite(zim_i)
)
if ok.sum() == 0:
return float("nan")
diff = np.hypot(zre_ref[ok] - zre_i[ok], zim_ref[ok] - zim_i[ok])
return float(np.sqrt(np.mean(diff**2)))