You can fill inn the MarkDown cells (the cells without "numbering") by double-clicking them. Also remember, press shift + enter
to execute a cell.
A couple of useful links:
It is often helpful to formulate what you wanted to achieve with your experiment before actually going into depth of the data. I believe that it does not make you "biased" when processing your data, but instead sharpens your mind and motivates you to look more closely on your results. I might be wrong, off course. Then just skip filling in this part.
(State the main hypothesis for the current set of experiment)
(What do you expect to find out? What kind of tests did you perform?)
(State if there are any special considerations for this experiment)
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 prms
from cellpy import prmreader
from cellpy.utils import batch
import holoviews as hv
%matplotlib inline
hv.extension('bokeh')
In [ ]:
prmreader.info()
In [ ]:
######################################################################
## ##
## development ##
## ##
######################################################################
import sys
from pathlib import Path
from pprint import pprint
# Use these when working on my work PC:
test_data_path = r"C:\Scripting\MyFiles\development_cellpy\testdata"
out_data_path = r"C:\Scripting\Processing\Test\out"
if sys.platform=="darwin":
# Use these when working on my MacBook:
test_data_path = "/Users/jepe/scripting/cellpy/testdata"
out_data_path = "/Users/jepe/cellpy_data"
test_data_path = Path(test_data_path)
out_data_path = Path(out_data_path)
print(" SETTING SOME PRMS ".center(80, "="))
prms.Paths["db_filename"] = "cellpy_db.xlsx"
prms.Paths["cellpydatadir"] = test_data_path / "hdf5"
prms.Paths["outdatadir"] = out_data_path
prms.Paths["rawdatadir"] = test_data_path / "data"
prms.Paths["db_path"] = test_data_path / "db"
prms.Paths["filelogdir"] = test_data_path / "log"
pprint(prms.Paths)
In [ ]:
## Uncomment this and run for checking your cellpy parameters.
# prmreader.info()
In [ ]:
# Please fill in here
project = "prebens_experiment"
name = "test"
batch_col = "b01"
In [ ]:
print(" INITIALISATION OF BATCH ".center(80, "="))
b = batch.init(name, project, batch_col=batch_col, log_level="INFO")
In [ ]:
# setting some prms
b.experiment.export_raw = False
b.experiment.export_cycles = False
b.experiment.export_ica = False
#b.experiment.all_in_memory = True # store all data in memory, defaults to False
In [ ]:
# load info from your db and write the journal pages
b.create_journal()
b.pages
In [ ]:
b.link()
In [ ]:
# create the apropriate folders
b.paginate()
In [ ]:
# load the data (and save .csv-files if you have set export_(raw/cycles/ica) = True)
# (this might take some time)
b.update()
In [ ]:
# collect summary-data (e.g. charge capacity vs cycle number) from each cell and export to .csv-file(s).
b.combine_summaries()
print(" FINISHED ".center(80, "-"))
In [ ]:
prms.Batch.summary_plot_height = 800
prms.Batch.summary_plot_width = 900
In [ ]:
# Plot the charge capacity and the C.E. (and resistance) vs. cycle number (standard plot)
b.plot_summaries()
In [ ]:
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource, ColumnarDataSource
data = ColumnDataSource(pd.DataFrame(
{
"header_en": [1, 2, 3, 4],
"annen": [22.1, 22.2, 22.3, 22.4],
"siste": [1000, 2000, 3000, 4000]
}
))
p = figure(title="Top Title with Toolbar", toolbar_location="above",
plot_width=600, plot_height=300)
p.circle(x="header_en", y="annen", source=data)
show(p)
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
b.summary_headers
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()
In [ ]:
summaries = b.summaries.copy()
In [ ]:
from cellpy.parameters.internal_settings import (
get_headers_summary,
get_headers_normal,
get_headers_step_table,
)
In [ ]:
labels = b.experiment.cell_names
labels
In [ ]:
d = b.experiment.data['20160805_test001_47_cc']
In [ ]:
b.experiment.data.experiment.cell_data_frames
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
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"]
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
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()
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)
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")
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"]
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();
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();
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")
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 [ ]: