{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Filtering data\n", "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." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Start by importing PyProBE and the dataset:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%capture\n", "%pip install matplotlib" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "\n", "import pyprobe\n", "\n", "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "info_dictionary = {\n", " \"Name\": \"Sample cell\",\n", " \"Chemistry\": \"NMC622\",\n", " \"Nominal Capacity [Ah]\": 0.04,\n", " \"Cycler number\": 1,\n", " \"Channel number\": 1,\n", "}\n", "data_directory = \"../../../tests/sample_data/neware\"\n", "\n", "# Create a cell object\n", "cell = pyprobe.Cell(info=info_dictionary)\n", "cell.add_procedure(\n", " procedure_name=\"Sample\",\n", " folder_path=data_directory,\n", " filename=\"sample_data_neware.parquet\",\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Plot the entire dataset:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "full_procedure = cell.procedure[\"Sample\"]\n", "full_procedure.plot(x=\"Time [s]\", y=\"Voltage [V]\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A `README.yaml` file is stored alongside this dataset, which appears like this:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open(data_directory + \"/README.yaml\", \"r\") as file:\n", " readme = file.read()\n", " print(readme)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Constructing the README file in this way allows three separate experiments to be separated out from the data:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "initial_charge = full_procedure.experiment(\"Initial Charge\")\n", "break_in = full_procedure.experiment(\"Break-in Cycles\")\n", "pulses = full_procedure.experiment(\"Discharge Pulses\")\n", "\n", "fig, ax = plt.subplots()\n", "initial_charge.plot(\n", " x=\"Time [s]\", y=\"Voltage [V]\", ax=ax, color=\"red\", label=\"Initial Charge\"\n", ")\n", "break_in.plot(\n", " x=\"Time [s]\", y=\"Voltage [V]\", ax=ax, color=\"blue\", label=\"Break-in Cycles\"\n", ")\n", "pulses.plot(\n", " x=\"Time [s]\", y=\"Voltage [V]\", ax=ax, color=\"purple\", label=\"Discharge Pulses\"\n", ")\n", "ax.set_ylabel(\"Voltage [V]\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Selecting the Break-in Cycles experiment, we can filter further:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "cycle_3 = break_in.cycle(\n", " 2\n", ") # python zero-indexing means we use index 2 to retrieve the third cycle\n", "\n", "fig, ax = plt.subplots()\n", "break_in.plot(\n", " x=\"Experiment Time [s]\",\n", " y=\"Voltage [V]\",\n", " ax=ax,\n", " color=\"blue\",\n", " label=\"Break-in Cycles\",\n", ")\n", "cycle_3.plot(\n", " x=\"Experiment Time [s]\", y=\"Voltage [V]\", ax=ax, color=\"red\", label=\"Cycle 3\"\n", ")\n", "ax.set_ylabel(\"Voltage [V]\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can break this down further into charge, discharge and rest sections:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "discharge = cycle_3.discharge()\n", "rest_0 = cycle_3.rest(0)\n", "charge = cycle_3.charge()\n", "rest_1 = cycle_3.rest(1)\n", "\n", "fig, ax = plt.subplots()\n", "discharge.plot(\n", " x=\"Experiment Time [s]\", y=\"Voltage [V]\", ax=ax, color=\"blue\", label=\"Discharge\"\n", ")\n", "rest_0.plot(\n", " x=\"Experiment Time [s]\", y=\"Voltage [V]\", ax=ax, color=\"red\", label=\"Rest 0\"\n", ")\n", "charge.plot(\n", " x=\"Experiment Time [s]\", y=\"Voltage [V]\", ax=ax, color=\"purple\", label=\"Charge\"\n", ")\n", "rest_1.plot(\n", " x=\"Experiment Time [s]\", y=\"Voltage [V]\", ax=ax, color=\"green\", label=\"Rest 1\"\n", ")\n", "ax.set_ylabel(\"Voltage [V]\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "CC_discharge = discharge.constant_current(0)\n", "CC_charge = charge.constant_current(0)\n", "CV_hold = cycle_3.constant_voltage(0)\n", "\n", "fig, ax = plt.subplots()\n", "cycle_3.plot(\n", " x=\"Experiment Time [s]\", y=\"Current [A]\", ax=ax, color=\"blue\", label=\"Cycle 3\"\n", ")\n", "CC_discharge.plot(\n", " x=\"Experiment Time [s]\", y=\"Current [A]\", ax=ax, color=\"green\", label=\"CC Discharge\"\n", ")\n", "CC_charge.plot(\n", " x=\"Experiment Time [s]\", y=\"Current [A]\", ax=ax, color=\"red\", label=\"CC Charge\"\n", ")\n", "CV_hold.plot(\n", " x=\"Experiment Time [s]\", y=\"Current [A]\", ax=ax, color=\"purple\", label=\"CV Hold\"\n", ")\n", "ax.set_ylabel(\"Current [A]\")" ] } ], "metadata": { "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" } }, "nbformat": 4, "nbformat_minor": 2 }