1. Settings


In [ ]:
%load_ext autoreload
%autoreload 2

In [ ]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

import cellpy
from cellpy import log
from cellpy import cellreader
from cellpy import prms
from cellpy import prmreader
from cellpy.utils import batch
#import holoviews as hv

%matplotlib inline
#hv.extension('bokeh')

In [ ]:
log.setup_logging(default_level="DEBUG")

In [ ]:
## Uncomment this and run for checking your cellpy parameters.
# prmreader.info()

In [ ]:
filepath = r"C:\Scripting\MyFiles\development_cellpy\dev_data\arbin\2019_types.res"



filepath = [
    
    r"C:\Scripting\MyFiles\development_cellpy\dev_data\arbin\20181126_cen41_02_cc_01.res",
    r"C:\Scripting\MyFiles\development_cellpy\dev_data\arbin\20181126_cen41_02_cc_02.res",
    r"C:\Scripting\MyFiles\development_cellpy\dev_data\arbin\20181126_cen41_02_cc_03.res",
    r"C:\Scripting\MyFiles\development_cellpy\dev_data\arbin\20181126_cen41_02_cc_04.res",
    r"C:\Scripting\MyFiles\development_cellpy\dev_data\arbin\20181126_cen41_02_cc_05.res",
    r"C:\Scripting\MyFiles\development_cellpy\dev_data\arbin\20181126_cen41_02_cc_06.res",
]



filepath2 = filepath[0]





m = 0.374433
outfilepath = r"C:\Scripting\MyFiles\development_cellpy\dev_data\arbin\2019_types.h5"
prms.Paths.rawdatadir =  r"C:\ExperimentalData\BatteryTestData\Arbin\RAW"

In [ ]:
cell = cellreader.CellpyData()
cell.from_raw(filepath)

cell2 = cellreader.CellpyData()
cell2.from_raw(filepath2)

In [ ]:
cell.set_mass(m)
cell2.set_mass(m)

In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]:
cell.make_step_table()
cell2.make_step_table()

In [ ]:
cell.make_summary()
cell2.make_summary()

In [ ]:
dataset = cell.dataset
dataset2 = cell2.dataset

In [ ]:


In [ ]:


In [ ]:


In [ ]:
dataset.summary

In [ ]:
dataset.steps

In [ ]:
dataset.raw

In [ ]:
dataset.raw.describe()

In [ ]:
dataset.raw.dtypes

In [ ]:
dataset2.raw.dtypes

In [ ]:
dataset.raw.Step_Index.unique()

In [ ]:
dataset2.raw.Step_Index.unique()

In [ ]:


In [ ]:
dataset.summary.dtypes

In [ ]:
dataset.steps.dtypes

In [ ]:
cell.save(outfilepath)

In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]:

4. Looking at the data

Summaries


In [ ]:
# Plot the charge capacity and the C.E. (and resistance) vs. cycle number (standard plot)
b.plot_summaries()

In [ ]:
# Show the journal pages
# b.experiment.journal.pages.head()

In [ ]:
# Show the most important part of the journal pages
b.view

In [ ]:
# b.experiment.status()

In [ ]:
# b.summaries.head()

Cycles


In [ ]:
%%opts Curve (color=hv.Palette('Magma'))
voltage_curves = dict()
for label in b.experiment.cell_names:
    d = b.experiment.data[label]
    curves = d.get_cap(label_cycle_number=True, interpolated=True, number_of_points=100)
    curve = hv.Curve(curves, kdims=["capacity", "cycle"], vdims="voltage").groupby("cycle").overlay().opts(show_legend=False)
    voltage_curves[label] = curve
NdLayout = hv.NdLayout(voltage_curves, kdims='label').cols(3)
NdLayout

In [ ]:
%%opts Curve (color=hv.Palette('Magma'))
ocv_curves = dict()
for label in b.experiment.cell_names:
    d = b.experiment.data[label]
    ocv_data = d.get_ocv(direction="up", number_of_points=40)
    ocv_curve = hv.Curve(ocv_data, kdims=["Step_Time", "Cycle_Index"], vdims="Voltage").groupby("Cycle_Index").overlay().opts(show_legend=False)
    ocv_curves[label] = ocv_curve

NdLayout = hv.NdLayout(ocv_curves, kdims='label').cols(3)
NdLayout

Selecting specific cells and investigating them


In [ ]:
# This will show you all your cell names
cell_labels = b.experiment.cell_names
cell_labels

In [ ]:
# This is how to select the data (CellpyData-objects)
data1 = b.experiment.data["20160805_test001_45_cc"]
data2 = b.experiment.data["20160805_test001_47_cc"]

Let's see how the smoothing (interpolation) method works


In [ ]:
# get voltage curves
df_cycles1 = data1.get_cap(method="back-and-forth",categorical_column=True, label_cycle_number=True, interpolated=False)

In [ ]:
# get interpolated voltage curves
df_cycles2 = data1.get_cap(
    method="back-and-forth", categorical_column=True, label_cycle_number=True, interpolated=True,
    dx=0.1, number_of_points=100,
)

In [ ]:
%%opts Scatter [width=600] (color="red", alpha=0.9, size=12)
single_curve = hv.Curve(df_cycles1, kdims=["capacity", "cycle"], vdims="voltage", label="not-smoothed").groupby("cycle")
single_scatter = hv.Scatter(df_cycles2, kdims=["capacity", "cycle"], vdims="voltage", label="smoothed").groupby("cycle")
single_scatter * single_curve

Using hvplot for plotting summaries

You can for example use hvplot for looking more at your summary data


In [ ]:
import hvplot.pandas

In [ ]:
# hvplot does not like infinities
s = b.summaries.replace([np.inf, -np.inf], np.nan)

In [ ]:
layout = s["coulombic_efficiency"].hvplot() + s["discharge_capacity"].hvplot() * s["charge_capacity"].hvplot()
layout.cols(1)

In [ ]:
s["cumulated_coulombic_efficiency"].hvplot()

Looking more in-depth and utilising advanced features

OCV relaxation points

Picking out 5 points on each OCV relaxation curve (distributed by last, last/2, last/2/2, ..., first).


In [ ]:
from cellpy.utils.batch_tools.batch_analyzers import OCVRelaxationAnalyzer
print(" analyzing ocv relaxation data ".center(80, "-"))
analyzer = OCVRelaxationAnalyzer()
analyzer.assign(b.experiment)
analyzer.direction = "down"
analyzer.do()
dfs = analyzer.last
df_file_one, _df_file_two = dfs

# keeping only the columns with voltages
ycols = [col for col in df_file_one.columns if col.find("point")>=0]

# removing the first ocv rlx (relaxation before starting cycling)
df = df_file_one.iloc[1:, :]
# tidy format
df = df.melt(id_vars = "cycle", var_name="point", value_vars=ycols, value_name="voltage")
curve = hv.Curve(df, kdims=["cycle", "point"], vdims="voltage").groupby("point").overlay().opts(xlim=(1,10), width=800)
scatter = hv.Scatter(df, kdims=["cycle", "point"], vdims="voltage").groupby("point").overlay().opts(
    xlim=(1,10), ylim=(0.7,1)
)

In [ ]:
layout = hv.Layout(curve * scatter)
layout.cols(1)

Looking closer at some summary-plots


In [ ]:
b.summary_columns

In [ ]:
discharge_capacity = b.summaries.discharge_capacity
charge_capacity = b.summaries.charge_capacity
coulombic_efficiency = b.summaries.coulombic_efficiency
ir_charge = b.summaries.ir_charge

In [ ]:
fig, (ax1, ax2) = plt.subplots(2, 1)
ax1.plot(discharge_capacity)
ax1.set_ylabel("capacity ")
ax2.plot(ir_charge)
ax2.set_xlabel("cycle")
ax2.set_ylabel("resistance")

5. Checking for more details per cycle

A. pick the CellpyData object for one of the cells


In [ ]:
# Lets check what cells we have
cell_labels = b.experiment.cell_names
cell_labels

In [ ]:
# OK, then I choose one of them
data = b.experiment.data["20160805_test001_45_cc"]

B. Get some voltage curves for some cycles and plot them

The method get_cap can be used to extract voltage curves.


In [ ]:
cap = data.get_cap(categorical_column=True)
cap.head()

In [ ]:
fig, ax = plt.subplots()
ax.plot(cap.capacity, cap.voltage)
ax.set_xlabel("capacity")
ax.set_ylabel("voltage")

In [ ]:
cv = data.get_cap(method="forth")
fig, ax = plt.subplots()
ax.set_xlabel("capacity")
ax.set_ylabel("voltage")
ax.plot(cv.capacity, cv.voltage)

In [ ]:
c4 = data.get_cap(cycle=4, method="forth-and-forth")
c10 = data.get_cap(cycle=10, method="forth-and-forth")
fig, ax = plt.subplots()
ax.set_xlabel("capacity")
ax.set_ylabel("voltage")
ax.plot(c4.capacity,c4.voltage, "ro", label="cycle 4")
ax.plot(c10.capacity,c10.voltage, "bs", label="cycle 22")
ax.legend();

Looking at some dqdv data

Get capacity cycles and make dqdv using the ica module


In [ ]:
from cellpy.utils import ica
v4, dqdv4 = ica.dqdv_cycle(
    data.get_cap(
        4, 
        categorical_column=True, 
        method = "forth-and-forth")
)

v10, dqdv10 = ica.dqdv_cycle(
    data.get_cap(
        10, 
        categorical_column=True, 
        method = "forth-and-forth")
)

plt.plot(v4,dqdv4, label="cycle 4")
plt.plot(v10, dqdv10, label="cycle 10")
plt.legend();

Put it in a for-loop for plotting many ica plots


In [ ]:
fig, ax = plt.subplots()
for cycle in data.get_cycle_numbers():
    d = data.get_cap(
            cycle, 
            categorical_column=True, 
            method = "forth-and-forth"
        )
    if not d.empty:
        v, dqdv = ica.dqdv_cycle(d)
        ax.plot(v, dqdv)
    else:
        print(f"cycle {cycle} seems to be missing or corrupted")

Get all the dqdv data in one go


In [ ]:
hv.extension('bokeh')

In [ ]:
tidy_ica = ica.dqdv_frames(data)
cycles = list(range(1,3)) + [10, 11, 12, 15]
tidy_ica = tidy_ica.loc[tidy_ica.cycle.isin(cycles), :]

In [ ]:
%%opts Curve [xlim=(0,1)] (color=hv.Palette('Magma'), alpha=0.9) NdOverlay [legend_position='right', width=800, height=500]
curve4 = (hv.Curve(tidy_ica, kdims=['voltage'], vdims=['dq', 'cycle'], label="Incremental capacity plot")
          .groupby("cycle")
          .overlay()
         )
curve4

In [ ]: