GITT analysis

GITT analysis#

In this notebook we will use cellpy to extract the open circuit voltages (OCV) from a GITT measurement. The extracted OCVs will be plotted, and the results saved in .csv format.”

[1]:
import pathlib
import pandas as pd
import matplotlib.pyplot as plt

import cellpy
from cellpy.utils import plotutils

Set filepath and load the datafile:

[2]:
filedir = pathlib.Path("data")  # foldername within the same directory
c = cellpy.get(filedir / "out" / "20210210_FC.h5")

Produce an overview plot to identify cycle numbers for the GITT experiment (for an interactive version of this plot, you have to have plotly installed):

[3]:
plotutils.cycle_info_plot(c, cycle=list(range(2, 7)))

OCV extraction#

From the overview plot above, we can identify the GITT cycles to be cycle number 4 and 5. In the following, we will focus on cycle 5 only.

For further analysis, we create the step table, called steps, a dataframe that contains a lot ofnformation on all the cycle steps for the cell.

In the following, we apply several filters to steps, to eventually extract OCV voltages and corresponding capacities:

  1. ``steps_cycle``: Extract the rows specifically for the selected GITT cycle (here: cycle Nr 5).

NB: For simplicity, steps_cycle only contains rows relevant for further analysis, i.e. “cycle”, “step””charge_last”, “discharge_last”, “voltage_first” ,”voltage_last”, “type”.”

[4]:
GITT_cycle = 5
c.make_step_table(all_steps=True)
steps = c.data.steps
steps_cycle = steps.loc[
    (steps.cycle == GITT_cycle),
    [
        "cycle",
        "step",
        "charge_last",
        "discharge_last",
        "voltage_first",
        "voltage_last",
        "type",
    ],
]

Taking a closer look at the created steps_cycle dataframe:

  • steps_cycle.head(10) to view the first 10 rows

  • steps_cycle.tail(10) to view the last 10 rows

[5]:
steps_cycle.tail(10)
[5]:
cycle step charge_last discharge_last voltage_first voltage_last type
755 5 8 0.003358 0.003258 3.212396 3.343531 ocvrlx_up
756 5 7 0.003358 0.003294 3.330632 3.139919 discharge
757 5 8 0.003358 0.003294 3.162645 3.314970 ocvrlx_up
758 5 7 0.003358 0.003330 3.302993 3.080647 discharge
759 5 8 0.003358 0.003330 3.102759 3.283338 ocvrlx_up
760 5 7 0.003358 0.003366 3.272282 3.008170 discharge
761 5 8 0.003358 0.003366 3.029361 3.246485 ocvrlx_up
762 5 7 0.003358 0.003392 3.233587 2.999878 discharge
763 5 10 0.003358 0.003392 3.010627 3.010627 ir
764 5 11 0.003358 0.003392 3.037038 3.228980 ocvrlx_up
  1. To extract the OCV voltages, we then filter the steps_cycle dataframe for

    • the OCV relaxation steps on discharge, steps_ocv_dch, of type oxvrlx_up (and rest), corresponding to step==3, and

    • the OCV relaxation steps on charge steps_ocv_cha, of type oxvrlx_down (and rest), corresponding to step==8. Thereby we obtain two new dataframes

[6]:
steps_ocv_cha = steps_cycle.loc[steps_cycle.step == 3]
steps_ocv_dch = steps_cycle.loc[steps_cycle.step == 8]
[7]:
steps_ocv_cha.head(5)
[7]:
cycle step charge_last discharge_last voltage_first voltage_last type
390 5 3 0.000036 0.0 3.512440 3.487564 rest
392 5 3 0.000072 0.0 3.518582 3.494320 rest
394 5 3 0.000109 0.0 3.524724 3.499848 rest
396 5 3 0.000145 0.0 3.530559 3.505991 rest
398 5 3 0.000181 0.0 3.537315 3.513054 rest

The voltages at the end of these steps (voltage_last), contain the (pseudo-) OCV voltages:

[8]:
V_cha = steps_ocv_cha.voltage_last.reset_index(drop=True)
V_dch = steps_ocv_dch.voltage_last.reset_index(drop=True)
cap_cha = (
    steps_ocv_cha.charge_last.reset_index(drop=True) * 1000
)  # *1000 to convert to mAh
cap_dch = (
    steps_ocv_dch.discharge_last.reset_index(drop=True) * 1000
)  # *1000 to convert to mAh

To plot our results, we additionally get the entire voltage vs capacity curves for the selected GITT cycle, employing the .get_ccap and .get_dcap methods. The cell mass is used to convert from gravimetric capacity (mAh/g) to capacity (mAh).

[9]:
c.make_step_table(all_steps=False)
ccap = c.get_ccap(cycle=GITT_cycle)
dcap = c.get_dcap(cycle=GITT_cycle)
mass = c.get_mass()  # in mg
[10]:
fig, ax = plt.subplots()
ax.plot(
    ccap["charge_capacity"] * mass / 1000, ccap["voltage"], color="blue", label="charge"
)
ax.plot(cap_cha, V_cha, "bo", label="OCV charge")
ax.plot(
    dcap["discharge_capacity"] * mass / 1000,
    dcap["voltage"],
    color="green",
    label="discharge",
)
ax.plot(cap_dch, V_dch, "go", label="OCV discharge")
plt.xlabel("Capacity [mAh]", fontsize=15)
plt.ylabel("Voltage [V]", fontsize=15)
plt.title("GITT OCV curve", fontsize=15)
# plt.ylim(0, 0.91)
# plt.xlim(0, 4.70)
ax.legend(fontsize=15)
fig.set_figheight(7)
fig.set_figwidth(10)
plt.show()
../_images/examples_05_GITT_17_0.png

Saving the data#

Concatenate the OCV voltages and capacities into a dataframe, and save as a .csv file.

[11]:
OCV_cha = pd.concat([cap_cha, V_cha], axis=1, keys=["Charge_cap_mAh", "OCV_V"])
OCV_dch = pd.concat([cap_dch, V_dch], axis=1, keys=["Discharge_cap_mAh", "OCV_V"])
[12]:
# OCV_cha.to_csv('GITT_OCV_cycle'+str(GITT_cycle)+'_cha.csv', index=False)
# OCV_dch.to_csv('GITT_OCV_cycle'+str(GITT_cycle)+'_dch.csv', index=False)