# Path: cellpy/exceptions.py
# class NullData(Error):
#     """Raised when required data is missing (e.g. voltage = None or summary_frames are missing)"""
# 
#     pass
# 
# Path: cellpy/readers/core.py
# def collect_capacity_curves(
#     data,
#     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.
# 
#     Input: CellpyData
#     Returns: list of pandas.DataFrames,
#         list of cycle numbers,
#         minimum voltage value,
#         maximum voltage value"""
# 
#     # TODO: should allow for giving cycle numbers as input (e.g. cycle=[1, 2, 10]
#     #  or cycle=2), not only max_cycle_number
# 
#     minimum_v_value = np.Inf
#     maximum_v_value = -np.Inf
#     charge_list = []
#     cycles = kwargs.pop("cycle", None)
# 
#     if cycles is None:
#         cycles = data.get_cycle_numbers()
# 
#     if max_cycle_number is None:
#         max_cycle_number = max(cycles)
# 
#     for cycle in cycles:
#         if cycle > max_cycle_number:
#             break
#         try:
#             if direction == "charge":
#                 q, v = data.get_ccap(
#                     cycle,
#                     trim_taper_steps=trim_taper_steps,
#                     steps_to_skip=steps_to_skip,
#                     steptable=steptable,
#                 )
#             else:
#                 q, v = data.get_dcap(
#                     cycle,
#                     trim_taper_steps=trim_taper_steps,
#                     steps_to_skip=steps_to_skip,
#                     steptable=steptable,
#                 )
# 
#         except NullData as e:
#             logging.warning(e)
#             d = pd.DataFrame()
#             d.name = cycle
#             charge_list.append(d)
#         else:
#             d = pd.DataFrame({"q": q, "v": v})
#             # d.name = f"{cycle}"
#             d.name = cycle
#             charge_list.append(d)
#             v_min = v.min()
#             v_max = v.max()
#             if v_min < minimum_v_value:
#                 minimum_v_value = v_min
#             if v_max > maximum_v_value:
#                 maximum_v_value = v_max
#     return charge_list, cycles, minimum_v_value, maximum_v_value


import os
import logging
import warnings
import numpy as np
import pandas as pd
import pandas as pd
    import matplotlib.pyplot as plt
    import pandas as pd
from scipy import stats
from scipy.interpolate import interp1d
from scipy.signal import savgol_filter
from scipy.integrate import simps
from scipy.ndimage.filters import gaussian_filter1d
from cellpy.exceptions import NullData
from cellpy.readers.core import collect_capacity_curves
    from cellpy import cellreader
    from cellpy import cellreader
        >>> from cellpy.utils import ica
        >>> charge_ica_df, dcharge_ica_df = ica.ica_frames(my_cell)
        >>> charge_ica_df.plot(x=("voltage", "v"))

    """
    cycle = kwargs.pop("cycle", None)
    if cycle and not isinstance(cycle, (list, tuple)):
        cycle = [cycle]

    charge_dfs, cycles, minimum_v, maximum_v = collect_capacity_curves(
        cell,
        direction="charge",
        trim_taper_steps=trim_taper_steps,
        steps_to_skip=steps_to_skip,
        steptable=steptable,
        max_cycle_number=max_cycle_number,
        cycle=cycle,
    )
    logging.debug(f"retrieved {len(charge_dfs)} charge cycles")
    # charge_df = pd.concat(
    # charge_dfs, axis=1, keys=[k.name for k in charge_dfs])

    ica_charge_dfs = _make_ica_charge_curves(
        charge_dfs, cycles, minimum_v, maximum_v, **kwargs
    )

    ica_charge_df = pd.concat(
        ica_charge_dfs, axis=1, keys=[k.name for k in ica_charge_dfs]
    )


# Path: cellpy/exceptions.py
# class NullData(Error):
#     """Raised when required data is missing (e.g. voltage = None or summary_frames are missing)"""
# 
#     pass
# 
# Path: cellpy/readers/core.py
# def collect_capacity_curves(
#     data,
#     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.
# 
#     Input: CellpyData
#     Returns: list of pandas.DataFrames,
#         list of cycle numbers,
#         minimum voltage value,
#         maximum voltage value"""
# 
#     # TODO: should allow for giving cycle numbers as input (e.g. cycle=[1, 2, 10]
#     #  or cycle=2), not only max_cycle_number
# 
#     minimum_v_value = np.Inf
#     maximum_v_value = -np.Inf
#     charge_list = []
#     cycles = kwargs.pop("cycle", None)
# 
#     if cycles is None:
#         cycles = data.get_cycle_numbers()
# 
#     if max_cycle_number is None:
#         max_cycle_number = max(cycles)
# 
#     for cycle in cycles:
#         if cycle > max_cycle_number:
#             break
#         try:
#             if direction == "charge":
#                 q, v = data.get_ccap(
#                     cycle,
#                     trim_taper_steps=trim_taper_steps,
#                     steps_to_skip=steps_to_skip,
#                     steptable=steptable,
#                 )
#             else:
#                 q, v = data.get_dcap(
#                     cycle,
#                     trim_taper_steps=trim_taper_steps,
#                     steps_to_skip=steps_to_skip,
#                     steptable=steptable,
#                 )
# 
#         except NullData as e:
#             logging.warning(e)
#             d = pd.DataFrame()
#             d.name = cycle
#             charge_list.append(d)
#         else:
#             d = pd.DataFrame({"q": q, "v": v})
#             # d.name = f"{cycle}"
#             d.name = cycle
#             charge_list.append(d)
#             v_min = v.min()
#             v_max = v.max()
#             if v_min < minimum_v_value:
#                 minimum_v_value = v_min
#             if v_max > maximum_v_value:
#                 maximum_v_value = v_max
#     return charge_list, cycles, minimum_v_value, maximum_v_value


# Path: cellpy/utils/ica.py
import os
import logging
import warnings
import numpy as np
import pandas as pd
import pandas as pd
    import matplotlib.pyplot as plt
    import pandas as pd
from scipy import stats
from scipy.interpolate import interp1d
from scipy.signal import savgol_filter
from scipy.integrate import simps
from scipy.ndimage.filters import gaussian_filter1d
from cellpy.exceptions import NullData
from cellpy.readers.core import collect_capacity_curves
    from cellpy import cellreader
    from cellpy import cellreader

        >>> from cellpy.utils import ica
        >>> charge_ica_df, dcharge_ica_df = ica.ica_frames(my_cell)
        >>> charge_ica_df.plot(x=("voltage", "v"))

    """
    cycle = kwargs.pop("cycle", None)
    if cycle and not isinstance(cycle, (list, tuple)):
        cycle = [cycle]

    charge_dfs, cycles, minimum_v, maximum_v = collect_capacity_curves(
        cell,
        direction="charge",
        trim_taper_steps=trim_taper_steps,
        steps_to_skip=steps_to_skip,
        steptable=steptable,
        max_cycle_number=max_cycle_number,
        cycle=cycle,
    )
    logging.debug(f"retrieved {len(charge_dfs)} charge cycles")
    # charge_df = pd.concat(
    # charge_dfs, axis=1, keys=[k.name for k in charge_dfs])

    ica_charge_dfs = _make_ica_charge_curves(
        charge_dfs, cycles, minimum_v, maximum_v, **kwargs
    )

    ica_charge_df = pd.concat(
        ica_charge_dfs, axis=1, keys=[k.name for k in ica_charge_dfs]
    )


    dcharge_dfs, cycles, minimum_v, maximum_v = collect_capacity_curves(