{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Plotting\n", "PyProBE includes compatibility with multiple open plotting libraries in Python. This example will go through interacting with each of them." ] }, { "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": [ "## Pandas/Matplotlib" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Matplotlib](https://matplotlib.org/) is one of the most popular plotting libraries in Python. [Pandas](https://pandas.pydata.org/) dataframes include a built-in `plot()` method to construct plots using Matplotlib, which is also integrated into PyProBE `Result` objects. \n", "\n", "Call `plot()` on any result object and control the method exactly as you would expect to with Pandas:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.figure()\n", "cell.procedure[\"Sample\"].experiment(\"Break-in Cycles\").plot(\n", " x=\"Time [s]\", y=\"Voltage [V]\", grid=True\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## HvPlot\n", "Plots created using Matplotlib sometimes need a lot of work to look good, and they are not particularly interactive. [HvPlot](https://hvplot.holoviz.org/index.html) provides a high-level interface similar to plotting in pandas with the additional flexibility of specifying a more interactive backend. Note hvplot is an optional dependency, it can be installed seperately to enable this functionality." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "cell.procedure[\"Sample\"].experiment(\"Break-in Cycles\").hvplot(\n", " x=\"Time [s]\", y=\"Voltage [V]\"\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Seaborn\n", "Seaborn is a high-level plotting library built on top of matplotlib. It provides a clean interface for dataframes, while maintaining much of matplotlib's flexibility.\n", "\n", "In PyProBE you can import a version of Seaborn customized to work with PyProBE objects directly:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from pyprobe.plot import seaborn as sns" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This version of Seaborn can be interacted with as normal. The only difference is you are able to pass PyProBE `Result` objects directly to Seaborn plotting functions in their `data` argument:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sns.lineplot(\n", " data=cell.procedure[\"Sample\"].experiment(\"Break-in Cycles\"),\n", " x=\"Time [s]\",\n", " y=\"Voltage [V]\",\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Being built on matplotlib, Seaborn can interact natively with customisation features like subplots:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots(2, 1, figsize=(8, 6))\n", "sns.lineplot(\n", " data=cell.procedure[\"Sample\"].experiment(\"Break-in Cycles\"),\n", " x=\"Time [s]\",\n", " y=\"Voltage [V]\",\n", " ax=ax[0],\n", ")\n", "sns.lineplot(\n", " data=cell.procedure[\"Sample\"].experiment(\"Break-in Cycles\"),\n", " x=\"Time [s]\",\n", " y=\"Current [A]\",\n", " ax=ax[1],\n", ")\n", "plt.tight_layout()\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarly, plots with two y axes can be created as usual:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots(figsize=(12, 6))\n", "sns.lineplot(\n", " data=cell.procedure[\"Sample\"].experiment(\"Break-in Cycles\").cycle(-1),\n", " x=\"Time [s]\",\n", " y=\"Voltage [V]\",\n", " ax=ax,\n", ")\n", "ax2 = ax.twinx()\n", "sns.lineplot(\n", " data=cell.procedure[\"Sample\"].experiment(\"Break-in Cycles\").cycle(-1),\n", " x=\"Time [s]\",\n", " y=\"Current [A]\",\n", " ax=ax2,\n", " color=\"r\",\n", ")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As for all the plotting methods demonstrated, built-in unit conversion is also present:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots(figsize=(12, 6))\n", "sns.lineplot(\n", " data=cell.procedure[\"Sample\"].experiment(\"Break-in Cycles\").cycle(-1),\n", " x=\"Time [hr]\",\n", " y=\"Voltage [V]\",\n", " ax=ax,\n", ")\n", "ax2 = ax.twinx()\n", "sns.lineplot(\n", " data=cell.procedure[\"Sample\"].experiment(\"Break-in Cycles\").cycle(-1),\n", " x=\"Time [hr]\",\n", " y=\"Current [mA]\",\n", " ax=ax2,\n", " color=\"r\",\n", ")\n", "plt.show()" ] } ], "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.6" } }, "nbformat": 4, "nbformat_minor": 2 }