Filtering data#

One of PyProBE’s main strengths is to be able to filter data quickly and with natural language. This example shows the power of the filtering functions available.

Start by importing PyProBE and the dataset:

[1]:
import pyprobe
import numpy as np
info_dictionary = {'Name': 'Sample cell',
                   'Chemistry': 'NMC622',
                   'Nominal Capacity [Ah]': 0.04,
                   'Cycler number': 1,
                   'Channel number': 1,}
data_directory = '../../../tests/sample_data/neware'

# Create a cell object
cell = pyprobe.Cell(info=info_dictionary)
cell.add_procedure(procedure_name='Sample',
                   folder_path = data_directory,
                   filename = 'sample_data_neware.parquet')

Plot the entire dataset:

[2]:
full_procedure = cell.procedure['Sample']
fig = pyprobe.Plot()
fig.add_line(full_procedure, 'Time [s]', 'Voltage [V]')
fig.show_image()
# fig.show() # This will show the plot interactively, it is commented out for the sake of the documentation
../_images/examples_filtering-data_4_0.png

A README.yaml file is stored alongside this dataset, which appears like this:

[3]:
with open(data_directory+'/README.yaml', 'r') as file:
    readme = file.read()
    print(readme)
Initial Charge: # Experiment title
  Steps: # Steps list, descriptions are PyBaMM experiment strings
    1: Rest for 4 hours # Start with index 1
    # CC-CV charge provided as two seperate PyBaMM experiment strings
    2: Charge at 4mA until 4.2 V, Hold at 4.2 V until 0.04 A
    3: Rest for 2 hours
Break-in Cycles:
  Steps:
    4: Discharge at 4 mA until 3 V
    5: Rest for 2 hours
    6: Charge at 4 mA until 4.2 V, Hold at 4.2 V until 0.04 A
    7: Rest for 2 hours
  Cycle: # Cycle instruction, contains start, end and count
    Start: 4 # loop starts with step 4 (inclusive)
    End: 7 # loop ends with step 7 (inclusive)
    Count: 5
Discharge Pulses:
  Steps:
    # Neware considers cycling (in previous experiment) to be its own step,
    # so Step 8 is skipped
    9: Rest for 10 seconds
    10: Discharge at 20 mA for 0.2 hours or until 3 V
    11: Rest for 30 minutes
    12: Rest for 1.5 hours
  Cycle:
    Start: 9
    End: 12
    Count: 10

Constructing the README file in this way allows three separate experiments to be separated out from the data:

[4]:
initial_charge = full_procedure.experiment("Initial Charge")
break_in = full_procedure.experiment("Break-in Cycles")
pulses = full_procedure.experiment("Discharge Pulses")

fig = pyprobe.Plot()
fig.add_line(initial_charge, 'Procedure Time [s]', 'Voltage [V]', color = 'red', label='Initial Charge')
fig.add_line(break_in, 'Procedure Time [s]', 'Voltage [V]', color = 'blue', label='Break-in Cycles')
fig.add_line(pulses, 'Procedure Time [s]', 'Voltage [V]', color='purple', label='Discharge Pulses')
fig.show_image()
# fig.show() # This will show the plot interactively, it is commented out for the sake of the documentation
../_images/examples_filtering-data_8_0.png

Selecting the Break-in Cycles experiment, we can filter further:

[5]:
cycle_3 = break_in.cycle(2) # python zero-indexing means we use index 2 to retrieve the third cycle

fig = pyprobe.Plot()
fig.add_line(break_in, 'Experiment Time [s]', 'Voltage [V]', color = 'blue', label='Break-in Cycles')
fig.add_line(cycle_3, 'Experiment Time [s]', 'Voltage [V]', color='red', label='Cycle 3')
fig.show_image()
# fig.show() # This will show the plot interactively, it is commented out for the sake of the documentation
../_images/examples_filtering-data_10_0.png

We can break this down further into charge, discharge and rest sections:

[6]:
discharge = cycle_3.discharge()
rest_0 = cycle_3.rest(0)
charge = cycle_3.charge()
rest_1 = cycle_3.rest(1)

fig = pyprobe.Plot()
fig.add_line(discharge, 'Experiment Time [s]', 'Voltage [V]', color = 'blue', label='Discharge')
fig.add_line(rest_0, 'Experiment Time [s]', 'Voltage [V]', color='red', label='Rest 0')
fig.add_line(charge, 'Experiment Time [s]', 'Voltage [V]', color='purple', label='Charge')
fig.add_line(rest_1, 'Experiment Time [s]', 'Voltage [V]', color='green', label='Rest 1')
fig.show_image()
# fig.show() # This will show the plot interactively, it is commented out for the sake of the documentation
../_images/examples_filtering-data_12_0.png

Some cyclers will split constant voltage and constant current instructions into two separate steps. That is not the case for the cycler used for this dataset, but we can still extract them with PyProBE filtering:

[7]:
CC_discharge = discharge.constant_current(0)
CC_charge  = charge.constant_current(0)
CV_hold = cycle_3.constant_voltage(0)

fig = pyprobe.Plot()
fig.add_line(cycle_3, 'Experiment Time [s]', 'Current [A]', color = 'blue', label='Rests')
fig.add_line(CC_discharge, 'Experiment Time [s]', 'Current [A]', color='green', label='CC Discharge')
fig.add_line(CC_charge, 'Experiment Time [s]', 'Current [A]', color='red', label='CC Charge')
fig.add_line(CV_hold, 'Experiment Time [s]', 'Current [A]', color='purple', label='CV Hold')
fig.show_image()
# fig.show() # This will show the plot interactively, it is commented out for the sake of the documentation
../_images/examples_filtering-data_14_0.png