Source code for ampworks.dqdv._tables

from __future__ import annotations

from typing import TYPE_CHECKING

import pandas as pd

from ampworks.utils import RichTable, RichResult

if TYPE_CHECKING:  # pragma: no cover
    from typing import Self
    from pathlib import Path


[docs] class DqdvFitResult(RichResult): """Container for a single dQdV fit.""" def __init__(self, **kwargs) -> None: """ Container for fits from the `DqdvFitter`. An instance of this class is returned from both the grid search and constrained fit methods. ========= ========= ============================================== Attribute Type Description ========= ========= ============================================== success bool whether or not the routine exited successfully message str description of the cause of termination nfev int number of function evaluations niter int number of optimization iterations fun float value of objective function at `x` Ah float max capacity (Ah) of the fitted `cell` dataset x 1D array the solution of the optimization x_std 1D array approximate standard deviation for each `x` x_map list[str] names/order of values store in `x` ========= ========= ============================================== """ super().__init__(**kwargs)
[docs] class DqdvFitTable(RichTable): """Container for many dQdV fits.""" _required_cols = [ 'Ah', 'xn0', 'xn0_std', 'xn1', 'xn1_std', 'xp0', 'xp0_std', 'xp1', 'xp1_std', 'iR', 'iR_std', 'fun', 'success', 'message', ] def __init__(self, extra_cols: list[str] | None = None) -> None: """ A container to store multiple dQdV fits. An instance of this class is required to run `calc_lam_lli`. Loop over multiple datasets and append fits one at a time to the table using the `append` method. Parameters ---------- extra_cols : list[str] or None, optional Any extra, non-required columns to add to the table. Pass the column names and their row values to `append` when writing each row. Use to track equivalent full cycles or other metrics with each fit. Raises ------ TypeError 'extra_cols' must be type list[str]. """ from ampworks._checks import _check_type if extra_cols is None: extra_cols = [] _check_type('extra_cols', extra_cols, list) self._extra_cols = extra_cols data = {col: [] for col in self._required_cols + self._extra_cols} df = pd.DataFrame(data) super().__init__(df)
[docs] @classmethod def from_csv(cls, path: str | Path) -> Self: """ Create a new instance from a CSV file. Parameters ---------- path : str or Path Path to the CSV file. Returns ------- table : Self A new instance initialized with data from the file. """ from pandas import read_csv df = read_csv(path) extra_cols = set(df.columns) - set(cls._required_cols) instance = cls(extra_cols=list(extra_cols)) instance._df = df return instance
[docs] def append(self, fit_result: DqdvFitResult, **extra_cols) -> None: """ Append a new row to the table. Parameters ---------- fit_result : DqdvFitResult A result from the `DqdvFitter's` grid search or constrained fit. extra_cols : dict, optional Any extra column names/values to include in the row. Raises ------ ValueError Columns cannot be created on the fly. Any extra columns must be defined at initialization. See Also -------- ~ampworks.dqdv.DqdvFitResult : Container for a single dQdV fit. """ row = { 'Ah': fit_result.Ah, 'fun': fit_result.fun, 'success': fit_result.success, 'message': fit_result.message, } # fill from x_map for idx, name in enumerate(fit_result.x_map): row[name] = fit_result.x[idx] row[name + '_std'] = fit_result.x_std[idx] # add in any extra columns for k in extra_cols.keys(): if k not in self.df.columns: raise ValueError( f"Column '{k}' does not exist in 'DqdvFitResult'. Extra" " columns must be defined during initialization." ) row[k] = extra_cols[k] # append the new row self.df.loc[len(self.df)] = row
[docs] class DegModeTable(RichTable): """Degradation modes table.""" _required_cols = [ 'Qn', 'Qn_std', 'Qp', 'Qp_std', 'Qc', 'LAMn', 'LAMn_std', 'LAMp', 'LAMp_std', 'LLI', 'LLI_std', ] def __init__(self, df: pd.DataFrame) -> None: """ Output container for `calc_lam_lli`. Stores capacities (Ah), loss of active material (LAM), loss of lithium inventory (LLI), and standard deviations (std). 'n', 'p', and 'c' in the column names refer to the negative electrode, positive electrode, and full cell, respectively. May also include extra columns inherited from the `DqdvFitTable`, if present. Parameters ---------- df : pd.DataFrame The input dataframe to store. See Also -------- ~ampworks.dqdv.calc_lam_lli : Calculate degradation modes from fits. """ super().__init__(df)