Skip to content

Readers

The cell object, its frames, and the cellpy-file I/O behind them.

CellpyCell

CellpyCell(filenames=None, selected_scans=None, profile=False, filestatuschecker=None, tester=None, initialize=False, cellpy_units=None, output_units=None, debug=False, native_schema=True, core=None, instrument_factory=None)

Main class for working and storing data.

This class is the main work-horse for cellpy where methods for reading, selecting, and tweaking your data is located. It also contains the header definitions, both for the cellpy hdf5 format, and for the various cell-tester file-formats that can be read.

Attributes:

  • data

    cellpy.Data object containing the data

  • cellpy_units

    cellpy.units object

  • cellpy_datadir

    path to cellpy data directory

  • raw_datadir

    path to raw data directory

  • filestatuschecker

    filestatuschecker object

  • force_step_table_creation

    force step table creation

  • ensure_step_table

    ensure step table

  • limit_loaded_cycles

    limit loaded cycles

  • profile

    profile

  • select_minimal

    select minimal

  • empty

    empty

  • forced_errors

    forced errors

  • capacity_modifiers

    capacity modifiers

  • sep

    delimiter to use when reading (when applicable) and exporting files

  • cycle_mode

    cycle mode

  • tester

    tester

  • cell_name

    cell name (session name, defaults to concatenated names of the subtests)

Parameters:

  • filenames

    list of files to load.

  • selected_scans
  • profile

    experimental feature.

  • filestatuschecker

    property to compare cellpy and raw-files; default read from prms-file.

  • tester

    instrument used (e.g. "arbin_res") (checks prms-file as default).

  • initialize

    create a dummy (empty) dataset; defaults to False.

  • cellpy_units (dict, default: None ) –

    sent to cellpy.parameters.internal_settings.get_cellpy_units

  • output_units (dict, default: None ) –

    sent to cellpy.parameters.internal_settings.get_default_output_units

  • debug (bool, default: False ) –

    set to True if you want to see debug messages.

  • core (CellpyCellCore, default: None ) –

    injected core seam (issue #520, DI). When given it is used as-is (it owns the Data object and runs the step/summary engine); when None the default is built from the native_schema flag.

  • instrument_factory (InstrumentFactory, default: None ) –

    injected loader registry (issue #520, DI). When None, register_instrument_readers() builds the default factory.

  • native_schema (bool, default: True ) –

    the runtime column schema (native-headers flip, Stage 5a). Defaults to True in cellpy 2: frames are kept in native cellpy-core column names and the polars engine runs directly (no legacy rename sandwich); legacy attribute access (headers_normal.voltage_txt, ...) is carried by the D6 shim (legacy_header_shim). Set False for the legacy bridge (OldCellpyCellCore, legacy column names) — the path for v8 byte round-trips and merge until native merge lands (5b). get_cap / exporters / plotting work on a native cell via the shim; merge still requires the legacy path.

active_electrode_area property writable

active_electrode_area

Returns the area

active_mass property writable

active_mass

Returns the active mass (same as mass)

cell_name property writable

cell_name

Returns the session name

cycle_mode property writable

cycle_mode

The active test's cycle_mode (scalar).

For per-test access on multi-test objects, use self.data.get_cycle_mode(test_id) / set_cycle_mode and the self.data.tests collection (issue #506).

data property writable

data

Returns the DataSet instance

empty property

empty

Gives True if the CellpyCell object is empty (or non-functional)

mass property writable

mass

Returns the mass

nom_cap property writable

nom_cap

Returns the nominal capacity

nom_cap_specifics property writable

nom_cap_specifics

Returns the nominal capacity specific

nominal_capacity property writable

nominal_capacity

Returns the nominal capacity

raw_units property

raw_units

Returns the raw_units dictionary

schema property

schema

The column names of this cell's frames (the public header API).

Use this instead of headers_normal / headers_step_table / headers_summary, which are a deprecation shim as of 2.0 (removed in 2.1)::

c.data.raw[c.schema.raw.potential]
c.data.steps[c.schema.steps.cycle_num]
c.data.summary[c.schema.summary.charge_capacity]

The frames are named as they are on c.data: raw, steps, summary. You always spell the column the native way; the value tracks the runtime, so on the legacy runtime (native_schema=False) schema.raw.potential returns "voltage" — the name that actually indexes that frame. Whatever this returns is a valid column key for the matching frame. See :mod:cellpy.parameters.cell_schema.

tot_mass property writable

tot_mass

Returns the total mass

add_to_summary

add_to_summary(column: str, method: str = 'last', new_name: Optional[str] = None) -> CellpyCell

Augment the summary frame with one value per cycle pulled from raw.

For every cycle present in self.data.summary, group the raw rows of column by cycle_index and reduce them with method. The result is written onto the summary frame in place.

Parameters:

  • column (str) –

    name of the column in self.data.raw to look up.

  • method (str, default: 'last' ) –

    groupby reducer applied per cycle. One of "last" (default), "first", "mean", "min", "max".

  • new_name (Optional[str], default: None ) –

    name to use for the new summary column. Defaults to column.

Returns:

Raises:

  • ValueError

    if column is not present in the raw frame or method is not one of the supported reducers.

  • NoDataFound

    propagated from self.data if no data is loaded.

check_file_ids

check_file_ids(rawfiles, cellpyfile, detailed=False)

Check the stats for the files (raw-data and cellpy hdf5).

This method checks if the hdf5 file and the res-files have the same timestamps etc. to find out if we need to bother to load .res -files.

if detailed is set to True, the method returns dict containing True or False for each individual raw-file. If not, it returns False if the raw files are newer than the cellpy hdf5-file (i.e. update is needed), else True.

Parameters:

  • cellpyfile (str) –

    filename of the cellpy hdf5-file.

  • rawfiles (list of str) –

    name(s) of raw-data file(s).

  • detailed (bool, default: False ) –

    return a dict containing True or False for each individual raw-file.

Returns:

  • Bool or dict

drop_edges

drop_edges(start: int, end: int) -> CellpyCell

Select middle part of experiment. See :func:cellpy.readers.slicing.drop_edges.

drop_from

drop_from(cycle=None)

Select first part of experiment up to cycle. See :func:cellpy.readers.slicing.drop_from.

drop_to

drop_to(cycle=None)

Select last part of experiment from cycle. See :func:cellpy.readers.slicing.drop_to.

filtered_summary

filtered_summary(*, rate=None, rate_columns=None, **extra_filters)

Return a filtered copy of the summary DataFrame.

Thin wrapper around :func:cellpy.filters.filter_summary that resolves the rate column names from self.headers_summary. See the underlying function for the full range semantics; in short (low, high) keeps rows where low < value <= high and {"value": v, "delta": d} keeps rows where v - d < value <= v + d.

Note

The name deliberately reads as a property-style "give me a filtered summary" - the return is just the summary DataFrame. The slot CellpyCell.filter_summary is reserved for a future method that returns a full CellpyCell with the summary, raw, and steps frames all filtered consistently.

Parameters:

  • rate

    Range filter applied to the rate columns. None disables it (default).

  • rate_columns

    Override which rate columns are filtered. Defaults to both (headers_summary.charge_c_rate, headers_summary.discharge_c_rate). Pass a single string to filter on only one side.

  • **extra_filters

    Additional range filters registered with :func:cellpy.filters.register_range_filter.

Returns:

  • Filtered copy of self.data.summary (cycle index reset

  • to a column so the result is a plain DataFrame).

from_cycle

from_cycle(cycle: int) -> CellpyCell

Select experiment from cycle number. See :func:cellpy.readers.slicing.from_cycle.

from_raw

from_raw(file_names=None, pre_processor_hook=None, post_processor_hook=None, is_a_file=True, refuse_copying=False, **kwargs)

Load a raw data-file.

Parameters:

  • file_names (list of raw-file names, default: None ) –

    uses CellpyCell.file_names if None. If the list contains more than one file name, then the runs will be merged together. Remark! the order of the files in the list is important.

  • pre_processor_hook (callable, default: None ) –

    function that will be applied to the data within the loader.

  • post_processor_hook (callable, default: None ) –

    function that will be applied to the cellpy.Dataset object after initial loading.

  • is_a_file (bool, default: True ) –

    set this to False if it is a not a file-like object.

  • refuse_copying (bool, default: False ) –

    if set to True, the raw-file will not be copied before loading.

Transferred Parameters

recalc (bool): used by merging. Set to false if you don't want cellpy to automatically shift cycle number and time (e.g. add last cycle number from previous file to the cycle numbers in the next file). bad_steps (list of tuples): used by ArbinLoader. (c, s) tuples of steps s (in cycle c) to skip loading. data_points (tuple of ints): used by ArbinLoader. Load only data from data_point[0] to data_point[1] (use None for infinite). NOT IMPLEMENTED YET.

get_cap

get_cap(cycle=None, cycles=None, method='back-and-forth', insert_nan=None, shift=0.0, categorical_column=False, label_cycle_number=False, split=False, interpolated=False, dx=0.1, number_of_points=None, ignore_errors=True, inter_cycle_shift=True, interpolate_along_cap=False, capacity_then_voltage=False, mode='gravimetric', mass=None, area=None, volume=None, cycle_mode=None, usteps=None, dynamic=False, **kwargs)

Gets the capacity for the run. See :func:cellpy.readers.capacity_curves.get_cap.

get_ccap

get_ccap(cycle=None, converter=None, mode='gravimetric', as_frame=True, usteps=False, **kwargs)

Returns charge capacity and voltage for the selected cycle. See :func:cellpy.readers.capacity_curves.get_ccap.

get_converter_to_specific

get_converter_to_specific(dataset: Data = None, value: float = None, from_units: CellpyUnits = None, to_units: CellpyUnits = None, mode: str = 'gravimetric') -> float

Convert from absolute units to specific (areal or gravimetric).

The method provides a conversion factor that you can multiply your values with to get them into specific values.

Parameters:

  • dataset (Data, default: None ) –

    data instance

  • value (float, default: None ) –

    value used to scale on.

  • from_units (CellpyUnits, default: None ) –

    defaults to data.raw_units.

  • to_units (CellpyUnits, default: None ) –

    defaults to cellpy_units.

  • mode (str, default: 'gravimetric' ) –

    gravimetric, areal or absolute

Returns:

  • float

    conversion factor (float)

get_current

get_current(cycle=None, with_index=True, with_time=False, as_frame=True)

Returns current (in raw units).

Parameters:

  • cycle

    cycle number (all cycles if None).

  • with_index

    if True, includes the cycle index as a column in the returned pandas.DataFrame.

  • with_time

    if True, includes the time as a column in the returned pandas.DataFrame.

  • as_frame

    if not True, returns a list of current values as numpy arrays (one for each cycle). Remark that with_time and with_index will be False if as_frame is set to False.

Returns:

  • pandas.DataFrame (or list of pandas.Series if cycle=None and as_frame=False)

get_cycle_numbers

get_cycle_numbers(steptable=None, rate=None, rate_on=None, rate_std=None, rate_agg='first', inverse=False)

Get a array containing the cycle numbers in the test.

Parameters:

  • steptable (DataFrame, default: None ) –

    the step-table to use (if None, the step-table from the cellpydata object will be used).

  • rate (float, default: None ) –

    the rate to filter on. Remark that it should be given as a float, i.e. you will have to convert from C-rate to the actual numeric value. For example, use rate=0.05 if you want to filter on cycles that has a C/20 rate.

  • rate_on (str, default: None ) –

    only select cycles if based on the rate of this step-type (e.g. on="discharge").

  • rate_std (float, default: None ) –

    allow for this inaccuracy in C-rate when selecting cycles

  • rate_agg (str, default: 'first' ) –

    perform an aggregation on rate if more than one step of charge or discharge is found (e.g. "mean", "first", "max"). For example, if agg='mean', the average rate for each cycle will be returned. Set to None if you want to keep all the rates.

  • inverse (bool, default: False ) –

    select steps that does not have the given C-rate.

Returns:

  • numpy.ndarray of cycle numbers.

get_datetime

get_datetime(cycle=None, with_index=True, with_time=False, as_frame=True)

Returns datetime (in raw units).

Parameters:

  • cycle

    cycle number (all cycles if None).

  • with_index

    if True, includes the cycle index as a column in the returned pandas.DataFrame.

  • with_time

    if True, includes the time as a column in the returned pandas.DataFrame.

  • as_frame

    if not True, returns a list of current values as numpy arrays (one for each cycle). Remark that with_time and with_index will be False if as_frame is set to False.

Returns:

  • pandas.DataFrame (or list of pandas.Series if cycle=None and as_frame=False)

get_dcap

get_dcap(cycle=None, converter=None, mode='gravimetric', as_frame=True, usteps=False, **kwargs)

Returns discharge capacity and voltage for the selected cycle. See :func:cellpy.readers.capacity_curves.get_dcap.

get_ir

get_ir()

Get the IR data (Deprecated).

get_mass

get_mass()

Returns the mass of the active material (in mg).

This method will be deprecated in the future.

get_number_of_cycles

get_number_of_cycles(steptable=None)

Get the number of cycles in the test.

get_ocv

get_ocv(cycles=None, direction='up', remove_first=False, interpolated=False, dx=None, number_of_points=None)

Get the open circuit voltage relaxation curves. See :func:cellpy.readers.capacity_curves.get_ocv.

get_rates

get_rates(steptable=None, agg='first', direction=None)

Get the rates in the test (only valid for constant current).

Parameters:

  • steptable

    provide custom steptable (if None, the steptable from the cellpydata object will be used).

  • agg (str, default: 'first' ) –

    perform an aggregation if more than one step of charge or discharge is found (e.g. "mean", "first", "max"). For example, if agg='mean', the average rate for each cycle will be returned. Set to None if you want to keep all the rates.

  • direction (str or list of str, default: None ) –

    only select rates for this direction (e.g. "charge" or "discharge").

Returns:

  • pandas.DataFrame with cycle, type, and rate_avr (i.e. C-rate) columns.

get_raw

get_raw(header, cycle: Optional[Union[Iterable, int]] = None, with_index: bool = True, with_step: bool = False, with_time: bool = False, additional_headers: Optional[list] = None, as_frame: bool = True, scaler: Optional[float] = None) -> Union[externals.pandas.DataFrame, List[externals.numpy.array]]

Returns the values for column with given header (in raw units).

Parameters:

  • header

    header name.

  • cycle (Optional[Union[Iterable, int]], default: None ) –

    cycle number (all cycles if None).

  • with_index (bool, default: True ) –

    if True, includes the cycle index as a column in the returned pandas.DataFrame.

  • with_step (bool, default: False ) –

    if True, includes the step index as a column in the returned pandas.DataFrame.

  • with_time (bool, default: False ) –

    if True, includes the time as a column in the returned pandas.DataFrame.

  • additional_headers (list, default: None ) –

    additional headers to include in the returned pandas.DataFrame.

  • as_frame (bool, default: True ) –

    if not True, returns a list of current values as numpy arrays (one for each cycle). Remark that with_time and with_index will be False if as_frame is set to False.

  • scaler (Optional[float], default: None ) –

    if not None, the returned values are scaled by this value.

Returns:

  • Union[DataFrame, List[array]]

    pandas.DataFrame (or list of numpy arrays if as_frame=False)

get_step_numbers

get_step_numbers(steptype: str = 'charge', allctypes: bool = True, pdtype: bool = False, cycle_number: int = None, trim_taper_steps: int = None, steps_to_skip: Optional[list] = None, steptable: Any = None, usteps: bool = False) -> Union[dict, Any]

Get the step numbers of selected type.

Returns the selected step_numbers for the selected type of step(s). Either in a dictionary containing a list of step numbers corresponding to the selected steptype for the cycle(s), or a pandas.DataFrame instead of a dict of lists if pdtype is set to True. The frame is a sub-set of the step-table frame (i.e. all the same columns, only filtered by rows).

Parameters:

  • steptype (str, default: 'charge' ) –

    string identifying type of step.

  • allctypes (bool, default: True ) –

    get all types of charge (or discharge).

  • pdtype (bool, default: False ) –

    return results as pandas.DataFrame

  • cycle_number (int, default: None ) –

    selected cycle, selects all if not set.

  • trim_taper_steps (int, default: None ) –

    number of taper steps to skip (counted from the end, i.e. 1 means skip last step in each cycle).

  • steps_to_skip (list, default: None ) –

    step numbers that should not be included.

  • steptable (DataFrame, default: None ) –

    optional steptable

Returns:

Examples:

>>> my_charge_steps = CellpyCell.get_step_numbers(
>>>    "charge",
>>>    cycle_number = 3
>>> )
>>> print my_charge_steps
{3: [5,8]}

get_summary

get_summary(use_summary_made=False)

Retrieve summary returned as a pandas DataFrame.

Warning

This function is deprecated. Use the CellpyCell.data.summary property instead.

get_timestamp

get_timestamp(cycle=None, with_index=True, as_frame=True, in_minutes=False, units='raw')

Returns timestamp.

Parameters:

  • cycle

    cycle number (all cycles if None).

  • with_index

    if True, includes the cycle index as a column in the returned pandas.DataFrame.

  • as_frame

    if not True, returns a list of current values as numpy arrays (one for each cycle). Remark that with_time and with_index will be False if as_frame is set to False.

  • in_minutes

    (deprecated, use units="minutes" instead) return values in minutes instead of seconds if True.

  • units

    return values in given time unit ("raw", "seconds", "minutes", "hours").

Returns:

  • pandas.DataFrame (or list of pandas.Series if cycle=None and as_frame=False)

get_voltage

get_voltage(cycle=None, with_index=True, with_time=False, as_frame=True)

Returns voltage (in raw units).

Parameters:

  • cycle

    cycle number (all cycles if None).

  • with_index

    if True, includes the cycle index as a column in the returned pandas.DataFrame.

  • with_time

    if True, includes the time as a column in the returned pandas.DataFrame.

  • as_frame

    if not True, returns a list of current values as numpy arrays (one for each cycle). Remark that with_time and with_index will be False if as_frame is set to False.

Returns:

  • pandas.DataFrame (or list of pandas.Series if cycle=None and as_frame=False)

has_data_point_as_column

has_data_point_as_column()

Check if the raw data has data_point as column.

has_data_point_as_index

has_data_point_as_index()

Check if the raw data has data_point as index.

has_no_full_duplicates

has_no_full_duplicates()

Check if the raw data has no full duplicates.

has_no_partial_duplicates

has_no_partial_duplicates(subset='data_point')

Check if the raw data has no partial duplicates.

initialize

initialize()

Initialize the CellpyCell object with empty Data instance.

inspect_nominal_capacity

inspect_nominal_capacity(cycles=None)

Method for estimating the nominal capacity

Parameters:

  • cycles (list of ints, default: None ) –

    the cycles where it is assumed that the data reaches nominal capacity.

Returns:

  • Nominal capacity (float).

load

load(cellpy_file, parent_level=None, return_cls=True, accept_old=False, selector=None, **kwargs)

Loads a cellpy file.

Parameters:

  • cellpy_file ((OtherPath, str)) –

    Full path to the cellpy file.

  • parent_level (str, default: None ) –

    Parent level. Warning! Deprecating this soon!

  • return_cls (bool, default: True ) –

    Return the class.

  • accept_old (bool, default: False ) –

    Accept loading pre-v8 cellpy-file versions. Default is False (2.0 freeze): pre-v8 raises WrongFileVersion naming cellpy convert on 1.x. Pass True only as an escape (tests / advanced use). Prefer rewriting with cellpy convert instead.

  • selector (dict, default: None ) –

    Experimental feature - select specific ranges of data.

Returns:

  • cellpy.CellpyCell class if return_cls is True

load_step_specifications

load_step_specifications(file_name, short=False)

Load a table that contains step-type definitions.

This method loads a file containing a specification for each step or for each (cycle_number, step_number) combinations if short==False, and runs the make_step_table method. The step_cycle specifications that are allowed are stored in the variable cellreader.list_of_step_types.

Parameters:

  • file_name (str) –

    name of the file to load

  • short (bool, default: False ) –

    if True, the file only contains step numbers and step types. If False, the file contains cycle numbers as well.

Returns:

  • None

loadcell

loadcell(raw_files, cellpy_file=None, mass=None, summary_on_raw=True, summary_on_cellpy_file=True, find_ir=True, find_end_voltage=True, force_raw=False, use_cellpy_stat_file=None, cell_type=None, loading=None, area=None, estimate_area=True, selector=None, **kwargs)

Loads data for given cells (soon to be deprecated).

Parameters:

  • raw_files (list) –

    name of res-files

  • cellpy_file (path, default: None ) –

    name of cellpy-file

  • mass (float or str, default: None ) –

    mass of electrode or active material in cellpy_units (default mg). Pass a string with unit (e.g. "1.14 mg") to override cellpy_units.

  • summary_on_raw (bool, default: True ) –

    calculate summary if loading from raw

  • summary_on_cellpy_file (bool, default: True ) –

    calculate summary if loading from cellpy-file.

  • find_ir (bool, default: True ) –

    summarize ir

  • find_end_voltage (bool, default: True ) –

    summarize end voltage

  • force_raw (bool, default: False ) –

    only use raw-files

  • use_cellpy_stat_file (bool, default: None ) –

    use stat file if creating summary from raw

  • cell_type (str, default: None ) –

    set the data type (e.g. "anode"). If not, the default from the config file is used.

  • loading (float or str, default: None ) –

    loading in units [mass] / [area] (cellpy_units), used to calculate area if area not given.

  • area (float or str, default: None ) –

    area of active electrode in cellpy_units (default cm2). Pass a string with unit (e.g. "2.12 cm2") to override cellpy_units.

  • estimate_area (bool, default: True ) –

    calculate area from loading if given (defaults to True).

  • selector (dict, default: None ) –

    passed to load.

  • **kwargs

    passed to from_raw

Examples:

>>> srnos = my_dbreader.select_batch("testing_new_solvent")
>>> cell_datas = []
>>> for srno in srnos:
>>> ... my_run_name = my_dbreader.get_cell_name(srno)
>>> ... mass = my_dbreader.get_mass(srno)
>>> ... rawfiles, cellpyfiles =             >>> ...     filefinder.search_for_files(my_run_name)
>>> ... cell_data = cellreader.CellpyCell()
>>> ... cell_data.loadcell(raw_files=rawfiles,
>>> ...                    cellpy_file=cellpyfiles)
>>> ... cell_data.set_mass(mass)
>>> ... cell_data.make_summary() # etc. etc.
>>> ... cell_datas.append(cell_data)
>>>
Warning

This method will soon be deprecated. Use cellpy.get instead.

make_step_table

make_step_table(step_specifications=None, short=False, override_step_types=None, override_raw_limits=None, profiling=False, all_steps=False, usteps=False, add_c_rate=True, skip_steps=None, sort_rows=True, from_data_point=None, nom_cap_specifics=None)

Create a table (v.4) that contains summary information for each step.

This function creates a table containing information about the different steps for each cycle and, based on that, decides what type of step it is (e.g. charge) for each cycle.

The format of the steps is:

  • index: cycleno - stepno - sub-step-no - ustep
  • Time info: average, stdev, max, min, start, end, delta
  • Logging info: average, stdev, max, min, start, end, delta
  • Current info: average, stdev, max, min, start, end, delta
  • Voltage info: average, stdev, max, min, start, end, delta
  • Type: (from pre-defined list) - SubType
  • Info: not used.

Parameters:

  • step_specifications (DataFrame, default: None ) –

    step specifications

  • short (bool, default: False ) –

    step specifications in short format

  • override_step_types (dict, default: None ) –

    override the provided step types, for example set all steps with step number 5 to "charge" by providing {5: "charge"}.

  • override_raw_limits (dict, default: None ) –

    override the instrument limits (resolution), for example set 'current_hard' to 0.1 by providing {'current_hard': 0.1}.

  • profiling (bool, default: False ) –

    turn on profiling

  • usteps (bool, default: False ) –

    investigate all steps including same steps within one cycle (this is useful for e.g. GITT).

  • add_c_rate (bool, default: True ) –

    include a C-rate estimate in the steps

  • skip_steps (list of integers, default: None ) –

    list of step numbers that should not be processed (future feature - not used yet).

  • sort_rows (bool, default: True ) –

    sort the rows after processing.

  • from_data_point (int, default: None ) –

    first data point to use.

  • nom_cap_specifics (str, default: None ) –

    "gravimetric", "areal", or "absolute".

Returns:

  • None

make_summary

make_summary(find_ir=False, find_end_voltage=True, use_cellpy_stat_file=None, ensure_step_table=True, remove_duplicates=True, normalization_cycles=None, nom_cap=None, nom_cap_specifics=None, create_copy=False, exclude_types=None, exclude_steps=None, selector_type=None, selector=None, exclude_step_types=None, **kwargs)

Convenience function that makes a summary of the cycling data.

Parameters:

  • find_ir (bool, default: False ) –

    if True, the internal resistance will be calculated.

  • find_end_voltage (bool, default: True ) –

    if True, the end voltage will be calculated.

  • use_cellpy_stat_file (bool, default: None ) –

    if True, the summary will be made from the cellpy_stat file (soon to be deprecated).

  • ensure_step_table (bool, default: True ) –

    if True, the step-table will be made if it does not exist.

  • remove_duplicates (bool, default: True ) –

    if True, duplicates will be removed from the summary.

  • normalization_cycles (int or list of int, default: None ) –

    cycles to use for normalization.

  • nom_cap (float or str, default: None ) –

    nominal capacity (if None, the nominal capacity from the data will be used).

  • nom_cap_specifics (str, default: None ) –

    gravimetric, areal, or volumetric.

  • create_copy (bool, default: False ) –

    if True, a copy of the cellpy object will be returned.

  • exclude_types (list of str, default: None ) –

    deprecated, has no effect.

  • exclude_steps (list of int, default: None ) –

    deprecated, has no effect.

  • selector_type (str, default: None ) –

    deprecated, has no effect.

  • selector (callable, default: None ) –

    deprecated, has no effect.

  • exclude_step_types (list of str, default: None ) –

    step-type prefixes whose capacity contributions are excluded from the summary (issue #509, core #54). E.g. ["cv_"] matches cv_charge and cv_discharge; the capacity gained during the excluded steps is subtracted per cycle from the cycle-end charge/discharge capacities before derived columns (coulombic efficiency, losses, cumulated and specific columns) are computed — a summary "as if those steps never happened". Replaces the removed selector-based exclusion.

  • **kwargs

    additional keyword arguments sent to internal method (check source for info).

Returns:

  • cellpy.CellpyData: cellpy object with the summary added to it.

merge

merge(cells, mode='campaign', renumber_cycles=True, **kwargs)

Merge other cells/datasets into this one.

Two distinct semantics (issue #507, epic #402 V2-03/V2-07):

  • mode="campaign" (default): the sources are different tests (possibly different cells or programs). Each source keeps its identity via a distinct compact test_id stamped on the raw frame (this overwrites tester-assigned ids such as Arbin's Test_ID — those remain as provenance in meta_test_dependent.test_ID), and its metadata becomes a record in self.data.tests. Cycle numbers are renumbered to be globally unique by default (see renumber_cycles); data points are offset; test_time / date_time are not shifted (independent timelines). Sources are never mutated. Mixing different cycle_mode values is allowed here, but computing steps/summary on the merged object then raises MixedCycleModesError.
  • mode="continuation": the sources are the same physical test resumed across files — the classic fold, numerically identical to from_raw([file1, file2]) (cycles, data points and test time are renumbered into one continuous run; source metadata is dropped). Extra **kwargs (e.g. recalc) are forwarded.

Parameters:

  • cells

    a CellpyCell or Data instance, or a sequence of them.

  • mode (str, default: 'campaign' ) –

    "campaign" (default) or "continuation".

  • renumber_cycles (bool, default: True ) –

    campaign mode only. If True (default), cycle numbers are renumbered to be globally unique. If False (#529, needs cellpycore >= 0.2.2), sources keep their original cycle numbers: the identifying key becomes (test_id, cycle) and cycle numbers repeat across tests — cycle-keyed consumers (get_cap(cycle=...), split / with_cycles, exporters) then operate on the union of the matching cycles. Data points are always offset to stay globally unique.

  • **kwargs

    forwarded to the continuation fold.

Returns:

  • self (chainable), with self.data holding the merged object.

mod_raw_split_cycle

mod_raw_split_cycle(data_points: List) -> None

Split cycle(s) into several cycles. See :func:cellpy.readers.slicing.mod_raw_split_cycle.

nominal_capacity_as_absolute

nominal_capacity_as_absolute(value=None, specific=None, nom_cap_specifics=None, convert_charge_units=False)

Get the nominal capacity as absolute value.

Delegated to cellpycore.units.nominal_capacity_as_absolute (#451, unit plan Phase 2). A DimensionalityError here usually means the nominal capacity is given in a different unit than the chosen nom_cap_specifics — e.g. nom_cap='1.2 mAh/cm**2' with gravimetric specifics; pass nom_cap_specifics='areal' (or set it on the cell before processing).

print_steps

print_steps()

Print the step table.

register_instrument_readers

register_instrument_readers()

Register instrument readers.

Builds the default factory only when none is set — an injected instrument_factory (#520, DI) is kept as-is. Set self.instrument_factory = None first to force a rebuild.

save

save(filename, force=False, overwrite=None, extension='cellpy', ensure_step_table=None, ensure_summary_table=None, cellpy_file_format=None)

Save the data structure to cellpy-format.

Default on-disk format is v9 (zip-of-parquet + meta.json, .cellpy). Pass cellpy_file_format="hdf5" / "v8" or a .h5 / .hdf5 path to write the legacy HDF5 layout.

Parameters:

  • filename

    (str or pathlib.Path) the name you want to give the file

  • force

    (bool) save a file even if the summary is not made yet (not recommended)

  • overwrite

    (bool) save the new version of the file even if old one exists.

  • extension

    (str) filename extension when filename has no suffix (default cellpy).

  • ensure_step_table

    (bool) make step-table if missing.

  • ensure_summary_table

    (bool) make summary-table if missing.

  • cellpy_file_format

    (str | None) "v9" / "cellpy" (default), or "hdf5" / "v8" for the legacy HDF5 writer. When omitted, inferred from the path suffix (.h5/.hdf5 → hdf5, otherwise v9).

Returns:

  • None

set_cellpy_datadir

set_cellpy_datadir(directory=None)

Set the directory containing .hdf5-files.

Used for setting directory for looking for hdf5-files. A valid directory name is required.

Parameters:

  • directory (str, default: None ) –

    path to hdf5-directory

Examples:

>>> d = CellpyCell()
>>> directory = "MyData/HDF5"
>>> d.set_raw_datadir(directory)

set_col_first staticmethod

set_col_first(df, col_names)

Set selected columns first in a pandas.DataFrame.

This function sets cols with names given in col_names (a list) first in the DataFrame. The last col in col_name will come first (processed last)

set_instrument

set_instrument(instrument=None, model=None, instrument_file=None, unit_test=False, **kwargs)

Set the instrument (i.e. tell cellpy the file-type you use).

Three different modes of setting instruments are currently supported. You can provide the already supported instrument names (see the documentation, e.g. "arbin_res"). You can use the "custom" loader by providing the path to a yaml-file describing the file format. This can be done either by setting instrument to "instrument_name::instrument_definition_file_name", or by setting instrument to "custom" and provide the definition file name through the instrument_file keyword argument. A last option exists where you provide the yaml-file name directly to the instrument parameter. Cellpy will then look into your local instrument folder and search for the yaml-file. Some instrument types also supports a model key-word.

Parameters:

  • instrument

    (str) in ["arbin_res", "maccor_txt",...]. If instrument ends with ".yml" a local instrument file will be used. For example, if instrument is "my_instrument.yml", cellpy will look into the local instruments folders for a file called "my_instrument.yml" and then use LocalTxtLoader to load after registering the instrument. If the instrument name contains a '::' separator, the part after the separator will be interpreted as 'instrument_file'.

  • model

    (str) optionally specify if the instrument loader supports handling several models (some instruments allow for exporting data in slightly different formats depending on the choices made during the export or the model of the instrument, e.g. different number of header lines, different encoding).

  • instrument_file

    (path) instrument definition file,

  • unit_test

    (bool) set to True if you want to print the settings instead of setting them.

  • kwargs (dict, default: {} ) –

    key-word arguments sent to the initializer of the loader class

Note

If you are using a local instrument loader, you will have to register it first to the loader factory.

c = CellpyCell() # this will automatically register the already implemented loaders c.instrument_factory.register_builder(instrument_id, (module_name, path_to_instrument_loader_file))

It is highly recommended using the module_name as the instrument_id.

set_mass

set_mass(mass, validated=None)
Warning

This function is deprecated. Use the setter instead (mass = value).

set_nom_cap

set_nom_cap(nom_cap, validated=None)
Warning

This function is deprecated. Use the setter instead (nom_cap = value).

set_raw_datadir

set_raw_datadir(directory=None)

Set the directory containing .res-files.

Used for setting directory for looking for res-files. A valid directory name is required.

Parameters:

  • directory (str, default: None ) –

    path to res-directory

Examples:

>>> d = CellpyCell()
>>> directory = "MyData/cycler-data"
>>> d.set_raw_datadir(directory)

set_tot_mass

set_tot_mass(mass, validated=None)
Warning

This function is deprecated. Use the setter instead (tot_mass = value).

sget_current

sget_current(cycle, step)

Returns current for cycle, step.

Convenience function; same as issuing::

raw[(raw[cycle_index_header] == cycle) & (raw[step_index_header] == step)][current_header]

Parameters:

  • cycle

    cycle number

  • step

    step number

Returns:

  • pandas.Series or None if empty

sget_step_numbers

sget_step_numbers(cycle, step)

Returns step number for cycle, step.

Convenience function; same as issuing::

raw[(raw[cycle_index_header] == cycle) &
     (raw[step_index_header] == step)][step_index_header]

Parameters:

  • cycle

    cycle number

  • step

    step number (can be a list of several step numbers)

Returns:

  • pandas.Series

sget_steptime

sget_steptime(cycle, step)

Returns step time for cycle, step.

Convenience function; Convenience function; same as issuing::

raw[(raw[cycle_index_header] == cycle) & (raw[step_index_header] == step)][step_time_header]

Parameters:

  • cycle

    cycle number

  • step

    step number

Returns:

  • pandas.Series or None if empty

sget_timestamp

sget_timestamp(cycle, step)

Returns timestamp for cycle, step.

Convenience function; same as issuing::

raw[(raw[cycle_index_header] == cycle) &
     (raw[step_index_header] == step)][timestamp_header]

Parameters:

  • cycle

    cycle number

  • step

    step number (can be a list of several step numbers)

Returns:

  • pandas.Series

sget_voltage

sget_voltage(cycle, step)

Returns voltage for cycle, step.

Convenience function; same as issuing::

raw[(raw[cycle_index_header] == cycle) &
     (raw[step_index_header] == step)][voltage_header]

Parameters:

  • cycle

    cycle number

  • step

    step number

Returns:

  • pandas.Series or None if empty

split

split(cycle=None)

Split experiment into two sub-experiments. See :func:cellpy.readers.slicing.split.

split_many

split_many(base_cycles: Optional[Union[int, List[int]]] = None) -> List[CellpyCell]

Split experiment into several sub-experiments. See :func:cellpy.readers.slicing.split_many.

to_bdf

to_bdf(filename=None, *, cycles=None, last_cycle=None, header_style='preferred', format='csv', extras=False, preprocess_fn=None, bdf_units=None)

Export the raw time-series in Battery Data Format (BDF).

See Battery Data Format <https://github.com/battery-data-alliance/battery-data-format>_ for the full specification.

Parameters:

  • filename

    Output path. If None or extensionless, a default <cell_name>.bdf.<format> (or <filename>.bdf.<format>) is used. An explicit suffix is honoured as-is.

  • cycles

    Optional cycle filter. None exports all cycles; an int exports that single cycle; an iterable of ints exports the listed cycles. Combines with last_cycle.

  • last_cycle

    If given, drop rows whose cycle index exceeds last_cycle.

  • header_style

    "preferred" (default, BDF spec) writes headers like "Test Time / s". "machine" writes machine-readable names like "test_time_second".

  • format

    "csv" (default) or "parquet".

  • extras

    Append columns from data.raw that are not in the BDF column map. False (default) exports only the BDF columns. True appends every unmapped raw column verbatim (no unit conversion, original name preserved). A string or iterable of strings restricts the appended columns to the listed names. The resulting file is no longer strictly BDF-compliant.

  • preprocess_fn

    A function that takes the raw DataFrame and returns a new DataFrame. This function is applied to the raw DataFrame after the cycle filter and before the BDF export.

  • bdf_units

    Optional :class:~cellpy.parameters.internal_settings.CellpyUnits controlling the units written into the BDF file. None (default) emits a strictly BDF-compliant file (A, V, Ah, Wh, s, W, ohm). When set, each attribute on the CellpyUnits overrides the spec target for the corresponding column kind (charge → charge / discharge capacity, energy → charge / discharge energy, etc.); column labels and machine names are rebuilt from the override (e.g. "Charging Capacity / mAh" / "charging_capacity_mah") and values are scaled accordingly via pint. An incompatible unit (e.g. charge="kg") raises :class:ValueError. A file written with overrides is no longer strictly BDF- compliant; this is logged once at INFO level.

    Example::

    from cellpy.parameters.internal_settings import CellpyUnits
    
    # write charge in mAh and current in mA
    bdf_units = CellpyUnits(charge="mAh", current="mA")
    cell.to_bdf("out.bdf.csv", bdf_units=bdf_units)
    

Returns:

  • pathlib.Path: The path that the file was written to.

Raises:

  • ValueError

    If the cell has no raw data, any BDF-required column is missing from data.raw, or bdf_units specifies a unit that cannot be converted from the cell's source unit.

to_cellpy_unit

to_cellpy_unit(value, physical_property)

Convert value to cellpy units.

Parameters:

  • value ((numeric, Quantity or str)) –

    what you want to convert from

  • physical_property (str) –

    What this value is a measure of (must correspond to one of the keys in the CellpyUnits class).

Returns (numeric): the value in cellpy units

to_csv

to_csv(datadir=None, sep=None, cycles=False, raw=True, summary=True, shifted=False, method=None, shift=0.0, last_cycle=None)

Saves the data as .csv file(s). See :func:cellpy.exporters.tabular.to_csv.

to_cycle

to_cycle(cycle: int) -> CellpyCell

Select experiment to cycle number. See :func:cellpy.readers.slicing.to_cycle.

to_excel

to_excel(filename=None, cycles=None, raw=False, steps=True, nice=True, get_cap_kwargs=None, to_excel_kwargs=None)

Saves the data as .xlsx file(s). See :func:cellpy.exporters.tabular.to_excel.

total_time_at_voltage_level

total_time_at_voltage_level(cycles=None, voltage_limit=0.5, sampling_unit='S', at='low')

Experimental method for getting the total time spent at low / high voltage.

Parameters:

  • cycles

    cycle number (all cycles if None).

  • voltage_limit

    voltage limit (default 0.5 V). Can be a tuple (low, high) if at="between".

  • sampling_unit

    sampling unit (default "S") H: hourly frequency T, min: minutely frequency S: secondly frequency L, ms: milliseconds U, us: microseconds N: nanoseconds

  • at (str, default: 'low' ) –

    "low", "high", or "between" (default "low")

unit_scaler_from_raw

unit_scaler_from_raw(unit, physical_property)

Get the conversion factor going from raw to given unit.

Parameters:

  • unit (str) –

    what you want to convert to

  • physical_property (str) –

    what this value is a measure of (must correspond to one of the keys in the CellpyUnits class).

Returns (numeric): conversion factor (scaler)

vacant classmethod

vacant(cell=None)

Create a CellpyCell instance.

Parameters:

  • cell (CellpyCell instance, default: None ) –

    the attributes from the data will be copied to the new CellpyCell instance.

Returns:

  • CellpyCell instance.

with_cellpy_unit

with_cellpy_unit(parameter, as_str=False)

Return quantity as pint.Quantity object.

with_cycles

with_cycles(cycles: Union[int, List[int]]) -> CellpyCell

Select a subset of cycles. See :func:cellpy.readers.slicing.with_cycles.

data_structures

This module contains several of the most important classes used in cellpy.

It also contains functions that are used by readers and utils. And it has the file version definitions.

BaseDbReader

Base class for database readers.

from_batch abstractmethod

from_batch(batch_name: str | None = None, include_key: bool = False, include_individual_arguments: bool = False, **kwargs: Any) -> dict

Get a dictionary with the data from a batch for the journal.

Parameters:

  • batch

    name of the batch.

  • include_key (bool, default: False ) –

    include the key (the cell ids).

  • include_individual_arguments (bool, default: False ) –

    include the individual arguments.

Returns:

  • dict ( dict ) –

    dictionary with the data.

BaseSimpleDbReader

Base class for database readers.

Data

Data(**kwargs)

Object to store data for a cell-test.

This class is used for storing all the relevant data for a cell-test, i.e. all the data collected by the tester as stored in the raw-files, and user-provided metadata about the cell-test.

Attributes:

  • raw_data_files (list) –

    list of FileID objects.

  • raw (DataFrame) –

    raw data.

  • summary (DataFrame) –

    summary data.

  • steps (DataFrame) –

    step data.

  • meta_common (CellpyMetaCommon) –

    common meta-data (authoritative for the active test; see tests).

  • meta_test_dependent (CellpyMetaIndividualTest) –

    test-dependent meta-data (authoritative for the active test; see tests).

  • tests (TestMetaCollection) –

    per-test metadata keyed by test_id. The active test's record is derived on access from the legacy meta boxes above (mutating it does not persist — use set_test_meta / set_cycle_mode or the legacy attributes); records for other test_id values are stored and survive in memory, but are not written to cellpy files in format v8 (full persistence: #510).

  • active_test_id (int) –

    compact grouping key of the active test (0 for a single, unmerged test; matches the engine's test_id column).

  • custom_info (Any) –

    custom meta-data.

  • raw_units (dict) –

    dictionary with units for the raw data.

  • raw_limits (dict) –

    dictionary with limits for the raw data.

  • loaded_from (str) –

    name of the file where the data was loaded from.

active_test_id property

active_test_id: int

Compact grouping key of the active test (0 = single, unmerged).

Matches the engine's test_id convention (raw/steps/summary are stamped 0 for a single test). Distinct from the legacy meta_test_dependent.test_ID, which is the tester-assigned id and stays available as provenance.

empty property

empty

Check if the data object is empty.

has_steps property

has_steps

check if the step table exists

has_summary property

has_summary

check if the summary table exists

tests property

tests: TestMetaCollection

Per-test metadata keyed by test_id (a fresh collection each access).

The active test's record is derived from meta_common / meta_test_dependent (which stay authoritative — the core engine reads them live), so mutating the returned record is a snapshot edit and does not persist. Use :meth:set_test_meta / :meth:set_cycle_mode (or the legacy attributes) to write.

__str__

__str__()

Return a string representation of the Data object.

get_cycle_mode

get_cycle_mode(test_id: Optional[int] = None) -> Optional[str]

cycle_mode for the given test (None = the active test).

populate_defaults

populate_defaults()

Populate the data object with default values.

set_cycle_mode

set_cycle_mode(cycle_mode: str, test_id: Optional[int] = None) -> None

Set cycle_mode for the given test (None = the active test).

The active test writes through to meta_test_dependent.cycle_mode — the attribute the processing engine reads.

set_test_meta

set_test_meta(meta: TestMeta, *, replace: bool = True) -> None

Store a TestMeta record, routed by its test_id.

The active test's record is written back onto the legacy meta boxes (fields without a legacy home, e.g. uuid / source_*, are skipped); records for other test_id values are kept in memory but are not persisted in cellpy-file format v8 (see #510).

FileID

FileID(filename: Union[str, OtherPath] = None, is_db: bool = False)

class for storing information about the raw-data files.

This class is used for storing and handling raw-data file information. It is important to keep track of when the data was extracted from the raw-data files so that it is easy to know if the hdf5-files used for @storing "treated" data is up-to-date.

Attributes:

  • name (str) –

    Filename of the raw-data file.

  • full_name (str) –

    Filename including path of the raw-data file.

  • size (float) –

    Size of the raw-data file.

  • last_modified (datetime) –

    Last time of modification of the raw-data file.

  • last_accessed (datetime) –

    last time of access of the raw-data file.

  • last_info_changed (datetime) –

    st_ctime of the raw-data file.

  • location (str) –

    Location of the raw-data file.

Initialize the FileID class.

last_data_point property writable

last_data_point

Get the last data point.

__str__

__str__()

Return a string representation of the FileID object.

get_last

get_last()

Get last modification time of the file.

get_name

get_name()

Get the filename.

get_raw

get_raw()

Get a list with information about the file.

The returned list contains name, size, last_modified and location.

get_size

get_size()

Get the size of the file.

populate

populate(filename: Union[str, OtherPath])

Finds the file-stats and populates the class with stat values.

Parameters:

  • filename ((str, OtherPath)) –

    name of the file.

InstrumentFactory

InstrumentFactory()

Factory for instrument loaders.

create

create(key: Union[str, None], **kwargs)

Create the instrument loader module and initialize the loader class.

Parameters:

  • key (Union[str, None]) –

    instrument id

  • **kwargs

    sent to the initializer of the loader class.

Returns:

  • instance of loader class.

create_all

create_all(**kwargs)

Create all the instrument loader modules.

Parameters:

  • **kwargs

    sent to the initializer of the loader class.

Returns:

  • dict of instances of loader classes.

query

query(key: str, variable: str) -> Any

performs a get_params lookup for the instrument loader.

Parameters:

  • key (str) –

    instrument id.

  • variable (str) –

    the variable you want to lookup.

Returns:

  • Any

    The value of the variable if the loaders get_params method supports it.

register_builder

register_builder(key: str, builder: Tuple[str, Any], **kwargs) -> None

register an instrument loader module.

Parameters:

  • key (str) –

    instrument id

  • builder (Tuple[str, Any]) –

    (module_name, module_path)

  • **kwargs

    stored in the factory (will be used in the future for allowing to set defaults to the builders to allow for using .query).

unregister_builder

unregister_builder(key: str) -> None

unregister an instrument loader module.

Parameters:

  • key (str) –

    instrument id

PagesDictBase

Bases: TypedDict

Base structure for pages_dict with known journal columns.

PickleProtocol

PickleProtocol(level)

Context for using a specific pickle protocol.

check64bit

check64bit(current_system='python')

checks if you are on a 64-bit platform

collect_capacity_curves

collect_capacity_curves(cell, direction='charge', trim_taper_steps=None, steps_to_skip=None, steptable=None, max_cycle_number=None, **kwargs)

Create a list of pandas.DataFrames, one for each charge step.

The DataFrames are named by its cycle number.

Parameters:

  • cell (``CellpyCell``) –

    object

  • direction (str, default: 'charge' ) –
  • trim_taper_steps (integer, default: None ) –

    number of taper steps to skip (counted from the end, i.e. 1 means skip last step in each cycle).

  • steps_to_skip (list, default: None ) –

    step numbers that should not be included.

  • steptable (``pandas.DataFrame``, default: None ) –

    optional steptable.

  • max_cycle_number (int, default: None ) –

    only select cycles up to this value.

Returns:

  • list of pandas.DataFrames,

  • list of cycle numbers,

  • minimum voltage value,

  • maximum voltage value

convert_from_simple_unit_label_to_string_unit_label

convert_from_simple_unit_label_to_string_unit_label(k, v)

Convert from simple unit label to string unit label.

find_all_instruments

find_all_instruments(name_contains: Optional[str] = None) -> Dict[str, Tuple[str, pathlib.Path]]

finds all the supported instruments

generate_default_factory

generate_default_factory()

This function searches for all available instrument readers and registers them in an InstrumentFactory instance.

Returns:

  • InstrumentFactory

group_by_interpolate

group_by_interpolate(df, x=None, y=None, group_by=None, number_of_points=100, tidy=False, individual_x_cols=False, header_name='Unit', dx=10.0, generate_new_x=True)

Do a pandas.DataFrame.group_by and perform interpolation for all groups.

This function is a wrapper around an internal interpolation function in cellpy (that uses scipy.interpolate.interp1d) that combines doing a group-by operation and interpolation.

Parameters:

  • df (DataFrame) –

    the dataframe to morph.

  • x (str, default: None ) –

    the header for the x-value (defaults to normal header step_time_txt) (remark that the default group_by column is the cycle column, and each cycle normally consist of several steps (so you risk interpolating / merging several curves on top of each other (not good)).

  • y (str, default: None ) –

    the header for the y-value (defaults to normal header voltage_txt).

  • group_by (str, default: None ) –

    the header to group by (defaults to normal header cycle_index_txt)

  • number_of_points (int, default: 100 ) –

    if generating new x-column, how many values it should contain.

  • tidy (bool, default: False ) –

    return the result in tidy (i.e. long) format.

  • individual_x_cols (bool, default: False ) –

    return as xy xy xy ... data.

  • header_name (str, default: 'Unit' ) –

    name for the second level of the columns (only applies for xy xy xy ... data) (defaults to "Unit").

  • dx (float, default: 10.0 ) –

    if generating new x-column and number_of_points is None or zero, distance between the generated values.

  • generate_new_x (bool, default: True ) –

    create a new x-column by using the x-min and x-max values from the original dataframe where the method is set by the number_of_points key-word:

    1) if number_of_points is not None (default is 100)::

        new_x = np.linspace(x_max, x_min, number_of_points)
    

    2) else::

        new_x = np.arange(x_max, x_min, dx)
    

pandas.DataFrame with interpolated x- and y-values. The returned

  • dataframe is in tidy (long) format for tidy=True.

humanize_bytes

humanize_bytes(b, precision=1)

Return a humanized string representation of a number of b.

identify_last_data_point

identify_last_data_point(data)

Find the last data point and store it in the fid instance

instrument_configurations

instrument_configurations(search_text: str = '') -> Dict[str, Any]

This function returns a dictionary with information about the available instrument loaders and their models.

Parameters:

  • search_text (str, default: '' ) –

    string to search for in the instrument names.

Returns:

  • dict ( Dict[str, Any] ) –

    nested dictionary with information about the available instrument loaders and their models.

interpolate_y_on_x

interpolate_y_on_x(df, x=None, y=None, new_x=None, dx=10.0, number_of_points=None, direction=1, **kwargs)

Interpolate a column based on another column.

Parameters:

  • df

    DataFrame with the (cycle) data.

  • x

    Column name for the x-value (defaults to the step-time column).

  • y

    Column name for the y-value (defaults to the voltage column).

  • new_x (numpy array or None, default: None ) –

    Interpolate using these new x-values instead of generating x-values based on dx or number_of_points.

  • dx

    step-value (defaults to 10.0)

  • number_of_points

    number of points for interpolated values (use instead of dx and overrides dx if given).

  • direction ((-1, 1), default: 1 ) –

    if direction is negative, then invert the x-values before interpolating.

  • **kwargs

    arguments passed to scipy.interpolate.interp1d

DataFrame with interpolated y-values based on given or

  • generated x-values.

interpolate_y_on_x_per_monotonic_segments

interpolate_y_on_x_per_monotonic_segments(df, x=None, y=None, dx=10.0, number_of_points=None, direction=1, max_segments=100, **kwargs)

Interpolate y on x per strictly monotonic segment, then concatenate.

When a curve has multiple steps (e.g. CC + taper), x may not be strictly monotonic (e.g. constant voltage during taper). scipy.interp1d requires strictly increasing x, so interpolating the whole curve drops steps or produces artefacts. This helper splits the dataframe into segments where x is strictly monotonic, interpolates each segment, and concatenates.

Many segments can occur with noisy x-data: every small reversal (x[i] <= x[i-1]) starts a new segment, so O(n) segments are possible. That would mean many calls to interpolate_y_on_x (slow) and many small DataFrames (memory). If the segment count exceeds max_segments, the function returns the dataframe unchanged and logs a warning.

Parameters:

  • df

    DataFrame with the (cycle) data.

  • x

    Column name for the x-value.

  • y

    Column name for the y-value.

  • dx

    step-value for interpolation.

  • number_of_points

    number of points (overrides dx if given).

  • direction ((-1, 1), default: 1 ) –

    1 = x must be strictly increasing, -1 = strictly decreasing.

  • max_segments

    if the number of monotonic segments exceeds this, return df unchanged and log a warning (default 100). Set to None for no limit.

  • **kwargs

    passed to interpolate_y_on_x.

Returns:

  • DataFrame with interpolated (x, y) preserving all segments, or df unchanged

  • if segment count exceeds max_segments.

xldate_as_datetime

xldate_as_datetime(xldate, datemode=0, option='to_datetime')

Converts a xls date stamp to a more sensible format.

Parameters:

  • xldate ((str, int)) –

    date stamp in Excel format.

  • datemode (int, default: 0 ) –

    0 for 1900-based, 1 for 1904-based.

  • option (str, default: 'to_datetime' ) –

    option in ("to_datetime", "to_float", "to_string"), return value

Returns:

  • datetime (datetime object, float, or string).

Metadata resolution

meta_resolver

Layered metadata resolution with provenance (metadata plan Step 3, #562).

Metadata about a cell arrives from four places at once — what the user passed in, what the batch journal or database says, what the instrument wrote into the file, and what the configuration defaults to. Until now they were merged ad hoc at whichever call site happened to run first, which is why "why is my mass 1.0?" was not answerable without reading the code.

The precedence is fixed and boring, most specific first::

kwargs  >  journal / db  >  raw file  >  config defaults

and every resolved field records which layer won. That record is the point: a batch run that silently used a default mass for one cell out of forty is otherwise invisible until the capacities look strange.

A layer only contributes a field if it actually has a value for it — None means "I don't know", not "make it None". So a journal that knows the mass but not the nominal capacity lets the file's nominal capacity through.

Layer

Bases: IntEnum

Where a metadata value came from. Higher wins.

MetaResolver

MetaResolver(target_fields: Iterable[str])

Merge metadata layers into one object, remembering who won.

Parameters:

  • target_fields (Iterable[str]) –

    the field names the result may carry. Anything a layer offers that is not in here is ignored — a journal column that happens to share a name with nothing in particular should not invent a metadata field.

resolve

resolve(*, kwargs: Any = None, journal: Any = None, raw_file: Any = None, config_defaults: Any = None, into: Any = None) -> tuple[Any, Resolution]

Resolve the layers onto into.

Parameters:

  • kwargs (Any, default: None ) –

    what the user passed explicitly. Wins over everything.

  • journal (Any, default: None ) –

    batch journal or database row.

  • raw_file (Any, default: None ) –

    the loader's draft — what the instrument file knew.

  • config_defaults (Any, default: None ) –

    the session's ScienceDefaults-style values.

  • into (Any, default: None ) –

    the object to populate (mutated and returned). Required.

Returns:

Resolution dataclass

Resolution(sources: dict[str, Layer] = dict())

The outcome of resolving one metadata object.

explain

explain() -> str

Human-readable per-field provenance, for logs and debugging.

fields_from

fields_from(layer: Layer) -> tuple[str, ...]

Every field this layer won.

source_of

source_of(name: str) -> Layer | None

Which layer supplied name, or None if nothing did.

resolve_cell_meta

resolve_cell_meta(cell_meta: Any, *, kwargs: Mapping[str, Any] | None = None, journal: Any = None, draft: Any = None, config_defaults: Any = None) -> tuple[Any, Resolution]

Resolve a CellMeta: the cell's own properties (mass, area, …).

resolve_from_loader_result

resolve_from_loader_result(result: Any, *, source: Any, source_type: str, kwargs: Mapping[str, Any] | None = None, journal: Any = None, config_defaults: Any = None) -> tuple[Any, Any, Resolution, Resolution]

Turn a loader's drafts into populated metadata, with provenance.

This is the ingestion-side entry point: it takes what the loader learned from the file, resolves it against the other layers, and stamps the provenance the loader is not allowed to fill itself.

Parameters:

  • result (Any) –

    a LoaderResult carrying draft test_meta/cell_meta.

  • source (Any) –

    the file the result came from.

  • source_type (str) –

    the loader/instrument name.

  • kwargs (Mapping[str, Any] | None, default: None ) –

    explicit user values.

  • journal (Any, default: None ) –

    batch journal or database row.

  • config_defaults (Any, default: None ) –

    session ScienceDefaults.

Returns:

resolve_test_meta

resolve_test_meta(test_meta: Any, *, kwargs: Mapping[str, Any] | None = None, journal: Any = None, draft: Any = None, config_defaults: Any = None) -> tuple[Any, Resolution]

Resolve a TestMeta: what this particular run was.

science_defaults_for_cell

science_defaults_for_cell(defaults: Any) -> dict[str, Any]

Map the config's ScienceDefaults onto CellMeta field names.

The configuration spells them default_mass / default_nom_cap (historically prms.Materials.*); the metadata model spells them mass / nom_cap. Translating here keeps the resolver ignorant of both.

provenance

Provenance stamping — the framework's half of metadata (#562).

A loader knows what the file says. Only the framework knows where the file came from, when it was read and what identity the resulting cell was given, so those fields are stamped here and a draft that arrives carrying them is a contract violation (architecture plan §5.1.3, enforced by the conformance kit).

Two identifiers, deliberately different:

source_uuid A stable hash of file identity. The same file yields the same value on every load and on every machine, so "have I already loaded this?" and "is this the same raw file the cellpy file was built from?" are answerable.

uuid Identity of this cell object, minted once at first load and then preserved through save, load and merge. Two loads of the same file are two cells and get different values.

file_identity_hash

file_identity_hash(source: Path | str) -> str | None

A stable identity hash for a raw file, or None if unreadable.

Deliberately not a full-content checksum — see _IDENTITY_BYTES. Two different files sharing both a 1 MB head and an exact byte size would collide; that is acceptable for provenance, and it is not used as a security or integrity control.

new_cell_uuid

new_cell_uuid() -> str

Mint the identity for a freshly loaded cell.

Preserved through save/load/merge — see preserve_cell_uuid.

preserve_cell_uuid

preserve_cell_uuid(target: Any, *sources: Any) -> str | None

Carry an existing cell uuid onto target, or mint one.

Merging keeps the first uuid it finds rather than minting a new one: the merged object is a continuation of that cell, and a fresh identity would break the link back to files already saved from it.

stamp_provenance

stamp_provenance(test_meta: Any, *, source: Path | str, source_type: str, source_kind: str = 'file', raw_file_names: list[str] | None = None, loaded_datetime: datetime | None = None) -> Any

Fill the provenance fields on a draft TestMeta.

Parameters:

  • test_meta (Any) –

    the loader's draft, mutated in place.

  • source (Path | str) –

    the raw file this test came from.

  • source_type (str) –

    the instrument/loader name ("maccor_txt").

  • source_kind (str, default: 'file' ) –

    "file" or "db".

  • raw_file_names (list[str] | None, default: None ) –

    override for multi-file loads; defaults to source.

  • loaded_datetime (datetime | None, default: None ) –

    override for reproducible tests; defaults to now, UTC.

Returns:

  • Any

    The same object, for chaining.

journal_layer

The batch journal as a metadata source (metadata plan Step 6, #563).

The journal has always been write-only as far as metadata is concerned: batch builds its pages from loaded cells (batch.py), and nothing ever read a row back to say "this is what we know about that cell". So a mass corrected in the journal was corrected for the report but not for the cell, and the two could disagree indefinitely.

This module supplies the missing direction — a journal row as a :class:~cellpy.readers.meta_resolver.MetaResolver layer, sitting where the plan puts it: below explicit user arguments, above whatever the instrument file happened to contain.

It is a source, not a store (plan Step 6). Nothing here writes journal pages.

journal_row_for

journal_row_for(pages: Any, cell_id: Any) -> dict[str, Any] | None

Pull one row out of a journal pages frame as a plain dict.

Returns None when the cell is not in the journal — a perfectly ordinary situation (loading a file that no batch has catalogued), not an error.

to_cell_meta

to_cell_meta(row: Mapping[str, Any]) -> dict[str, Any]

Extract CellMeta values from one journal page row.

Parameters:

  • row (Mapping[str, Any]) –

    a mapping of journal column → value (e.g. pages.loc[cell_id] as a dict, or any row-like mapping).

Returns:

  • dict[str, Any]

    A {field: value} dict suitable as the resolver's journal layer.

  • dict[str, Any]

    Columns the journal left blank are omitted rather than passed as None,

  • dict[str, Any]

    so the resolver's "None means I don't know" rule is never even reached.

to_test_meta

to_test_meta(row: Mapping[str, Any]) -> dict[str, Any]

Extract TestMeta values from one journal page row.

Named to_test_meta rather than test_meta_from_...: any name starting with test_ is collected as a test case by pytest wherever it is imported, which turns a helper into a spurious failing test.