2021-09-10 13:05:38 +02:00
import pandas as pd
2021-09-14 16:22:24 +02:00
import numpy as np
import matplotlib . pyplot as plt
2021-09-10 13:05:38 +02:00
def read_battsmall ( path ) :
''' Reads BATTSMALL-data into a DataFrame.
Input :
path ( required ) : string with path to datafile
Output :
df : pandas DataFrame containing the data as - is , but without additional NaN - columns . '''
2021-09-10 16:53:07 +02:00
df = pd . read_csv ( path , skiprows = 2 , sep = ' \t ' )
2021-09-10 13:05:38 +02:00
df = df . loc [ : , ~ df . columns . str . contains ( ' ^Unnamed ' ) ]
return df
2021-09-10 15:05:58 +02:00
2021-09-14 16:22:24 +02:00
def unit_conversion ( df , units ) :
2021-09-10 15:05:58 +02:00
2021-09-14 16:22:24 +02:00
C , m = units [ ' C ' ] . split ( ' / ' )
2021-09-10 15:05:58 +02:00
# Get the units used in the data set
t_prev = df . columns [ 0 ] . split ( ) [ - 1 ] . strip ( ' [] ' )
U_prev = df . columns [ 1 ] . split ( ) [ - 1 ] . strip ( ' [] ' )
I_prev = df . columns [ 2 ] . split ( ) [ - 1 ] . strip ( ' [] ' )
2021-09-10 16:53:07 +02:00
C_prev , m_prev = df . columns [ 4 ] . split ( ) [ - 1 ] . strip ( ' [] ' ) . split ( ' / ' )
2021-09-10 15:05:58 +02:00
# Define matrix for unit conversion for time
t_units_df = { ' h ' : [ 1 , 60 , 3600 , 3600000 ] , ' min ' : [ 1 / 60 , 1 , 60 , 60000 ] , ' s ' : [ 1 / 3600 , 1 / 60 , 1 , 1000 ] , ' ms ' : [ 1 / 3600000 , 1 / 60000 , 1 / 1000 , 1 ] }
t_units_df = pd . DataFrame ( t_units_df )
t_units_df . index = [ ' h ' , ' min ' , ' s ' , ' ms ' ]
# Define matrix for unit conversion for current
2021-09-10 16:53:07 +02:00
I_units_df = { ' A ' : [ 1 , 1000 , 1000000 ] , ' mA ' : [ 1 / 1000 , 1 , 1000 ] , ' uA ' : [ 1 / 1000000 , 1 / 1000 , 1 ] }
2021-09-10 15:05:58 +02:00
I_units_df = pd . DataFrame ( I_units_df )
I_units_df . index = [ ' A ' , ' mA ' , ' uA ' ]
# Define matrix for unit conversion for voltage
2021-09-10 16:53:07 +02:00
U_units_df = { ' V ' : [ 1 , 1000 , 1000000 ] , ' mV ' : [ 1 / 1000 , 1 , 1000 ] , ' uV ' : [ 1 / 1000000 , 1 / 1000 , 1 ] }
U_units_df = pd . DataFrame ( U_units_df )
U_units_df . index = [ ' V ' , ' mV ' , ' uV ' ]
2021-09-10 15:05:58 +02:00
# Define matrix for unit conversion for capacity
2021-09-10 16:53:07 +02:00
C_units_df = { ' Ah ' : [ 1 , 1000 , 1000000 ] , ' mAh ' : [ 1 / 1000 , 1 , 1000 ] , ' uAh ' : [ 1 / 1000000 , 1 / 1000 , 1 ] }
2021-09-10 15:05:58 +02:00
C_units_df = pd . DataFrame ( C_units_df )
C_units_df . index = [ ' Ah ' , ' mAh ' , ' uAh ' ]
2021-09-10 16:53:07 +02:00
# Define matrix for unit conversion for capacity
m_units_df = { ' kg ' : [ 1 , 1000 , 1000000 , 1000000000 ] , ' g ' : [ 1 / 1000 , 1 , 1000 , 1000000 ] , ' mg ' : [ 1 / 1000000 , 1 / 1000 , 1 , 1000 ] , ' ug ' : [ 1 / 1000000000 , 1 / 1000000 , 1 / 1000 , 1 ] }
m_units_df = pd . DataFrame ( m_units_df )
m_units_df . index = [ ' kg ' , ' g ' , ' mg ' , ' ug ' ]
2021-09-10 15:05:58 +02:00
2021-09-10 16:53:07 +02:00
#print(df["TT [{}]".format(t_prev)])
2021-09-14 16:22:24 +02:00
df [ " TT [ {} ] " . format ( t_prev ) ] = df [ " TT [ {} ] " . format ( t_prev ) ] * t_units_df [ t_prev ] . loc [ units [ ' t ' ] ]
df [ " U [ {} ] " . format ( U_prev ) ] = df [ " U [ {} ] " . format ( U_prev ) ] * U_units_df [ U_prev ] . loc [ units [ ' U ' ] ]
df [ " I [ {} ] " . format ( I_prev ) ] = df [ " I [ {} ] " . format ( I_prev ) ] * I_units_df [ I_prev ] . loc [ units [ ' I ' ] ]
df [ " C [ {} / {} ] " . format ( C_prev , m_prev ) ] = df [ " C [ {} / {} ] " . format ( C_prev , m_prev ) ] * ( C_units_df [ C_prev ] . loc [ units [ ' C ' ] ] / m_units_df [ m_prev ] . loc [ units [ ' m ' ] ] )
2021-09-10 16:53:07 +02:00
2021-09-14 16:22:24 +02:00
df . columns = [ ' TT ' , ' U ' , ' I ' , ' Z1 ' , ' C ' , ' Comment ' ]
2021-09-10 16:53:07 +02:00
return df
2021-09-14 16:22:24 +02:00
#def process_battsmall_data(df, t='ms', C='mAh/g', I='mA', U='V'):
def process_battsmall_data ( df , units = None ) :
''' Takes BATTSMALL-data in the form of a DataFrame and cleans the data up and converts units into desired units.
Splits up into individual charge and discharge DataFrames per cycle , and outputs a list where each element is a tuple with the Chg and DChg - data . E . g . cycles [ 10 ] [ 0 ] gives the charge data for the 11 th cycle .
For this to work , the cycling program must be set to use the counter .
Input :
df ( required ) : A pandas DataFrame containing BATTSMALL - data , as obtained from read_battsmall ( ) .
t ( optional ) : Unit for time data . Defaults to ms .
C ( optional ) : Unit for specific capacity . Defaults to mAh / g .
I ( optional ) : Unit for current . Defaults mA .
U ( optional ) : Unit for voltage . Defaults to V .
Output :
cycles : A list with
'''
required_units = [ ' t ' , ' I ' , ' U ' , ' C ' ]
default_units = { ' t ' : ' h ' , ' I ' : ' mA ' , ' U ' : ' V ' , ' C ' : ' mAh/g ' }
if not units :
units = default_units
if units :
for unit in required_units :
if unit not in units . values ( ) :
units [ unit ] = default_units [ unit ]
# Convert all units to the desired units.
df = unit_conversion ( df = df , units = units )
# Replace NaN with empty string in the Comment-column and then remove all steps where the program changes - this is due to inconsistent values for current and
df [ [ " Comment " ] ] = df [ [ " Comment " ] ] . fillna ( value = { ' Comment ' : ' ' } )
df = df [ df [ " Comment " ] . str . contains ( " program " ) == False ]
# Creates masks for
chg_mask = df [ ' I ' ] > = 0
dchg_mask = df [ ' I ' ] < 0
# Initiate cycles list
cycles = [ ]
# Loop through all the cycling steps, change the current and capacities in the
for i in range ( df [ " Z1 " ] . max ( ) ) :
sub_df = df . loc [ df [ ' Z1 ' ] == i ] . copy ( )
sub_df . loc [ dchg_mask , ' I ' ] * = - 1
sub_df . loc [ dchg_mask , ' C ' ] * = - 1
chg_df = sub_df . loc [ chg_mask ]
dchg_df = sub_df . loc [ dchg_mask ]
cycles . append ( ( chg_df , dchg_df ) )
return cycles
def plot_gc ( cycles , which_cycles = ' all ' , chg = True , dchg = True , colours = None , x = ' C ' , y = ' U ' ) :
fig , ax = prepare_gc_plot ( )
if which_cycles == ' all ' :
which_cycles = [ i for i , c in enumerate ( cycles ) ]
if not colours :
chg_colour = ( 40 / 255 , 70 / 255 , 75 / 255 ) # Dark Slate Gray #28464B
dchg_colour = ( 239 / 255 , 160 / 255 , 11 / 255 ) # Marigold #EFA00B
2021-09-10 16:53:07 +02:00
2021-09-14 16:22:24 +02:00
for i , cycle in cycles :
if i in which_cycles :
if chg :
cycle [ 0 ] . plot ( ax = ax )
def prepare_gc_plot ( figsize = ( 14 , 7 ) , dpi = None ) :
fig , ax = plt . subplots ( figsize = figsize , dpi = dpi )
return fig , ax
2021-09-10 15:05:58 +02:00