Skip to content

API Reference

BatteryProc exposes a programmatic Python API through the batteryproc.api module. This API mirrors the CLI's processing behaviour but returns structured result objects instead of printing to the console or calling sys.exit.

Use the API when you want to:

  • Embed battery data processing in a larger analysis pipeline.
  • Process files programmatically and inspect results in code.
  • Build custom workflows that go beyond what the CLI offers.

Quick Example

from pathlib import Path
from batteryproc.api import process_files
from batteryproc.batteryproc_types import ProcessOptions

# Configure processing options
options = ProcessOptions(
    outdir=Path("results"),
    energy=True,          # generate energy plots
    average=True,         # average replicate cells
    csv_export=True,      # export CSV data alongside plots
)

# Process multiple files
result = process_files(
    [Path("data/Cell_A1.xlsx"), Path("data/Cell_A2.xlsx")],
    options,
)

# Inspect results
print(f"Processed: {result.success_count} ok, {result.failure_count} failed")
for fr in result.files:
    print(f"  {fr.path.name}: {fr.status}")
    if fr.errors:
        for err in fr.errors:
            print(f"    ⚠ {err}")

Public Functions

process_file

process_file(input: Path, options: ProcessOptions | None = None) -> FileResult

Process a single battery data file.

Parameters:

Parameter Type Description
input Path Path to the data file (.xlsx, .csv, .txt, or .mpt).
options ProcessOptions \| None Configuration controlling outputs, metrics, and behaviour. Defaults to ProcessOptions() when omitted.

Returns: A FileResult describing the outcome.

Example:

from pathlib import Path
from batteryproc.api import process_file
from batteryproc.batteryproc_types import ProcessOptions

result = process_file(
    Path("data/cell_01.xlsx"),
    ProcessOptions(outdir=Path("output")),
)

if result.ok:
    print(f"Success: {result.path.name}")
else:
    print(f"Failed: {result.errors}")

process_files

process_files(
    inputs: Iterable[Path],
    options: ProcessOptions | None = None,
    *,
    pre_process: Callable[[Path], None] | None = None,
    post_process: Callable[[Path, FileResult], None] | None = None,
) -> ProcessResult

pre_process and post_process are keyword-only (they follow the * marker).

Process multiple files in sequence. This is the batch equivalent of process_file.

Parameters:

Parameter Type Description
inputs Iterable[Path] Paths to data files.
options ProcessOptions \| None Shared configuration for all files. Defaults to ProcessOptions() when omitted.
pre_process Callable[[Path], None] or None Optional keyword-only callback invoked before each file.
post_process Callable[[Path, FileResult], None] or None Optional keyword-only callback invoked after each file, with the file's FileResult.

Returns: A ProcessResult with per-file outcomes and aggregate counts.

When averaging is enabled (options.average or options.average_energy), averaged plots are generated after all individual files have been processed.


normalize_averaging_flags

normalize_averaging_flags(
    average: bool,
    average_energy: bool,
    average_ignore_plan: bool,
) -> tuple[bool, bool, str | None]

Ensures that --average-ignore-plan alone still activates capacity averaging. Returns a tuple of (average, average_energy, notice) where notice is an informational message if averaging was implicitly enabled.


options_from_args

options_from_args(args: argparse.Namespace) -> ProcessOptions

Convert a CLI argparse.Namespace into a ProcessOptions instance. This is the single boundary where argparse values are translated into the typed ProcessOptions dataclass; the Namespace itself is never threaded further into the API or processing layers.


Data Types

ProcessOptions

A frozen dataclass that captures the full runtime configuration. Create one with keyword arguments; all fields have sensible defaults.

from batteryproc.batteryproc_types import ProcessOptions

# Minimal — all defaults
opts = ProcessOptions()

# Customized
opts = ProcessOptions(
    outdir=Path("results"),
    energy=True,
    derivative_cycles=(1, 10, 50),
    dqdv_enabled=True,
    svg=True,
    dpi=600,
    csv_export=True,
    average=True,
    mass_g=0.523,
)

Key fields:

Field Type Default Description
outdir Path \| None None Output directory. None means a Results folder next to the input.
svg bool False Save SVG plots in addition to PNG.
dpi int 300 PNG resolution in dots per inch.
energy bool False Generate specific energy (Wh/kg) plots.
derivative_cycles tuple[int, ...] \| None None Specific cycle numbers for dQ/dV plots. Requires dqdv_enabled=True.
dqdv_enabled bool False Enable dQ/dV analysis and plotting. If True, plots are generated for cycles in derivative_cycles. If derivative_cycles is None or empty, the last available cycle is plotted.
average bool False Average capacity metrics across replicate cells.
average_energy bool False Average energy metrics across replicate cells.
average_ignore_plan bool False Average by filename only, ignoring step plan compatibility.
force_process bool False Process files even if data appears incomplete.
prefer_file_metrics bool True Use file-reported metrics if within tolerance.
recompute_all bool False Force recalculation of all metrics from raw data.
heuristic_map bool True Enable fuzzy column name matching.
metric_tolerance float \| None None Max relative difference for metric validation.
metric_tolerance_abs float \| None None Absolute tolerance for metric validation.
mass_g float \| None None Active material mass (grams) for capacity normalization.
cell_weight_g float \| None None Total cell weight (grams) for energy normalization.
csv_export bool False Export plot data as CSV files alongside plots.
csv_only bool False Export CSV files only, skip plot generation. Mutually exclusive with csv_export.
validate_cycles bool False Print cycle validation diagnostics.
debug bool False Enable verbose debug logging.
quiet bool False Suppress non-critical warnings.
prompt_for_mass bool False Permit interactive mass prompting via input(). The CLI opts back in; library callers stay non-blocking.
write_artifacts bool True Produce output files (plots, CSV). Set False for pure data processing with no filesystem side effects.
capture_output bool False Explicit opt-in for the convenience stdout/stderr capture into FileResult fields. Disabled by default; structured diagnostics are the source of truth for outcomes.
original_inputs tuple[str, ...] \| None None Raw input paths supplied on the command line before file discovery, used by the averaging workflows to tell explicit multi-file runs apart from directory expansion. None for programmatic callers, which fall back to the discovered file paths.

Mutual exclusivity

csv_export and csv_only cannot both be True. Setting both raises ValueError at construction time.

Precedence

prefer_file_metrics and recompute_all express opposite preferences for using file-reported metrics versus recomputing them. If both are set to True, recompute_all=True takes precedence and forces recalculation regardless of file-reported values.

Removed: raw_args (deprecated since 3.5.0)

Earlier releases carried a deprecated raw_args field that smuggled the raw argparse.Namespace below the CLI boundary. It has been removed. Configuration now travels exclusively as ProcessOptions (and the focused ParseOptions/AnalysisOptions/ArtifactOptions) dataclasses — no argparse.Namespace is constructed or passed through the API. Code that previously read options.raw_args should use the typed ProcessOptions fields directly; the original command-line paths the averaging workflows needed are now available via original_inputs. Passing raw_args=... to ProcessOptions(...) raises TypeError.


FileResult

Returned by process_file and included in ProcessResult.files.

Field Type Description
path Path Input file that was processed.
ok bool True if processing succeeded.
status "success" | "skipped" | "failure" Normalized status code.
error_category FileErrorCategory \| None Structured failure classification (see below).
cell CellData \| None Processed cell data when averaging is enabled.
errors list[str] Human-readable error messages.
cycle_metadata dict \| None Cycle-detection diagnostics when requested.
stdout list[str] Captured stdout lines (when capture_output=True).
stderr list[str] Captured stderr lines (when capture_output=True).
processed ProcessedCell \| None Complete analytical result for the file when analysis ran. May be populated even for failures/skips (carrying partial data and diagnostics). Prefer this over cell for new consumers.
artifacts list[ArtifactRecord] Files written (plots, CSVs) while processing this input.
diagnostics list[Diagnostic] Structured diagnostics describing the outcome.

ProcessResult

Returned by process_files.

Field Type Description
files list[FileResult] Per-file outcomes in processing order.
success_count int Number of files that completed successfully.
failure_count int Number of files that failed.
skipped_count int Number of files that were skipped.
errors list[str] High-level error messages from the batch run.

Methods:

  • error_categories() → tuple[FileErrorCategory, ...] — Returns the ordered error categories observed across all files.

FileErrorCategory

An enum classifying how a file failed:

Value Meaning
PARSE The file could not be read or parsed.
DATA_QUALITY The file was read but contained insufficient or invalid data (e.g., "bad cell").
WRONG_DATA_TYPE The file is valid but does not contain battery cycling data.
PERMISSION The file could not be accessed due to OS permissions.
UNEXPECTED An unexpected error occurred during processing.

Error Handling

The API raises domain exceptions from batteryproc.errors that are caught internally by process_file and process_files and surfaced as structured FileResult objects. You typically do not need to catch these yourself unless you call lower-level functions directly.

Exception When raised Maps to
ParserError File cannot be read or parsed FileErrorCategory.PARSE
BadCellError Data quality check fails FileErrorCategory.DATA_QUALITY
WrongDataTypeError File is not battery cycling data FileErrorCategory.WRONG_DATA_TYPE

All three inherit from BatteryAnalysisError.

See the Exception Handling Deep Dive for details on exit codes and multi-file error logic.


Extension Points

PipelineHooks and the hooks parameter

PipelineHooks is the public mechanism for supplying late-bound collaborators to the processing services. The functions analyze_cell, first_cycle_only_result, write_artifacts, and process_file_pipeline each accept an optional keyword-only hooks: PipelineHooks | None = None parameter. When omitted, default_hooks() resolves the real BatteryProc implementations, so ordinary callers never need to supply one.

A PipelineHooks instance bundles the modules and callables the services delegate to instead of importing them directly:

Attribute Type Role
metrics module Capacity/energy/dQ-dV summaries, mass validation, bad-cell check, first-cycle profile.
plots module Plot generation for the artifact stage.
csv_export module CSV artifact export.
bad_cell_check Callable[..., None] Data-quality safety check.
reconcile_metric_sources Callable[..., Any] Metric reconciliation across file-reported and recomputed values.
build_metric_comparison_config Callable[..., Any] Comparison-tolerance configuration.
logger logging.Logger Logger used for pipeline diagnostics.

Supplying a custom PipelineHooks lets callers substitute alternative implementations — for example to redirect computation or inject a custom logger — through the function signature rather than by mutating module globals:

from batteryproc.processing import default_hooks, process_file_pipeline

hooks = default_hooks()  # start from the real implementations
# ... customize attributes on `hooks` as needed ...
outcome = process_file_pipeline("cell_data.xlsx", hooks=hooks)

Auto-Generated Module Documentation

The sections below use mkdocstrings to render docstrings directly from the source code. They provide additional detail on internal functions and signatures.

batteryproc.api

Programmatic processing interface for BatteryProc.

This module exposes a public API that mirrors the CLI's core processing behaviour without relying on argparse.Namespace instances or invoking sys.exit. Callers supply :class:~batteryproc.batteryproc_types.ProcessOptions objects that capture the normalized runtime configuration.

normalize_averaging_flags(average, average_energy, average_ignore_plan)

Normalize averaging flags so ignore-plan alone still activates averaging.

Parameters

average : bool Capacity averaging flag supplied by the caller. average_energy : bool Energy averaging flag supplied by the caller. average_ignore_plan : bool Ignore-plan compatibility flag supplied by the caller.

Returns

tuple A tuple of (average, average_energy, notice) where average and average_energy are the normalized flags and notice is an informational message when averaging was implicitly enabled.

Source code in batteryproc/api.py
def normalize_averaging_flags(
    average: bool,
    average_energy: bool,
    average_ignore_plan: bool,
) -> tuple[bool, bool, str | None]:
    """Normalize averaging flags so ignore-plan alone still activates averaging.

    Parameters
    ----------
    average : bool
        Capacity averaging flag supplied by the caller.
    average_energy : bool
        Energy averaging flag supplied by the caller.
    average_ignore_plan : bool
        Ignore-plan compatibility flag supplied by the caller.

    Returns
    -------
    tuple
        A tuple of ``(average, average_energy, notice)`` where ``average`` and
        ``average_energy`` are the normalized flags and ``notice`` is an
        informational message when averaging was implicitly enabled.
    """

    notice: str | None = None
    if average_ignore_plan and not (average or average_energy):
        average = True
        notice = (
            "INFO: --average-ignore-plan was provided without --average/--average-energy. "
            "Capacity averaging will run while ignoring plan compatibility."
        )
    return average, average_energy, notice

options_from_args(args)

Translate CLI :class:argparse.Namespace into :class:ProcessOptions.

The translator normalises CLI-specific attributes into a programmatic configuration object. It also disables output capture so that the CLI can continue streaming progress messages directly to stdout/stderr.

Source code in batteryproc/api.py
def options_from_args(args: argparse.Namespace) -> ProcessOptions:
    """Translate CLI :class:`argparse.Namespace` into :class:`ProcessOptions`.

    The translator normalises CLI-specific attributes into a programmatic
    configuration object. It also disables output capture so that the CLI can
    continue streaming progress messages directly to stdout/stderr.
    """

    outdir_value = getattr(args, "outdir", None)
    outdir_path = Path(outdir_value) if outdir_value else None

    derivative_arg = getattr(args, "derivative", None)
    if derivative_arg is None:
        derivative_cycles: tuple[int, ...] | None = None
        dqdv_enabled = False
    elif len(derivative_arg) == 0:
        derivative_cycles = None
        dqdv_enabled = True
    else:
        derivative_cycles = tuple(int(value) for value in derivative_arg)
        dqdv_enabled = True

    metrics_defaults = getattr(args, "metrics_defaults", None)
    if metrics_defaults is None:
        metrics_defaults = MetricsConfig()

    cycle_config = getattr(args, "cycle_detection_config", None)

    average_flag = bool(getattr(args, "average", False))
    average_energy_flag = bool(getattr(args, "average_energy", False))
    average_ignore_plan_flag = bool(getattr(args, "average_ignore_plan", False))

    # Normalize averaging flags without mutating the namespace. The CLI normalizes
    # and emits any notice before this translation runs, so re-normalizing here is
    # idempotent; the notice itself is recomputed downstream and surfaced via the
    # return value rather than carried on the namespace.
    normalized_average, normalized_average_energy, _ = normalize_averaging_flags(
        average_flag,
        average_energy_flag,
        average_ignore_plan_flag,
    )

    raw_inputs = getattr(args, "inputs", None) or []
    original_inputs = tuple(str(value) for value in raw_inputs)

    return ProcessOptions(
        outdir=outdir_path,
        svg=bool(getattr(args, "svg", False)),
        dpi=int(getattr(args, "dpi", 300)),
        energy=bool(getattr(args, "energy", False)),
        derivative_cycles=derivative_cycles,
        dqdv_enabled=dqdv_enabled,
        average=normalized_average,
        average_energy=normalized_average_energy,
        average_ignore_plan=average_ignore_plan_flag,
        force_process=bool(getattr(args, "force_process", False)),
        prefer_file_metrics=bool(getattr(args, "prefer_file_metrics", True)),
        recompute_all=bool(getattr(args, "recompute_all", False)),
        heuristic_map=bool(getattr(args, "heuristic_map", True)),
        metric_tolerance=getattr(args, "metric_tolerance", None),
        metric_tolerance_abs=getattr(args, "metric_tolerance_abs", None),
        mass_g=getattr(args, "mass_g", None),
        cell_weight_g=getattr(args, "cell_weight_g", None),
        cycle_config=cycle_config,
        validate_cycles=bool(getattr(args, "validate_cycles", False)),
        debug=bool(getattr(args, "debug", False)),
        debug_step_plan=bool(getattr(args, "debug_step_plan", False)),
        debug_signatures=bool(getattr(args, "debug_signatures", False)),
        metrics_defaults=metrics_defaults,
        mappings_config=getattr(args, "mappings_config", None),
        csv_export=bool(getattr(args, "csv", False)),
        csv_only=bool(getattr(args, "csv_only", False)),
        capture_output=False,
        original_inputs=original_inputs,
        stream_errors=True,
        quiet=bool(getattr(args, "quiet", False)),
        prompt_for_mass=bool(getattr(args, "prompt_for_mass", False)),
        write_artifacts=bool(getattr(args, "write_artifacts", True)),
    )

process_file(input, options=None)

Process a single file according to options.

This is the primary data-oriented entry point: it composes :func:batteryproc.parse_file, :func:batteryproc.analyze_cell, and (optionally) :func:batteryproc.write_artifacts — the same analysis core the CLI runs — and returns a :class:FileResult whose processed attribute carries the complete :class:ProcessedCell.

With default options no interactive prompt is ever issued (prompt_for_mass=False); pass ProcessOptions(write_artifacts=False) to also suppress every file and plot side effect.

Parameters

input : Path File path to process. options : ProcessOptions, optional Normalized runtime configuration. Defaults to ProcessOptions().

Returns

FileResult Structured outcome describing success, skip, or failure state, including processed, artifacts, and diagnostics.

Source code in batteryproc/api.py
def process_file(input: Path, options: ProcessOptions | None = None) -> FileResult:
    """Process a single file according to ``options``.

    This is the primary data-oriented entry point: it composes
    :func:`batteryproc.parse_file`, :func:`batteryproc.analyze_cell`, and
    (optionally) :func:`batteryproc.write_artifacts` — the same analysis core
    the CLI runs — and returns a :class:`FileResult` whose ``processed``
    attribute carries the complete :class:`ProcessedCell`.

    With default options no interactive prompt is ever issued
    (``prompt_for_mass=False``); pass
    ``ProcessOptions(write_artifacts=False)`` to also suppress every file
    and plot side effect.

    Parameters
    ----------
    input : Path
        File path to process.
    options : ProcessOptions, optional
        Normalized runtime configuration. Defaults to ``ProcessOptions()``.

    Returns
    -------
    FileResult
        Structured outcome describing success, skip, or failure state,
        including ``processed``, ``artifacts``, and ``diagnostics``.
    """

    if options is None:
        options = ProcessOptions()
    options, pending_notice = _handle_averaging_normalization(options)

    result = _process_single(Path(input), options)

    if pending_notice is not None and isinstance(result.stdout, list):
        result.stdout.insert(0, pending_notice)

    return result

process_files(inputs, options=None, *, pre_process=None, post_process=None)

Process a collection of input files and aggregate the results.

Source code in batteryproc/api.py
def process_files(
    inputs: Iterable[Path],
    options: ProcessOptions | None = None,
    *,
    pre_process: Callable[[Path], None] | None = None,
    post_process: Callable[[Path, FileResult], None] | None = None,
) -> ProcessResult:
    """Process a collection of input files and aggregate the results."""

    if options is None:
        options = ProcessOptions()
    paths = [Path(p) for p in inputs]
    options, pending_notice = _handle_averaging_normalization(options)

    file_results: list[FileResult] = []
    averaging_cells: list[CellData] = []

    for path in paths:
        if pre_process is not None:
            pre_process(path)
        result = _process_single(path, options)
        file_results.append(result)
        if post_process is not None:
            post_process(path, result)
        if result.cell is not None:
            averaging_cells.append(result.cell)

    success_count = sum(1 for result in file_results if result.status == "success")
    skipped_count = sum(1 for result in file_results if result.status == "skipped")
    failure_count = sum(1 for result in file_results if result.status == "failure")

    aggregate_errors: list[str] = []
    if pending_notice is not None:
        aggregate_errors.append(pending_notice)
    for result in file_results:
        if result.status == "failure":
            aggregate_errors.extend(result.errors)

    if options.average:
        aggregate_errors.extend(_run_averaging(averaging_cells, paths, options))

    if options.average_energy:
        aggregate_errors.extend(_run_energy_averaging(averaging_cells, paths, options))

    flattened_errors: list[str] = []
    for message in aggregate_errors:
        flattened_errors.extend(_split_non_empty(message))

    return ProcessResult(
        files=file_results,
        success_count=success_count,
        failure_count=failure_count,
        skipped_count=skipped_count,
        errors=flattened_errors,
    )

batteryproc.batteryproc_types

batteryproc.batteryproc_types

AnalysisOptions dataclass

Options consumed by :func:batteryproc.analyze_cell.

Attributes

mass_g : float or None Explicit active-material mass override in grams (highest precedence). cell_weight_g : float or None Explicit whole-cell weight override in grams. cycle_config : CycleDetectionConfig or None Cycle-detection parameters threaded explicitly into the metric calls. When None the metrics layer applies a default :class:CycleDetectionConfig. metrics_defaults : MetricsConfig Configuration-file defaults for mass and tolerances. compute_energy : bool Compute the per-cycle energy summary. When False (default) :attr:ProcessedCell.energy_summary remains None. derivative_cycles : tuple[int, ...] or None Specific cycles for dQ/dV computation. None with dqdv_enabled=True selects the last cycle. dqdv_enabled : bool Compute dQ/dV traces. force_process : bool Accept processing despite BatteryProc safety/validation conditions (bad-cell and too-new checks). This does not affect artifact overwriting, caching, or diagnostics emission. prefer_file_metrics : bool Honour instrument-reported metrics during reconciliation. recompute_all : bool Ignore instrument metrics and use only recomputed values. metric_tolerance : float or None Relative tolerance for metric reconciliation. metric_tolerance_abs : float or None Absolute tolerance for metric reconciliation. prompt_for_mass : bool Permit interactive mass prompting. Defaults to False so that library processing never blocks on input(). check_data_completeness : bool Run the too-new and first-cycle-incomplete short-circuit checks. The CLI disables this because it performs those checks itself before invoking the analysis core. quiet : bool Suppress non-critical reconciliation warnings on stderr. debug : bool Emit metric-comparison debug output.

Source code in batteryproc/batteryproc_types.py
@dataclass(frozen=True)
class AnalysisOptions:
    """Options consumed by :func:`batteryproc.analyze_cell`.

    Attributes
    ----------
    mass_g : float or None
        Explicit active-material mass override in grams (highest precedence).
    cell_weight_g : float or None
        Explicit whole-cell weight override in grams.
    cycle_config : CycleDetectionConfig or None
        Cycle-detection parameters threaded explicitly into the metric calls.
        When ``None`` the metrics layer applies a default
        :class:`CycleDetectionConfig`.
    metrics_defaults : MetricsConfig
        Configuration-file defaults for mass and tolerances.
    compute_energy : bool
        Compute the per-cycle energy summary. When ``False`` (default)
        :attr:`ProcessedCell.energy_summary` remains ``None``.
    derivative_cycles : tuple[int, ...] or None
        Specific cycles for dQ/dV computation. ``None`` with
        ``dqdv_enabled=True`` selects the last cycle.
    dqdv_enabled : bool
        Compute dQ/dV traces.
    force_process : bool
        Accept processing despite BatteryProc safety/validation conditions
        (bad-cell and too-new checks). This does not affect artifact
        overwriting, caching, or diagnostics emission.
    prefer_file_metrics : bool
        Honour instrument-reported metrics during reconciliation.
    recompute_all : bool
        Ignore instrument metrics and use only recomputed values.
    metric_tolerance : float or None
        Relative tolerance for metric reconciliation.
    metric_tolerance_abs : float or None
        Absolute tolerance for metric reconciliation.
    prompt_for_mass : bool
        Permit interactive mass prompting. Defaults to ``False`` so that
        library processing never blocks on ``input()``.
    check_data_completeness : bool
        Run the too-new and first-cycle-incomplete short-circuit checks.
        The CLI disables this because it performs those checks itself before
        invoking the analysis core.
    quiet : bool
        Suppress non-critical reconciliation warnings on stderr.
    debug : bool
        Emit metric-comparison debug output.
    """

    mass_g: float | None = None
    cell_weight_g: float | None = None
    cycle_config: "CycleDetectionConfig | None" = None
    metrics_defaults: "MetricsConfig" = field(default_factory=lambda: MetricsConfig())
    compute_energy: bool = False
    derivative_cycles: tuple[int, ...] | None = None
    dqdv_enabled: bool = False
    force_process: bool = False
    prefer_file_metrics: bool = True
    recompute_all: bool = False
    metric_tolerance: float | None = None
    metric_tolerance_abs: float | None = None
    prompt_for_mass: bool = False
    check_data_completeness: bool = True
    quiet: bool = False
    debug: bool = False

ArtifactOptions dataclass

Options consumed by :func:batteryproc.write_artifacts.

Attributes

output_dir : Path Directory artifacts are written into (created if missing). file_stem : str or None Base name for output files. Derived from the source path when None. plot_title : str or None Title prefix for plots. Derived from the source path when None. svg : bool Also save plots as SVG alongside PNG. dpi : int PNG rendering resolution. csv_export : bool Export plot data as CSV files alongside plots. csv_only : bool Export CSV data only and skip plot generation. Mutually exclusive with csv_export. energy_plots : bool Generate the energy-vs-cycle plot when an energy summary is present.

Source code in batteryproc/batteryproc_types.py
@dataclass(frozen=True)
class ArtifactOptions:
    """Options consumed by :func:`batteryproc.write_artifacts`.

    Attributes
    ----------
    output_dir : Path
        Directory artifacts are written into (created if missing).
    file_stem : str or None
        Base name for output files. Derived from the source path when
        ``None``.
    plot_title : str or None
        Title prefix for plots. Derived from the source path when ``None``.
    svg : bool
        Also save plots as SVG alongside PNG.
    dpi : int
        PNG rendering resolution.
    csv_export : bool
        Export plot data as CSV files alongside plots.
    csv_only : bool
        Export CSV data only and skip plot generation. Mutually exclusive
        with ``csv_export``.
    energy_plots : bool
        Generate the energy-vs-cycle plot when an energy summary is present.
    """

    output_dir: Path
    file_stem: str | None = None
    plot_title: str | None = None
    svg: bool = False
    dpi: int = 300
    csv_export: bool = False
    csv_only: bool = False
    energy_plots: bool = False

    def __post_init__(self) -> None:
        """Validate option combinations that must remain mutually exclusive."""
        if self.csv_export and self.csv_only:
            raise ValueError(
                "ArtifactOptions.csv_export and ArtifactOptions.csv_only are mutually exclusive."
            )

__post_init__()

Validate option combinations that must remain mutually exclusive.

Source code in batteryproc/batteryproc_types.py
def __post_init__(self) -> None:
    """Validate option combinations that must remain mutually exclusive."""
    if self.csv_export and self.csv_only:
        raise ValueError(
            "ArtifactOptions.csv_export and ArtifactOptions.csv_only are mutually exclusive."
        )

ArtifactRecord dataclass

Description of one file written by :func:batteryproc.write_artifacts.

Attributes

artifact_type : str Logical artifact identifier (e.g. "capacity_vs_cycle"). path : Path Location of the written file. media_type : str or None IANA media type inferred from the file suffix, when known. schema_version : str or None Schema version for data artifacts, when applicable. created : datetime UTC timestamp recorded when the artifact was registered.

Source code in batteryproc/batteryproc_types.py
@dataclass(frozen=True)
class ArtifactRecord:
    """Description of one file written by :func:`batteryproc.write_artifacts`.

    Attributes
    ----------
    artifact_type : str
        Logical artifact identifier (e.g. ``"capacity_vs_cycle"``).
    path : Path
        Location of the written file.
    media_type : str or None
        IANA media type inferred from the file suffix, when known.
    schema_version : str or None
        Schema version for data artifacts, when applicable.
    created : datetime
        UTC timestamp recorded when the artifact was registered.
    """

    artifact_type: str
    path: Path
    media_type: str | None = None
    schema_version: str | None = None
    created: datetime = field(default_factory=lambda: datetime.now(timezone.utc))

CellData dataclass

Represents processed data and metadata for a single battery cell file.

This dataclass is a structured container for information extracted or derived from a battery data file. It passes data between different stages of the batteryproc pipeline, such as for averaging.

Attributes

file_path : Path The absolute path to the original data file. cleaned_stem : str The cleaned filename stem, used for naming outputs. step_plan : str | None A string representation of the cell's step plan for debugging. Defaults to None. step_signature : str | None A unique signature (e.g., SHA-1 hash) of the step plan, used for grouping cells with identical testing procedures. Defaults to None. capacity_summary : pd.DataFrame | None A DataFrame containing the per-cycle capacity summary (e.g., charge/discharge capacity, CE). Defaults to None. energy_summary : pd.DataFrame | None A DataFrame summarizing energy metrics (e.g., specific energy, energy efficiency). Defaults to None.

Source code in batteryproc/batteryproc_types.py
@dataclass
class CellData:
    """Represents processed data and metadata for a single battery cell file.

    This dataclass is a structured container for information extracted or
    derived from a battery data file. It passes data between different stages
    of the `batteryproc` pipeline, such as for averaging.

    Attributes
    ----------
    file_path : Path
        The absolute path to the original data file.
    cleaned_stem : str
        The cleaned filename stem, used for naming outputs.
    step_plan : str | None
        A string representation of the cell's step plan for debugging.
        Defaults to ``None``.
    step_signature : str | None
        A unique signature (e.g., SHA-1 hash) of the step plan, used for
        grouping cells with identical testing procedures. Defaults to ``None``.
    capacity_summary : pd.DataFrame | None
        A DataFrame containing the per-cycle capacity summary (e.g.,
        charge/discharge capacity, CE). Defaults to ``None``.
    energy_summary : pd.DataFrame | None
        A DataFrame summarizing energy metrics (e.g., specific energy,
        energy efficiency). Defaults to ``None``.

    """

    file_path: Path
    cleaned_stem: str
    step_plan: str | None = None
    step_signature: str | None = None
    capacity_summary: Any | None = None
    energy_summary: Any | None = None

    def __post_init__(self) -> None:
        """Standardize empty DataFrames to None after initialization.

        Ensures that if `capacity_summary` or `energy_summary` are empty pandas
        DataFrames, they are set to None. This standardizes the representation
        of "no data" for these fields.
        """
        if isinstance(self.capacity_summary, pd.DataFrame) and self.capacity_summary.empty:
            self.capacity_summary = None
        if isinstance(self.energy_summary, pd.DataFrame) and self.energy_summary.empty:
            self.energy_summary = None

__post_init__()

Standardize empty DataFrames to None after initialization.

Ensures that if capacity_summary or energy_summary are empty pandas DataFrames, they are set to None. This standardizes the representation of "no data" for these fields.

Source code in batteryproc/batteryproc_types.py
def __post_init__(self) -> None:
    """Standardize empty DataFrames to None after initialization.

    Ensures that if `capacity_summary` or `energy_summary` are empty pandas
    DataFrames, they are set to None. This standardizes the representation
    of "no data" for these fields.
    """
    if isinstance(self.capacity_summary, pd.DataFrame) and self.capacity_summary.empty:
        self.capacity_summary = None
    if isinstance(self.energy_summary, pd.DataFrame) and self.energy_summary.empty:
        self.energy_summary = None

CompareResult dataclass

Container for detailed and aggregate metric comparison outputs.

Parameters

per_metric : Mapping of metric names to their per-cycle comparison tables. summaries : Mapping of metric names to aggregate statistics. missing_cycles_in_file : Sorted collection of cycle identifiers missing from the file-reported frame. missing_cycles_in_recomputed : Sorted collection of cycle identifiers missing from the recomputed frame.

Source code in batteryproc/batteryproc_types.py
@dataclass
class CompareResult:
    """Container for detailed and aggregate metric comparison outputs.

    Parameters
    ----------
    per_metric :
        Mapping of metric names to their per-cycle comparison tables.
    summaries :
        Mapping of metric names to aggregate statistics.
    missing_cycles_in_file :
        Sorted collection of cycle identifiers missing from the file-reported frame.
    missing_cycles_in_recomputed :
        Sorted collection of cycle identifiers missing from the recomputed frame.
    """

    per_metric: dict[str, pd.DataFrame] = field(default_factory=dict)
    summaries: dict[str, CompareSummary] = field(default_factory=dict)
    missing_cycles_in_file: list[float] = field(default_factory=list)
    missing_cycles_in_recomputed: list[float] = field(default_factory=list)

CompareSummary dataclass

Aggregate comparison statistics for a metric collection.

Parameters

metric : The metric column name summarised by this record. compared_count : Number of rows successfully compared (after null policy filtering). flagged_count : Number of rows that fell outside tolerance thresholds. missing_in_file : Count of cycles present in the recomputed frame but absent from the file frame. missing_in_recomputed : Count of cycles present in the file frame but absent from the recomputed frame. intersection_count : Number of cycles present in both frames prior to null filtering.

Source code in batteryproc/batteryproc_types.py
@dataclass(frozen=True)
class CompareSummary:
    """Aggregate comparison statistics for a metric collection.

    Parameters
    ----------
    metric :
        The metric column name summarised by this record.
    compared_count :
        Number of rows successfully compared (after null policy filtering).
    flagged_count :
        Number of rows that fell outside tolerance thresholds.
    missing_in_file :
        Count of cycles present in the recomputed frame but absent from the file frame.
    missing_in_recomputed :
        Count of cycles present in the file frame but absent from the recomputed frame.
    intersection_count :
        Number of cycles present in both frames prior to null filtering.
    """

    metric: str
    compared_count: int
    flagged_count: int
    missing_in_file: int
    missing_in_recomputed: int
    intersection_count: int

ComparisonConfig dataclass

Configuration controlling metric reconciliation behaviour.

Parameters

metrics : Ordered collection of metric column names to compare. tolerances : Mapping of metric names to their tolerance definitions. Metrics not present in this mapping will fall back to default_tolerance. default_tolerance : Baseline tolerance applied to metrics not explicitly listed in tolerances. cycle_column : Name of the column used to align per-cycle rows. Defaults to "cycle_index". null_policy : Strategy applied when null values appear in the compared columns.

Source code in batteryproc/batteryproc_types.py
@dataclass(frozen=True)
class ComparisonConfig:
    """Configuration controlling metric reconciliation behaviour.

    Parameters
    ----------
    metrics :
        Ordered collection of metric column names to compare.
    tolerances :
        Mapping of metric names to their tolerance definitions. Metrics not present
        in this mapping will fall back to ``default_tolerance``.
    default_tolerance :
        Baseline tolerance applied to metrics not explicitly listed in ``tolerances``.
    cycle_column :
        Name of the column used to align per-cycle rows. Defaults to ``"cycle_index"``.
    null_policy :
        Strategy applied when null values appear in the compared columns.
    """

    metrics: tuple[str, ...]
    tolerances: dict[str, MetricTolerance] = field(default_factory=dict)
    default_tolerance: MetricTolerance | None = None
    cycle_column: str = "cycle_index"
    null_policy: ComparisonNullPolicy = ComparisonNullPolicy.SKIP_ROW

ComparisonNullPolicy

Bases: str, Enum

Treatment of null values encountered during metric comparisons.

Source code in batteryproc/batteryproc_types.py
class ComparisonNullPolicy(str, Enum):
    """Treatment of null values encountered during metric comparisons."""

    SKIP_ROW = "skip_row"
    """Ignore rows containing nulls in either input and exclude them from counts."""

    FAIL_ON_ANY_NULL = "fail_on_any_null"
    """Treat any null as an automatic out-of-tolerance condition."""

FAIL_ON_ANY_NULL = 'fail_on_any_null' class-attribute instance-attribute

Treat any null as an automatic out-of-tolerance condition.

SKIP_ROW = 'skip_row' class-attribute instance-attribute

Ignore rows containing nulls in either input and exclude them from counts.

CycleAnomalyCode

Bases: str, Enum

Structured anomaly codes emitted by cycle validation.

Source code in batteryproc/batteryproc_types.py
class CycleAnomalyCode(str, Enum):
    """Structured anomaly codes emitted by cycle validation."""

    NON_MONOTONIC_INDEX = "non_monotonic_index"
    INDEX_GAP = "index_gap"
    MISSING_INDEX = "missing_index"
    SHORT_CYCLE = "short_cycle"
    INCOMPLETE_CYCLE = "incomplete_cycle"
    TIME_REVERSAL = "time_reversal"
    CAPACITY_MISALIGNMENT = "capacity_misalignment"
    REST_MISALIGNMENT = "rest_misalignment"
    ZERO_DURATION = "zero_duration"

CycleDetectionConfig dataclass

Runtime configuration applied to the cycle detection pipeline.

Parameters

method : CycleDetectionMethod, optional Strategy used for detecting cycles. Defaults to CycleDetectionMethod.AUTO which selects the best available method based on input data and heuristics. current_threshold : float, optional Current magnitude (in Amperes) used as the baseline threshold for distinguishing active (charge/discharge) vs rest periods. Defaults to 0.01 A. When :attr:auto_current_threshold is enabled this value acts as a fallback for degenerate traces and an upper bound when the auto-tuner cannot derive a robust threshold. validate_cycles : bool, optional When True, run post-detection validation checks (e.g., short or incomplete cycles). Defaults to False. Validation results may be written to diagnostics files depending on the runtime configuration. auto_current_threshold : bool, optional Controls whether detection routines automatically derive a dataset-specific activation threshold from the absolute current trace. Defaults to True. Disable to honour manual current_threshold overrides exactly. auto_current_threshold_percentile : float, optional Percentile of the absolute current distribution used by the auto-tuner (default 90.0). Values must reside within (0, 100]. auto_current_threshold_scale : float, optional Multiplicative scale applied to the selected percentile when computing the adaptive threshold. Defaults to 0.05. min_auto_current_threshold : float, optional Lower bound (Amperes) enforced on the adaptive threshold. Defaults to 5e-5 to keep sub-milliamp signals classified as active when possible. validator_kwargs : dict[str, Any], optional Optional overrides passed to the cycle validation routine. Common keys include min_cycle_duration_seconds, min_cycle_length_samples, and rest_current_threshold. Defaults to an empty dict. current_sign_kwargs : dict[str, Any], optional Optional overrides for current-sign based detection heuristics. Typical keys include median_window, charge_threshold, discharge_threshold, and rest_threshold. Defaults to an empty dict.

Source code in batteryproc/batteryproc_types.py
@dataclass
class CycleDetectionConfig:
    """Runtime configuration applied to the cycle detection pipeline.

    Parameters
    ----------
    method : CycleDetectionMethod, optional
        Strategy used for detecting cycles. Defaults to
        ``CycleDetectionMethod.AUTO`` which selects the best available
        method based on input data and heuristics.
    current_threshold : float, optional
        Current magnitude (in Amperes) used as the baseline threshold for
        distinguishing active (charge/discharge) vs rest periods. Defaults to
        0.01 A. When :attr:`auto_current_threshold` is enabled this value acts
        as a fallback for degenerate traces and an upper bound when the
        auto-tuner cannot derive a robust threshold.
    validate_cycles : bool, optional
        When True, run post-detection validation checks (e.g., short or
        incomplete cycles). Defaults to False. Validation results may be
        written to diagnostics files depending on the runtime configuration.
    auto_current_threshold : bool, optional
        Controls whether detection routines automatically derive a
        dataset-specific activation threshold from the absolute current trace.
        Defaults to ``True``. Disable to honour manual ``current_threshold``
        overrides exactly.
    auto_current_threshold_percentile : float, optional
        Percentile of the absolute current distribution used by the auto-tuner
        (default 90.0). Values must reside within ``(0, 100]``.
    auto_current_threshold_scale : float, optional
        Multiplicative scale applied to the selected percentile when computing
        the adaptive threshold. Defaults to ``0.05``.
    min_auto_current_threshold : float, optional
        Lower bound (Amperes) enforced on the adaptive threshold. Defaults to
        ``5e-5`` to keep sub-milliamp signals classified as active when
        possible.
    validator_kwargs : dict[str, Any], optional
        Optional overrides passed to the cycle validation routine. Common
        keys include ``min_cycle_duration_seconds``, ``min_cycle_length_samples``,
        and ``rest_current_threshold``. Defaults to an empty dict.
    current_sign_kwargs : dict[str, Any], optional
        Optional overrides for current-sign based detection heuristics. Typical
        keys include ``median_window``, ``charge_threshold``, ``discharge_threshold``,
        and ``rest_threshold``. Defaults to an empty dict.
    """

    method: CycleDetectionMethod = CycleDetectionMethod.AUTO
    current_threshold: float = 0.01
    validate_cycles: bool = False
    auto_current_threshold: bool = True
    auto_current_threshold_percentile: float = 90.0
    auto_current_threshold_scale: float = 0.05
    min_auto_current_threshold: float = 5e-5
    validator_kwargs: dict[str, Any] = field(default_factory=dict)
    current_sign_kwargs: dict[str, Any] = field(default_factory=dict)

CycleDetectionMethod

Bases: str, Enum

Well-known strategies used by the cycle detection pipeline.

Source code in batteryproc/batteryproc_types.py
class CycleDetectionMethod(str, Enum):
    """Well-known strategies used by the cycle detection pipeline."""

    AUTO = "auto"
    STEP_TYPE = "step_type"
    CURRENT_SIGN = "current_sign"
    CAPACITY = "capacity"
    STATE_MACHINE = "state_machine"
    LEGACY = "legacy"

CyclePhaseLabel

Bases: str, Enum

Canonical per-row phase labels produced by cycle helpers.

Source code in batteryproc/batteryproc_types.py
class CyclePhaseLabel(str, Enum):
    """Canonical per-row phase labels produced by cycle helpers."""

    CHARGE = "charge"
    DISCHARGE = "discharge"
    REST = "rest"
    UNKNOWN = "unknown"

Diagnostic dataclass

Structured description of a processing condition or failure.

Attributes

code : str Stable machine-readable identifier; see :class:DiagnosticCode for the well-known values. severity : DiagnosticSeverity How serious the condition is. message : str Human-readable explanation. Descriptive only; not a stable contract. stage : ProcessingStage Pipeline stage that raised the diagnostic. source_path : Path or None Source file the diagnostic refers to, when known. context : dict[str, Any] Small structured mapping with condition-specific details (e.g. {"forced": True} when a safety check was overridden). The dataclass is frozen (fields cannot be reassigned) but context itself is a live dict; treat it as read-only.

Source code in batteryproc/batteryproc_types.py
@dataclass(frozen=True)
class Diagnostic:
    """Structured description of a processing condition or failure.

    Attributes
    ----------
    code : str
        Stable machine-readable identifier; see :class:`DiagnosticCode` for
        the well-known values.
    severity : DiagnosticSeverity
        How serious the condition is.
    message : str
        Human-readable explanation. Descriptive only; not a stable contract.
    stage : ProcessingStage
        Pipeline stage that raised the diagnostic.
    source_path : Path or None
        Source file the diagnostic refers to, when known.
    context : dict[str, Any]
        Small structured mapping with condition-specific details (e.g.
        ``{"forced": True}`` when a safety check was overridden). The
        dataclass is frozen (fields cannot be reassigned) but ``context``
        itself is a live dict; treat it as read-only.
    """

    code: str
    severity: DiagnosticSeverity
    message: str
    stage: ProcessingStage
    source_path: Path | None = None
    context: dict[str, Any] = field(default_factory=dict)

DiagnosticCode

Bases: str, Enum

Stable machine-readable diagnostic codes emitted by the pipeline.

Downstream consumers should classify outcomes by these codes rather than parsing human-readable messages. Messages are descriptive and may change; codes are part of the public compatibility contract.

Source code in batteryproc/batteryproc_types.py
class DiagnosticCode(str, Enum):
    """Stable machine-readable diagnostic codes emitted by the pipeline.

    Downstream consumers should classify outcomes by these codes rather than
    parsing human-readable messages. Messages are descriptive and may change;
    codes are part of the public compatibility contract.
    """

    UNSUPPORTED_EXTENSION = "unsupported_extension"
    PARSER_FAILED = "parser_failed"
    MISSING_REQUIRED_CHANNEL = "missing_required_channel"
    MASS_MISSING = "mass_missing"
    MASS_INFERRED = "mass_inferred"
    CYCLE_SUMMARY_UNAVAILABLE = "cycle_summary_unavailable"
    FIRST_CYCLE_INCOMPLETE = "first_cycle_incomplete"
    FILE_TOO_NEW = "file_too_new"
    BAD_CELL = "bad_cell"
    WRONG_DATA_TYPE = "wrong_data_type"
    PERMISSION_DENIED = "permission_denied"
    UNEXPECTED_ERROR = "unexpected_error"
    ARTIFACT_WRITE_FAILED = "artifact_write_failed"

DiagnosticSeverity

Bases: str, Enum

Severity levels for structured processing diagnostics.

Source code in batteryproc/batteryproc_types.py
class DiagnosticSeverity(str, Enum):
    """Severity levels for structured processing diagnostics."""

    INFO = "info"
    WARNING = "warning"
    ERROR = "error"

FileErrorCategory

Bases: str, Enum

Structured categories used to classify per-file processing failures.

Source code in batteryproc/batteryproc_types.py
class FileErrorCategory(str, Enum):
    """Structured categories used to classify per-file processing failures."""

    PARSE = "parse"
    DATA_QUALITY = "data_quality"
    WRONG_DATA_TYPE = "wrong_data_type"
    PERMISSION = "permission"
    UNEXPECTED = "unexpected"

FileResult dataclass

Outcome produced when processing a single file via the public API.

Attributes

path : Path Input file that was processed. ok : bool True when processing completed successfully or yielded data for averaging; False indicates a failure or skip condition. status : {"success", "skipped", "failure"} Normalised status code describing how the file was handled. error_category : FileErrorCategory or None Structured failure classification applied when status is "failure" or "skipped" due to domain conditions. None when the file completed successfully or the failure was not categorised. cell : CellData or None Populated when averaging data was generated for the file. None otherwise. Retained for averaging/comparison compatibility; new consumers should prefer :attr:processed. errors : list[str] Human-readable error messages captured during processing. cycle_metadata : dict[str, Any] or None Cycle-detection metadata captured for diagnostics when requested. stdout : list[str] Captured standard-output messages, populated only when the capture_output opt-in is enabled. Empty by default. stderr : list[str] Captured standard-error messages, populated only when the capture_output opt-in is enabled. Empty by default. Failure classification never depends on these fields. processed : ProcessedCell or None Complete analytical result for the file when analysis ran. May be populated even for failures/skips (carrying partial data and diagnostics). artifacts : list[ArtifactRecord] Files written while processing this input. diagnostics : list[Diagnostic] Structured diagnostics describing the outcome.

Source code in batteryproc/batteryproc_types.py
@dataclass
class FileResult:
    """Outcome produced when processing a single file via the public API.

    Attributes
    ----------
    path : Path
        Input file that was processed.
    ok : bool
        ``True`` when processing completed successfully or yielded data for
        averaging; ``False`` indicates a failure or skip condition.
    status : {"success", "skipped", "failure"}
        Normalised status code describing how the file was handled.
    error_category : FileErrorCategory or None
        Structured failure classification applied when ``status`` is
        ``"failure"`` or ``"skipped"`` due to domain conditions. ``None`` when
        the file completed successfully or the failure was not categorised.
    cell : CellData or None
        Populated when averaging data was generated for the file. ``None``
        otherwise. Retained for averaging/comparison compatibility; new
        consumers should prefer :attr:`processed`.
    errors : list[str]
        Human-readable error messages captured during processing.
    cycle_metadata : dict[str, Any] or None
        Cycle-detection metadata captured for diagnostics when requested.
    stdout : list[str]
        Captured standard-output messages, populated only when the
        ``capture_output`` opt-in is enabled. Empty by default.
    stderr : list[str]
        Captured standard-error messages, populated only when the
        ``capture_output`` opt-in is enabled. Empty by default. Failure
        classification never depends on these fields.
    processed : ProcessedCell or None
        Complete analytical result for the file when analysis ran. May be
        populated even for failures/skips (carrying partial data and
        diagnostics).
    artifacts : list[ArtifactRecord]
        Files written while processing this input.
    diagnostics : list[Diagnostic]
        Structured diagnostics describing the outcome.
    """

    path: Path
    ok: bool
    status: Literal["success", "skipped", "failure"]
    error_category: FileErrorCategory | None = None
    cell: CellData | None = None
    errors: list[str] = field(default_factory=list)
    cycle_metadata: dict[str, Any] | None = None
    stdout: list[str] = field(default_factory=list)
    stderr: list[str] = field(default_factory=list)
    processed: ProcessedCell | None = None
    artifacts: list[ArtifactRecord] = field(default_factory=list)
    diagnostics: list[Diagnostic] = field(default_factory=list)

HeuristicDiagnostics dataclass

Diagnostics for heuristic column mapping decisions.

Captures what was mapped explicitly, what the heuristic mapped (with a simple score), and which columns remained unmatched. This structure is intended for internal use and unit tests.

Parameters

explicit_mapped : dict[str, str] Mapping of original column name to standardized column name applied via explicit rules. heuristic_mapped : dict[str, tuple[str, float]] Mapping of original column name to a tuple of (standardized name, similarity score) applied by heuristics. unmatched : list[str] List of original column names that remained unmapped after both passes.

Source code in batteryproc/batteryproc_types.py
@dataclass
class HeuristicDiagnostics:
    """Diagnostics for heuristic column mapping decisions.

    Captures what was mapped explicitly, what the heuristic mapped (with a
    simple score), and which columns remained unmatched. This structure is
    intended for internal use and unit tests.

    Parameters
    ----------
    explicit_mapped : dict[str, str]
        Mapping of original column name to standardized column name applied
        via explicit rules.
    heuristic_mapped : dict[str, tuple[str, float]]
        Mapping of original column name to a tuple of (standardized name,
        similarity score) applied by heuristics.
    unmatched : list[str]
        List of original column names that remained unmapped after both passes.
    """

    explicit_mapped: dict[str, str] = field(default_factory=dict)
    heuristic_mapped: dict[str, tuple[str, float]] = field(default_factory=dict)
    unmatched: list[str] = field(default_factory=list)

InstrumentMapping dataclass

Mappings for a specific instrument profile.

Parameters

columns : Dict[str, str] Mapping from raw column name or regex pattern to standardized column name. units : Dict[str, UnitConversion] Unit conversion rules keyed by standardized column name.

Source code in batteryproc/batteryproc_types.py
@dataclass
class InstrumentMapping:
    """Mappings for a specific instrument profile.

    Parameters
    ----------
    columns : Dict[str, str]
        Mapping from raw column name or regex pattern to standardized column name.
    units : Dict[str, UnitConversion]
        Unit conversion rules keyed by standardized column name.
    """

    columns: dict[str, str] = field(default_factory=dict)
    units: dict[str, UnitConversion] = field(default_factory=dict)

MappingsConfig dataclass

Top-level configuration for sheet synonyms and instrument mappings.

Parameters

sheets : Dict[str, List[str]] Synonyms for logical sheets (record, cycle, unit, test). instruments : Dict[str, InstrumentMapping] Instrument-specific column and unit mappings.

Source code in batteryproc/batteryproc_types.py
@dataclass
class MappingsConfig:
    """Top-level configuration for sheet synonyms and instrument mappings.

    Parameters
    ----------
    sheets : Dict[str, List[str]]
        Synonyms for logical sheets (record, cycle, unit, test).
    instruments : Dict[str, InstrumentMapping]
        Instrument-specific column and unit mappings.
    """

    sheets: dict[str, list[str]] = field(default_factory=dict)
    instruments: dict[str, InstrumentMapping] = field(default_factory=dict)

MassConfig dataclass

Optional mass overrides supplied via config files.

Source code in batteryproc/batteryproc_types.py
@dataclass(frozen=True)
class MassConfig:
    """Optional mass overrides supplied via config files."""

    mass_g: float | None = None
    cell_weight_g: float | None = None

MassSourcePrecedence

Bases: str, Enum

Ordering of possible mass inputs used during normalization.

Source code in batteryproc/batteryproc_types.py
class MassSourcePrecedence(str, Enum):
    """Ordering of possible mass inputs used during normalization."""

    CLI = "cli"
    CONFIG = "config"
    INFERRED = "infer"
    PROMPT = "prompt"

MetricDiffRow dataclass

Per-cycle reconciliation record for a single metric.

Parameters

cycle : Cycle identifier associated with the comparison row. metric : Metric column name that was compared. file_value : Value extracted from the file-reported metrics DataFrame. recomputed_value : Value computed by the formulas engine. diff : Signed difference file_value - recomputed_value. within_tolerance : Flag indicating whether the pair satisfied the tolerance policy.

Source code in batteryproc/batteryproc_types.py
@dataclass(frozen=True)
class MetricDiffRow:
    """Per-cycle reconciliation record for a single metric.

    Parameters
    ----------
    cycle :
        Cycle identifier associated with the comparison row.
    metric :
        Metric column name that was compared.
    file_value :
        Value extracted from the file-reported metrics DataFrame.
    recomputed_value :
        Value computed by the formulas engine.
    diff :
        Signed difference ``file_value - recomputed_value``.
    within_tolerance :
        Flag indicating whether the pair satisfied the tolerance policy.
    """

    cycle: float
    metric: str
    file_value: float | None
    recomputed_value: float | None
    diff: float | None
    within_tolerance: bool

MetricTolerance dataclass

Absolute and relative tolerance bounds for a single metric.

Parameters

absolute : Absolute difference threshold applied before relative tolerance checks. relative : Relative multiplier applied to max(|file|, |recomputed|) when the absolute check fails and magnitudes are sufficiently large.

Source code in batteryproc/batteryproc_types.py
@dataclass(frozen=True)
class MetricTolerance:
    """Absolute and relative tolerance bounds for a single metric.

    Parameters
    ----------
    absolute :
        Absolute difference threshold applied before relative tolerance checks.
    relative :
        Relative multiplier applied to ``max(|file|, |recomputed|)`` when the absolute
        check fails and magnitudes are sufficiently large.
    """

    absolute: float
    relative: float

MetricsConfig dataclass

Metrics-and-normalization related configuration values.

Source code in batteryproc/batteryproc_types.py
@dataclass(frozen=True)
class MetricsConfig:
    """Metrics-and-normalization related configuration values."""

    mass: MassConfig = field(default_factory=MassConfig)
    tolerance_abs: float | None = None
    tolerance_rel: float | None = None

NewareParseResult dataclass

Container for Neware parser outputs consumed by the CLI.

Attributes

record : pd.DataFrame Standardized record DataFrame. cycle : pd.DataFrame Standardized cycle DataFrame. sheet_mapping : dict[str, str] Mapping of logical sheet names (record, cycle, unit, test) to actual Excel sheet names. step_plan : str | None String representation of the extracted step-plan DataFrame for debug output. step_plan_df : pd.DataFrame | None Raw step-plan DataFrame for richer downstream inspection. step_signature : str | None Step-plan signature for averaging compatibility checks. test_sheet_found : bool True when a logical test sheet was located; used to preserve legacy CLI messaging. test_sheet_name : str | None Actual sheet name that satisfied the logical test lookup (if present). mass_hint : float | None Active material mass hint extracted from the workbook, if available.

Source code in batteryproc/batteryproc_types.py
@dataclass
class NewareParseResult:
    """Container for Neware parser outputs consumed by the CLI.

    Attributes
    ----------
    record : pd.DataFrame
        Standardized record DataFrame.
    cycle : pd.DataFrame
        Standardized cycle DataFrame.
    sheet_mapping : dict[str, str]
        Mapping of logical sheet names (record, cycle, unit, test) to actual Excel sheet names.
    step_plan : str | None
        String representation of the extracted step-plan DataFrame for debug output.
    step_plan_df : pd.DataFrame | None
        Raw step-plan DataFrame for richer downstream inspection.
    step_signature : str | None
        Step-plan signature for averaging compatibility checks.
    test_sheet_found : bool
        ``True`` when a logical ``test`` sheet was located; used to preserve legacy CLI messaging.
    test_sheet_name : str | None
        Actual sheet name that satisfied the logical ``test`` lookup (if present).
    mass_hint : float | None
        Active material mass hint extracted from the workbook, if available.
    """

    record: pd.DataFrame
    cycle: pd.DataFrame
    sheet_mapping: dict[str, str]
    step_plan: str | None
    step_plan_df: pd.DataFrame | None
    step_signature: str | None
    test_sheet_found: bool
    test_sheet_name: str | None
    mass_hint: float | None

ParseOptions dataclass

Options consumed by :func:batteryproc.parse_file.

Attributes

mappings_config : MappingsConfig or None Column-mapping configuration forwarded to parser implementations. heuristic_map : bool Enable heuristic column-name matching for parsers that support it. debug : bool Emit parser debug output. cycle_config : CycleDetectionConfig or None Cycle-detection parameters threaded into parsers that synthesize a cycle index at parse time (e.g. the Neware parser). When None the cycle-detection pipeline applies its default configuration.

Source code in batteryproc/batteryproc_types.py
@dataclass(frozen=True)
class ParseOptions:
    """Options consumed by :func:`batteryproc.parse_file`.

    Attributes
    ----------
    mappings_config : MappingsConfig or None
        Column-mapping configuration forwarded to parser implementations.
    heuristic_map : bool
        Enable heuristic column-name matching for parsers that support it.
    debug : bool
        Emit parser debug output.
    cycle_config : CycleDetectionConfig or None
        Cycle-detection parameters threaded into parsers that synthesize a
        cycle index at parse time (e.g. the Neware parser). When ``None`` the
        cycle-detection pipeline applies its default configuration.
    """

    mappings_config: "MappingsConfig | None" = None
    heuristic_map: bool = True
    debug: bool = False
    cycle_config: "CycleDetectionConfig | None" = None

ParsedCell dataclass

Result of parser dispatch for one source file, before analysis.

Tables are the parser's format-specific standardized output (column names normalised to BatteryProc's record schema); they are not the cross-format canonical representation, which is produced by :func:batteryproc.analyze_cell.

Attributes

source_path : Path or None Path of the parsed file. None only for synthesized inputs. parser_id : str Stable identifier of the parser implementation that produced the data. source_record : pd.DataFrame Standardized time-series (record) table. source_cycle : pd.DataFrame or None Standardized per-cycle summary table when the format provides one, otherwise None. step_plan : str or None String rendering of the extracted step plan, when available. step_plan_df : pd.DataFrame or None Step-plan table for richer inspection, when available. step_signature : str or None Stable signature of the step plan used for averaging compatibility. mass_hint_g : float or None Active-material mass discovered in the source file, in grams. source_metadata : dict[str, Any] Format-specific metadata (e.g. Neware sheet mapping). diagnostics : list[Diagnostic] Structured diagnostics raised during parsing.

Source code in batteryproc/batteryproc_types.py
@dataclass
class ParsedCell:
    """Result of parser dispatch for one source file, before analysis.

    Tables are the parser's format-specific *standardized* output (column
    names normalised to BatteryProc's record schema); they are not the
    cross-format canonical representation, which is produced by
    :func:`batteryproc.analyze_cell`.

    Attributes
    ----------
    source_path : Path or None
        Path of the parsed file. ``None`` only for synthesized inputs.
    parser_id : str
        Stable identifier of the parser implementation that produced the data.
    source_record : pd.DataFrame
        Standardized time-series (record) table.
    source_cycle : pd.DataFrame or None
        Standardized per-cycle summary table when the format provides one,
        otherwise ``None``.
    step_plan : str or None
        String rendering of the extracted step plan, when available.
    step_plan_df : pd.DataFrame or None
        Step-plan table for richer inspection, when available.
    step_signature : str or None
        Stable signature of the step plan used for averaging compatibility.
    mass_hint_g : float or None
        Active-material mass discovered in the source file, in grams.
    source_metadata : dict[str, Any]
        Format-specific metadata (e.g. Neware sheet mapping).
    diagnostics : list[Diagnostic]
        Structured diagnostics raised during parsing.
    """

    source_path: Path | None
    parser_id: str
    source_record: pd.DataFrame
    source_cycle: pd.DataFrame | None = None
    step_plan: str | None = None
    step_plan_df: pd.DataFrame | None = None
    step_signature: str | None = None
    mass_hint_g: float | None = None
    source_metadata: dict[str, Any] = field(default_factory=dict)
    diagnostics: list[Diagnostic] = field(default_factory=list)

PipelineOutcome dataclass

Structured result of :func:batteryproc.processing.process_file_pipeline.

Captures everything the per-file orchestration produced for one source file as typed fields, so callers (the CLI and the public API) branch on explicit values rather than reconstructing state from a bool | CellData return or scraped console text.

Attributes

status : {"success", "skipped", "failure"} Overall outcome of the pipeline for the file. "success" covers full analysis and the first-cycle-only partial result; "skipped" covers safety short-circuits that produce no per-cycle summary (e.g. a file that is too new); "failure" covers a blocked data-quality condition (bad cell). processed : ProcessedCell or None The full analytical result, when analysis ran. None only when no :class:ProcessedCell was produced. artifacts : list[ArtifactRecord] Files written for the cell. Empty when write_artifacts was disabled or when no artifacts were applicable. diagnostics : list[Diagnostic] Structured diagnostics accumulated during parsing and analysis. cell_data : CellData or None Cell payload assembled for the averaging workflows, populated only when capacity/energy averaging was requested and a summary was available. error_category : FileErrorCategory or None Failure classification, set when status is "failure" (or a classifiable skip). None on success.

Source code in batteryproc/batteryproc_types.py
@dataclass
class PipelineOutcome:
    """Structured result of :func:`batteryproc.processing.process_file_pipeline`.

    Captures everything the per-file orchestration produced for one source
    file as typed fields, so callers (the CLI and the public API) branch on
    explicit values rather than reconstructing state from a ``bool | CellData``
    return or scraped console text.

    Attributes
    ----------
    status : {"success", "skipped", "failure"}
        Overall outcome of the pipeline for the file. ``"success"`` covers
        full analysis and the first-cycle-only partial result; ``"skipped"``
        covers safety short-circuits that produce no per-cycle summary (e.g.
        a file that is too new); ``"failure"`` covers a blocked data-quality
        condition (bad cell).
    processed : ProcessedCell or None
        The full analytical result, when analysis ran. ``None`` only when no
        :class:`ProcessedCell` was produced.
    artifacts : list[ArtifactRecord]
        Files written for the cell. Empty when ``write_artifacts`` was
        disabled or when no artifacts were applicable.
    diagnostics : list[Diagnostic]
        Structured diagnostics accumulated during parsing and analysis.
    cell_data : CellData or None
        Cell payload assembled for the averaging workflows, populated only
        when capacity/energy averaging was requested and a summary was
        available.
    error_category : FileErrorCategory or None
        Failure classification, set when ``status`` is ``"failure"`` (or a
        classifiable skip). ``None`` on success.
    """

    status: Literal["success", "skipped", "failure"]
    processed: "ProcessedCell | None" = None
    artifacts: list[ArtifactRecord] = field(default_factory=list)
    diagnostics: list[Diagnostic] = field(default_factory=list)
    cell_data: "CellData | None" = None
    error_category: FileErrorCategory | None = None

ProcessOptions dataclass

Normalized processing parameters consumed by the programmatic API.

The CLI translates user arguments into this dataclass so that downstream code can operate on a stable, argparse-free structure. Only the values required by the processing pipeline are represented—UI-specific knobs such as progress output remain the responsibility of the CLI layer.

Attributes

outdir : Path or None Optional base directory for per-file output folders. When None the processor mirrors the CLI's default behaviour (placing results beside each input file). svg : bool Request SVG output alongside PNG plots. dpi : int Rendering resolution for generated plots. energy : bool Enable energy summaries and energy plots. derivative_cycles : tuple[int, ...] or None Specific cycle indices to use for dQ/dV calculations. None disables dQ/dV. dqdv_enabled : bool Convenience switch signalling whether dQ/dV should run, regardless of whether explicit indices were supplied. average : bool Enable capacity averaging workflows. average_energy : bool Enable energy averaging workflows. average_ignore_plan : bool Skip step-plan compatibility enforcement when averaging. force_process : bool Override safety checks that normally skip problematic files. prefer_file_metrics : bool Honour instrument-reported metrics during reconciliation. recompute_all : bool Ignore instrument metrics and recompute all per-cycle values. heuristic_map : bool Enable heuristic column mapping when supported by the parser. metric_tolerance : float or None Relative tolerance applied during metric reconciliation. metric_tolerance_abs : float or None Absolute tolerance applied prior to the relative tolerance check. mass_g : float or None Explicit active-material mass override. cell_weight_g : float or None Explicit whole-cell weight override for energy normalisation. cycle_config : CycleDetectionConfig or None Effective cycle-detection parameters applied to the metrics engine. validate_cycles : bool Emit cycle-detection validation summaries when enabled. debug : bool Enable verbose debug logging. debug_step_plan : bool Emit formatted step-plan tables during parsing (requires tabulate). debug_signatures : bool Print generated step-plan signatures for averaging diagnostics. metrics_defaults : MetricsConfig Metrics configuration resolved from configuration files. mappings_config : MappingsConfig or None Column-mapping configuration supplied to parser implementations. capture_output : bool Explicit opt-in for the convenience stdout/stderr capture machinery. Disabled by default (False): no stdout/stderr redirection occurs and the structured :class:Diagnostic system is the single source of truth for processing outcomes. When set to True, stdout/stderr produced by the processing pipeline are captured and surfaced on the :attr:FileResult.stdout/:attr:FileResult.stderr fields for debugging convenience; this never affects failure classification, which is always derived from structured diagnostics. The CLI leaves this False so that legacy console output streams unchanged. stream_errors : bool When True and capture_output is False, error messages are emitted directly to stderr as they occur. Setting this to False suppresses the immediate emission so callers can format messages themselves. csv_export : bool When True export plot data as CSV files alongside plots. csv_only : bool When True export plot data as CSV files and skip plot generation. Mutually exclusive with csv_export. quiet : bool Suppress non-critical warnings from stdout/stderr while keeping them available via logging or structured metadata. prompt_for_mass : bool Permit interactive mass prompting via input(). Defaults to False so that programmatic processing never blocks; the CLI explicitly enables it to preserve its interactive behaviour. write_artifacts : bool Produce output files (plots and CSV exports). Defaults to True to preserve historical behaviour; set to False for pure data processing with no filesystem side effects. original_inputs : tuple[str, ...] or None The raw input paths supplied on the command line before file discovery, used by the averaging workflows to distinguish explicit multi-file invocations from directory expansion. None for programmatic callers, in which case the averaging workflows fall back to the discovered file paths.

Source code in batteryproc/batteryproc_types.py
@dataclass(frozen=True)
class ProcessOptions:
    """Normalized processing parameters consumed by the programmatic API.

    The CLI translates user arguments into this dataclass so that downstream
    code can operate on a stable, argparse-free structure. Only the values
    required by the processing pipeline are represented—UI-specific knobs such
    as progress output remain the responsibility of the CLI layer.

    Attributes
    ----------
    outdir : Path or None
        Optional base directory for per-file output folders. When ``None`` the
        processor mirrors the CLI's default behaviour (placing results beside
        each input file).
    svg : bool
        Request SVG output alongside PNG plots.
    dpi : int
        Rendering resolution for generated plots.
    energy : bool
        Enable energy summaries and energy plots.
    derivative_cycles : tuple[int, ...] or None
        Specific cycle indices to use for dQ/dV calculations. ``None`` disables
        dQ/dV.
    dqdv_enabled : bool
        Convenience switch signalling whether dQ/dV should run, regardless of
        whether explicit indices were supplied.
    average : bool
        Enable capacity averaging workflows.
    average_energy : bool
        Enable energy averaging workflows.
    average_ignore_plan : bool
        Skip step-plan compatibility enforcement when averaging.
    force_process : bool
        Override safety checks that normally skip problematic files.
    prefer_file_metrics : bool
        Honour instrument-reported metrics during reconciliation.
    recompute_all : bool
        Ignore instrument metrics and recompute all per-cycle values.
    heuristic_map : bool
        Enable heuristic column mapping when supported by the parser.
    metric_tolerance : float or None
        Relative tolerance applied during metric reconciliation.
    metric_tolerance_abs : float or None
        Absolute tolerance applied prior to the relative tolerance check.
    mass_g : float or None
        Explicit active-material mass override.
    cell_weight_g : float or None
        Explicit whole-cell weight override for energy normalisation.
    cycle_config : CycleDetectionConfig or None
        Effective cycle-detection parameters applied to the metrics engine.
    validate_cycles : bool
        Emit cycle-detection validation summaries when enabled.
    debug : bool
        Enable verbose debug logging.
    debug_step_plan : bool
        Emit formatted step-plan tables during parsing (requires ``tabulate``).
    debug_signatures : bool
        Print generated step-plan signatures for averaging diagnostics.
    metrics_defaults : MetricsConfig
        Metrics configuration resolved from configuration files.
    mappings_config : MappingsConfig or None
        Column-mapping configuration supplied to parser implementations.
    capture_output : bool
        Explicit opt-in for the convenience stdout/stderr capture machinery.
        Disabled by default (``False``): no stdout/stderr redirection occurs and
        the structured :class:`Diagnostic` system is the single source of truth
        for processing outcomes. When set to ``True``, stdout/stderr produced by
        the processing pipeline are captured and surfaced on the
        :attr:`FileResult.stdout`/:attr:`FileResult.stderr` fields for
        debugging convenience; this never affects failure classification, which
        is always derived from structured diagnostics. The CLI leaves this
        ``False`` so that legacy console output streams unchanged.
    stream_errors : bool
        When ``True`` and ``capture_output`` is ``False``, error messages are
        emitted directly to stderr as they occur. Setting this to ``False``
        suppresses the immediate emission so callers can format messages
        themselves.
    csv_export : bool
        When ``True`` export plot data as CSV files alongside plots.
    csv_only : bool
        When ``True`` export plot data as CSV files and skip plot generation.
        Mutually exclusive with ``csv_export``.
    quiet : bool
        Suppress non-critical warnings from stdout/stderr while keeping them
        available via logging or structured metadata.
    prompt_for_mass : bool
        Permit interactive mass prompting via ``input()``. Defaults to
        ``False`` so that programmatic processing never blocks; the CLI
        explicitly enables it to preserve its interactive behaviour.
    write_artifacts : bool
        Produce output files (plots and CSV exports). Defaults to ``True``
        to preserve historical behaviour; set to ``False`` for pure data
        processing with no filesystem side effects.
    original_inputs : tuple[str, ...] or None
        The raw input paths supplied on the command line before file
        discovery, used by the averaging workflows to distinguish explicit
        multi-file invocations from directory expansion. ``None`` for
        programmatic callers, in which case the averaging workflows fall back
        to the discovered file paths.
    """

    outdir: Path | None = None
    svg: bool = False
    dpi: int = 300
    energy: bool = False
    derivative_cycles: tuple[int, ...] | None = None
    dqdv_enabled: bool = False
    average: bool = False
    average_energy: bool = False
    average_ignore_plan: bool = False
    force_process: bool = False
    prefer_file_metrics: bool = True
    recompute_all: bool = False
    heuristic_map: bool = True
    metric_tolerance: float | None = None
    metric_tolerance_abs: float | None = None
    mass_g: float | None = None
    cell_weight_g: float | None = None
    cycle_config: CycleDetectionConfig | None = None
    validate_cycles: bool = False
    debug: bool = False
    debug_step_plan: bool = False
    debug_signatures: bool = False
    metrics_defaults: MetricsConfig = field(default_factory=MetricsConfig)
    mappings_config: MappingsConfig | None = None
    csv_export: bool = False
    csv_only: bool = False
    capture_output: bool = False
    stream_errors: bool = True
    quiet: bool = False
    prompt_for_mass: bool = False
    write_artifacts: bool = True
    original_inputs: tuple[str, ...] | None = None

    def __post_init__(self) -> None:
        """Validate option combinations that must remain mutually exclusive."""
        if self.csv_export and self.csv_only:
            raise ValueError(
                "ProcessOptions.csv_export and ProcessOptions.csv_only are mutually exclusive."
            )

__post_init__()

Validate option combinations that must remain mutually exclusive.

Source code in batteryproc/batteryproc_types.py
def __post_init__(self) -> None:
    """Validate option combinations that must remain mutually exclusive."""
    if self.csv_export and self.csv_only:
        raise ValueError(
            "ProcessOptions.csv_export and ProcessOptions.csv_only are mutually exclusive."
        )

ProcessResult dataclass

Aggregate result produced when processing multiple files.

Attributes

files : list[FileResult] Per-file outcomes in processing order. success_count : int Number of files that completed without errors. failure_count : int Number of files that failed processing. skipped_count : int Number of files that were explicitly skipped. errors : list[str] Collection of high-level error messages raised during the batch.

Source code in batteryproc/batteryproc_types.py
@dataclass
class ProcessResult:
    """Aggregate result produced when processing multiple files.

    Attributes
    ----------
    files : list[FileResult]
        Per-file outcomes in processing order.
    success_count : int
        Number of files that completed without errors.
    failure_count : int
        Number of files that failed processing.
    skipped_count : int
        Number of files that were explicitly skipped.
    errors : list[str]
        Collection of high-level error messages raised during the batch.
    """

    files: list[FileResult] = field(default_factory=list)
    success_count: int = 0
    failure_count: int = 0
    skipped_count: int = 0
    errors: list[str] = field(default_factory=list)

    def error_categories(self) -> tuple[FileErrorCategory, ...]:
        """Return the ordered error categories observed across ``files``."""

        categories: list[FileErrorCategory] = []
        for file_result in self.files:
            if file_result.error_category is not None:
                categories.append(file_result.error_category)
        return tuple(categories)

error_categories()

Return the ordered error categories observed across files.

Source code in batteryproc/batteryproc_types.py
def error_categories(self) -> tuple[FileErrorCategory, ...]:
    """Return the ordered error categories observed across ``files``."""

    categories: list[FileErrorCategory] = []
    for file_result in self.files:
        if file_result.error_category is not None:
            categories.append(file_result.error_category)
    return tuple(categories)

ProcessedCell dataclass

Complete analytical result for one processed cell.

This is the primary object of the data-oriented public API. It carries the parser's standardized source tables, BatteryProc's cross-format canonical record, derived summaries, mass provenance, and structured diagnostics — independent of whether any artifact files were written.

Attributes

source_path : Path or None Source file the result was computed from. parser_id : str or None Identifier of the parser used. source_record : pd.DataFrame or None Parser-standardized time-series table. canonical_record : pd.DataFrame or None Cross-format canonical record produced by :meth:batteryproc.formulas.NormalizedInputs.to_frame. None when normalization could not locate the required channels (a missing_required_channel diagnostic is emitted instead). canonical_schema_version : str Version of the canonical record schema contract. source_cycle : pd.DataFrame or None Parser-standardized per-cycle table, when the format provides one. capacity_summary : pd.DataFrame or None Reconciled per-cycle capacity summary (the authoritative result, also used for averaging). None when no summary could be computed. energy_summary : pd.DataFrame or None Reconciled per-cycle energy summary. None unless energy computation was requested via the processing options. recomputed_capacity_summary : pd.DataFrame or None Capacity summary as recomputed by the formulas engine before reconciliation against file-reported metrics. This is the table the CLI plots are generated from. recomputed_energy_summary : pd.DataFrame or None Energy summary before reconciliation; None unless requested. first_cycle_profile : pd.DataFrame or None First-cycle voltage/capacity profile used by the overview plot. dqdv : Any or None Differential capacity traces when dQ/dV was requested. step_plan : str or None Step-plan string carried over from parsing. step_plan_df : pd.DataFrame or None Step-plan table carried over from parsing. step_signature : str or None Step-plan signature carried over from parsing. mass_hint_g : float or None Mass discovered in the source file, in grams. resolved_mass_g : float or None Active-material mass actually used for normalization, in grams. None when mass remained unknown (mass_missing diagnostic). mass_source : str or None Provenance of resolved_mass_g: "cli", "config", "infer", "prompt", or None when unresolved. resolved_cell_weight_g : float or None Whole-cell weight used for energy normalization, in grams. source_columns : dict[str, str] Mapping from canonical column name to the original source column that supplied it during normalization. cycle_metadata : dict[str, Any] or None Cycle-detection metadata tracker (primary/latest/events). processing_options : Any or None The :class:AnalysisOptions the result was computed with. processing_metadata : dict[str, Any] Provenance details (package version, reconciliation settings, ...). source_metadata : dict[str, Any] Format-specific parse metadata carried over from the :class:ParsedCell (e.g. Neware sheet_mapping and test_sheet_found); used to preserve legacy CLI messaging. diagnostics : list[Diagnostic] Structured diagnostics accumulated during parsing and analysis.

Source code in batteryproc/batteryproc_types.py
@dataclass
class ProcessedCell:
    """Complete analytical result for one processed cell.

    This is the primary object of the data-oriented public API. It carries
    the parser's standardized source tables, BatteryProc's cross-format
    canonical record, derived summaries, mass provenance, and structured
    diagnostics — independent of whether any artifact files were written.

    Attributes
    ----------
    source_path : Path or None
        Source file the result was computed from.
    parser_id : str or None
        Identifier of the parser used.
    source_record : pd.DataFrame or None
        Parser-standardized time-series table.
    canonical_record : pd.DataFrame or None
        Cross-format canonical record produced by
        :meth:`batteryproc.formulas.NormalizedInputs.to_frame`. ``None`` when
        normalization could not locate the required channels (a
        ``missing_required_channel`` diagnostic is emitted instead).
    canonical_schema_version : str
        Version of the canonical record schema contract.
    source_cycle : pd.DataFrame or None
        Parser-standardized per-cycle table, when the format provides one.
    capacity_summary : pd.DataFrame or None
        Reconciled per-cycle capacity summary (the authoritative result, also
        used for averaging). ``None`` when no summary could be computed.
    energy_summary : pd.DataFrame or None
        Reconciled per-cycle energy summary. ``None`` unless energy
        computation was requested via the processing options.
    recomputed_capacity_summary : pd.DataFrame or None
        Capacity summary as recomputed by the formulas engine *before*
        reconciliation against file-reported metrics. This is the table the
        CLI plots are generated from.
    recomputed_energy_summary : pd.DataFrame or None
        Energy summary before reconciliation; ``None`` unless requested.
    first_cycle_profile : pd.DataFrame or None
        First-cycle voltage/capacity profile used by the overview plot.
    dqdv : Any or None
        Differential capacity traces when dQ/dV was requested.
    step_plan : str or None
        Step-plan string carried over from parsing.
    step_plan_df : pd.DataFrame or None
        Step-plan table carried over from parsing.
    step_signature : str or None
        Step-plan signature carried over from parsing.
    mass_hint_g : float or None
        Mass discovered in the source file, in grams.
    resolved_mass_g : float or None
        Active-material mass actually used for normalization, in grams.
        ``None`` when mass remained unknown (``mass_missing`` diagnostic).
    mass_source : str or None
        Provenance of ``resolved_mass_g``: ``"cli"``, ``"config"``,
        ``"infer"``, ``"prompt"``, or ``None`` when unresolved.
    resolved_cell_weight_g : float or None
        Whole-cell weight used for energy normalization, in grams.
    source_columns : dict[str, str]
        Mapping from canonical column name to the original source column
        that supplied it during normalization.
    cycle_metadata : dict[str, Any] or None
        Cycle-detection metadata tracker (``primary``/``latest``/``events``).
    processing_options : Any or None
        The :class:`AnalysisOptions` the result was computed with.
    processing_metadata : dict[str, Any]
        Provenance details (package version, reconciliation settings, ...).
    source_metadata : dict[str, Any]
        Format-specific parse metadata carried over from the
        :class:`ParsedCell` (e.g. Neware ``sheet_mapping`` and
        ``test_sheet_found``); used to preserve legacy CLI messaging.
    diagnostics : list[Diagnostic]
        Structured diagnostics accumulated during parsing and analysis.
    """

    source_path: Path | None = None
    parser_id: str | None = None
    source_record: pd.DataFrame | None = None
    canonical_record: pd.DataFrame | None = None
    canonical_schema_version: str = ""
    source_cycle: pd.DataFrame | None = None
    capacity_summary: pd.DataFrame | None = None
    energy_summary: pd.DataFrame | None = None
    recomputed_capacity_summary: pd.DataFrame | None = None
    recomputed_energy_summary: pd.DataFrame | None = None
    first_cycle_profile: pd.DataFrame | None = None
    dqdv: Any | None = None
    step_plan: str | None = None
    step_plan_df: pd.DataFrame | None = None
    step_signature: str | None = None
    mass_hint_g: float | None = None
    resolved_mass_g: float | None = None
    mass_source: str | None = None
    resolved_cell_weight_g: float | None = None
    source_columns: dict[str, str] = field(default_factory=dict)
    cycle_metadata: dict[str, Any] | None = None
    processing_options: Any | None = None
    processing_metadata: dict[str, Any] = field(default_factory=dict)
    source_metadata: dict[str, Any] = field(default_factory=dict)
    diagnostics: list[Diagnostic] = field(default_factory=list)

    def diagnostic_codes(self) -> tuple[str, ...]:
        """Return the ordered diagnostic codes attached to this result."""

        return tuple(diag.code for diag in self.diagnostics)

    def has_diagnostic(self, code: str) -> bool:
        """Return ``True`` when a diagnostic with ``code`` is present."""

        return any(diag.code == code for diag in self.diagnostics)

diagnostic_codes()

Return the ordered diagnostic codes attached to this result.

Source code in batteryproc/batteryproc_types.py
def diagnostic_codes(self) -> tuple[str, ...]:
    """Return the ordered diagnostic codes attached to this result."""

    return tuple(diag.code for diag in self.diagnostics)

has_diagnostic(code)

Return True when a diagnostic with code is present.

Source code in batteryproc/batteryproc_types.py
def has_diagnostic(self, code: str) -> bool:
    """Return ``True`` when a diagnostic with ``code`` is present."""

    return any(diag.code == code for diag in self.diagnostics)

ProcessingStage

Bases: str, Enum

Pipeline stage that produced a :class:Diagnostic.

Source code in batteryproc/batteryproc_types.py
class ProcessingStage(str, Enum):
    """Pipeline stage that produced a :class:`Diagnostic`."""

    PARSE = "parse"
    NORMALIZE = "normalize"
    METRICS = "metrics"
    VALIDATION = "validation"
    ARTIFACT = "artifact"

UnitConversion dataclass

Unit conversion description for a standardized column.

Parameters

from_unit : str Name of the unit expected in the raw data (e.g., "mV"). factor : float Multiplicative factor to convert from from_unit to the standardized unit used by BatteryProc.

Source code in batteryproc/batteryproc_types.py
@dataclass
class UnitConversion:
    """Unit conversion description for a standardized column.

    Parameters
    ----------
    from_unit : str
        Name of the unit expected in the raw data (e.g., "mV").
    factor : float
        Multiplicative factor to convert from `from_unit` to the standardized unit
        used by BatteryProc.
    """

    from_unit: str
    factor: float