Source code for impedance_agent.fitters.linkk

# src/fitters/linkk.py
import numpy as np
import logging
from typing import Optional
from impedance.validation import linKK
from ..core.models import ImpedanceData, LinKKResult


[docs] class LinKKFitter:
[docs] def __init__(self, data: ImpedanceData): self.freq = data.frequency self.Z = data.real + 1j * data.imaginary self.logger = logging.getLogger(__name__)
[docs] def fit(self, c: float = 0.85, max_M: int = 100) -> Optional[LinKKResult]: """Perform Lin-KK analysis Args: c: cutoff ratio for determining optimal number of RC elements max_M: maximum number of RC elements to try Returns: LinKKResult object containing fit results """ try: self.logger.info("Starting Lin-KK analysis") M, mu, Z_fit, res_real, res_imag = linKK( f=self.freq, Z=self.Z, c=c, max_M=max_M, fit_type="complex", add_cap=True, ) # Calculate residuals and quality metrics residuals = np.abs((self.Z - Z_fit) / self.Z) max_residual = np.max(residuals) mean_residual = np.mean(residuals) self.logger.info("Lin-KK Results:") self.logger.info(f"M (RC elements): {M}") self.logger.info(f"mu parameter: {mu:.6f}") self.logger.info(f"Mean residual: {mean_residual:.6e}") self.logger.info(f"Max residual: {max_residual:.6e}") result = LinKKResult( M=M, mu=float(mu), Z_fit=Z_fit, residuals_real=res_real, residuals_imag=res_imag, max_residual=float(max_residual), mean_residual=float(mean_residual), ) self.logger.debug(f"Created LinKKResult object: {result}") return result except Exception as e: self.logger.error(f"Lin-KK fitting failed: {str(e)}", exc_info=True) return None