In [ ]:
%load_ext autoreload
%autoreload 2
In [ ]:
import os
import copy
import logging
import bokeh
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from cellpy import cellreader
from cellpy.utils import ica
import holoviews as hv
import ipywidgets as widgets
from ipywidgets import interact, interact_manual
%matplotlib inline
hv.extension('bokeh')
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
my_data = cellreader.CellpyData()
filename = "../../../testdata/hdf5/20160805_test001_45_cc.h5"
assert os.path.isfile(filename)
my_data.load(filename)
my_data.set_mass(0.1)
from icafit import *
The natural way (and my impression is that this is how other groups also do it) of conducting an "in-depth" ica study on a LiB cell would be to measure ica of re-buildt half-cells of both the cathode and the anode of the full cells, fit the peaks of the half cells, and then a use convolution of these fits to fit the actual full cell.
Should include references here...
__add__
In [ ]:
In [ ]:
logger.setLevel(logging.DEBUG)
In [ ]:
import logging
from colorama import Fore
import ipywidgets as widgets
class log_viewer(logging.Handler):
""" Class to redistribute python logging data """
# have a class member to store the existing logger
logger_instance = logging.getLogger("__name__")
def __init__(self, output=None, up_side_down=True, max_lines=20, *args, **kwargs):
self._output = output
self.up_side_down = up_side_down
self.max_lines = max_lines
if self._output is None:
self._output = widgets.Output(layout=widgets.Layout(width='600px', height='160px', border='solid'))
self._output.layout.overflow_y = "scroll"
# Initialize the Handler
logging.Handler.__init__(self, *args)
# optional take format
# setFormatter function is derived from logging.Handler
for key, value in kwargs.items():
if "{}".format(key) == "format":
self.setFormatter(value)
# make the logger send data to this class
self.logger_instance.addHandler(self)
@property
def output(self):
return self._output
def emit(self, record):
""" Overload of logging.Handler method """
record = self.format(record)
if self.up_side_down:
self.output.outputs = (
{
'name': 'stdout',
'output_type':
'stream',
'text': (Fore.BLACK + (record + '\n'))
},
) + self.output.outputs[:self.max_lines]
else:
self.output.outputs = self.output.outputs[-self.max_lines:] + (
{
'name': 'stdout',
'output_type': 'stream',
'text': (Fore.BLACK + (record + '\n'))
},
)
In [ ]:
import ipywidgets as widgets
from IPython.display import display
import matplotlib.pyplot as plt
%matplotlib inline
In [ ]:
from fit_widget import SiliconPeaksFitWidget
In [ ]:
silicon = Silicon(shift=-0.0, max_point=1000000, sigma_p1=0.06)
In [ ]:
cycle = 5
cha, volt = my_data.get_ccap(cycle)
v, dq = ica.dqdv(volt, cha)
In [ ]:
silicon_fit_widget = SiliconPeaksFitWidget(silicon, cha, volt)
In [ ]:
# ---------------------------------------------------------------------------
visited = {}
options = list(range(1, 10+1))
def reset_cycle(event):
main_logger.info("-> reset cycle")
_load_cycle(sel.value, reset=True)
def load_cycle(change):
cycle = change.new
_load_cycle(cycle, reset=False)
def _load_cycle(cycle, reset):
if not reset and cycle in visited.keys():
c = visited[cycle]
if reset and cycle in visited.keys():
old = visited[cycle]
v = old.x
dq = old.y
silicon = Silicon(shift=-0.0, max_point=dq.max(), sigma_p1=0.06)
c = SiliconPeaksFitWidget(silicon, v, dq, f"Cycle {cycle}")
visited[cycle] = c
if cycle not in visited.keys():
cha, volt = my_data.get_ccap(cycle)
v, dq = ica.dqdv(volt, cha)
silicon = Silicon(shift=-0.0, max_point=dq.max(), sigma_p1=0.06)
c = SiliconPeaksFitWidget(silicon, v, dq, f"Cycle {cycle}")
visited[cycle] = c
with fit_window:
fit_window.clear_output(wait=True)
display(c)
def _copy(cycle1, cycle2):
main_logger.info(f"-> copy from {cycle1} to {cycle2}")
old = visited[cycle1]
old_peaks = copy.deepcopy(old.peaks_object)
cha, volt = my_data.get_ccap(cycle2)
v, dq = ica.dqdv(volt, cha)
new = SiliconPeaksFitWidget(old_peaks, v, dq, f"Cycle {cycle2}")
visited[cycle2] = new
sel.value = cycle2
def copy_cycle_forward(event):
cycle1 = sel.value
cycle2 = cycle1 + 1
if cycle2 in options:
_copy(cycle1, cycle2)
else:
main_logger.info(f"-> {cycle2} does not exist")
def copy_cycle_backward(event):
cycle1 = sel.value
cycle2 = cycle1 - 1
if cycle2 in options:
_copy(cycle1, cycle2)
else:
main_logger.info(f"-> {cycle2} does not exist")
fit_window = widgets.Output()
description = widgets.Label("Select cycle")
sel = widgets.Select(
options=options,
value=options[0],
rows=20,
disabled=False,
layout=widgets.Layout(width='70%', height='220px'),
)
sel.observe(load_cycle, 'value')
reset = widgets.Button(description="Reset!")
copy_next = widgets.Button(description="Copy >>")
copy_prev = widgets.Button(description="Copy <<")
reset.on_click(reset_cycle)
copy_next.on_click(copy_cycle_forward)
copy_prev.on_click(copy_cycle_backward)
header = widgets.VBox([description, sel, reset, copy_next, copy_prev])
out = widgets.HBox([header, fit_window])
handler = log_viewer()
main_logger_out = handler.output
main_logger = logging.getLogger(__name__)
main_logger.addHandler(handler)
main_logger.setLevel(20) # log at info level.
display(main_logger_out)
display(out)
_load_cycle(sel.value, reset=False)
In [ ]:
import pickle
cc = visited[3]
c3 = cc.result
b3 = c3.best_values
pickle_out = open("example.pickle", "wb")
pickle.dump(b3, pickle_out)
pickle_out.close()
In [ ]:
pickle_in = open("example.pickle","rb")
b3new = pickle.load(pickle_in)
In [ ]:
for key in b3new:
cc.peaks_object.set_param(key, value=b3new[key])
In [ ]:
jsonstr = cc.peaks_object.params.dumps()
In [ ]:
ccc = visited[4]
In [ ]:
s = ccc.peaks_object.params.loads(jsonstr)
In [ ]:
cc.peaks_object.params
In [ ]:
ccc.peaks_object.params
In [ ]:
In [ ]:
cc.set_value('shift', -0.2)
In [ ]:
cc.w_shift.value = 0.001
In [ ]:
cc.peaks_object.params.pretty_print()
In [ ]:
p_si = Silicon()
p_si.params["Si02sigma"]
In [ ]:
prm = "Si02sigma"
step = 0.01
p_si.params[prm].min += step
In [ ]:
# method two implemented in CompositeEnsamble
p_t = CompositeEnsemble(Silicon(), Graphite())
p_t.set_param('Si02sigma', minimum=0.02, vary=False)
p_t.reset_peaks()
print(f"hint: {p_t.param_hints['Si02sigma']} val: {p_t.params['Si02sigma']}")
In [ ]:
In [ ]:
In [ ]:
In [ ]:
import pandas as pd
pd.options.display.max_columns = None
In [ ]:
cycles = sorted(visited.keys())
all_dfs = []
for cycle in cycles:
params = visited[cycle].peaks_object.params
labels = params.keys()
columns = list(labels)
df = pd.DataFrame(columns=columns)
df.loc[cycle] = None
for label in labels:
df.loc[cycle, label] = params[label].value
all_dfs.append(df)
n_df = pd.concat(all_dfs)
n_df.index.name = "cycle"
In [ ]:
n_df
In [ ]:
n_df.plot(y=["Si01center", "Si02center"])
In [ ]: