{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Getting started with PyProBE" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%capture\n", "%pip install matplotlib" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from pprint import pprint\n", "\n", "import pyprobe\n", "\n", "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Convert data to standard format" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Create the cell object and load some data. If this is the first time that the data has been loaded, it must first be converted into the standard format for PyProBE. The `import_from_cycler` method will then add the data directly to the `procedure` dictionary of the cell with the given `procedure_name` as its key." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Describe the cell. Required fields are 'Name'.\n", "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", "\n", "# Create a cell object\n", "cell = pyprobe.Cell(info=info_dictionary)\n", "\n", "data_directory = \"../../../tests/sample_data/neware\"\n", "\n", "cell.import_from_cycler(\n", " procedure_name=\"Sample\",\n", " cycler=\"neware\",\n", " input_data_path=data_directory + \"/sample_data_neware.xlsx\",\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If a file named `README.yaml`, sits alongside your data, it will automatically be imported. You can also specify a custom path for this file. The README file contains descriptions of the experiments and steps in the procedure:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import yaml\n", "\n", "with open(data_directory + \"/README.yaml\") as f:\n", " pprint(yaml.safe_load(f))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once loaded, these can be accessed through the `experiment_names` and `step_descriptions` attributes of the procedure:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"Experiment names: \", cell.procedure[\"Sample\"].experiment_names)\n", "print(\"Step Descriptions: \")\n", "pprint(cell.procedure[\"Sample\"].step_descriptions)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alternatively, if you need to view data quickly and have not prepared a README file, the data will load without one (we will temporarily rename the README file to prevent it being automatically detected):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import os\n", "\n", "os.rename(data_directory + \"/README.yaml\", data_directory + \"/README_bak.yaml\")\n", "cell.import_from_cycler(\n", " procedure_name=\"Sample Quick\",\n", " cycler=\"neware\",\n", " input_data_path=data_directory + \"/sample_data_neware.xlsx\",\n", ")\n", "os.rename(data_directory + \"/README_bak.yaml\", data_directory + \"/README.yaml\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This procedure will have empty `experiment_names` and `step_descriptions` attributes:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"Experiment names: \", cell.procedure[\"Sample Quick\"].experiment_names)\n", "print(\"Step Descriptions: \")\n", "pprint(cell.procedure[\"Sample Quick\"].step_descriptions)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The dashboard can be launched as soon as procedures have been added to the cell (uncomment to run when outside docs environment):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# pyprobe.launch_dashboard([cell]) # noqa: ERA001" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The raw data is accessible as a dataframe with the data property:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(cell.procedure[\"Sample\"].data)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Individual columns can be returned as 1D numpy arrays with the `get()` method:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "current = (\n", " cell.procedure[\"Sample\"].experiment(\"Break-in Cycles\").charge(0).get(\"Current [A]\")\n", ")\n", "print(type(current), current)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Multiple columns can be returned at once:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "current, voltage = (\n", " cell.procedure[\"Sample\"]\n", " .experiment(\"Break-in Cycles\")\n", " .charge(0)\n", " .get(\"Current [A]\", \"Voltage [V]\")\n", ")\n", "print(\"Current = \", current)\n", "print(\"Voltage = \", voltage)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And different unit can be returned on command:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "current_mA = (\n", " cell.procedure[\"Sample\"].experiment(\"Break-in Cycles\").charge(0).get(\"Current [mA]\")\n", ")\n", "print(\"Current [mA] = \", current_mA)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Any part of the procedure can be plotted quickly using the ```plot``` method:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "cell.procedure[\"Sample\"].experiment(\"Break-in Cycles\").plot(\n", " x=\"Experiment Time [s]\",\n", " y=\"Voltage [V]\",\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can use the `analysis` to further analyse the data. For the `'Break-in Cycles'` we will use the `cycling` analysis module and the functions within. These functions return `Result` objects, so they can be interacted with in the same ways as raw data:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from pyprobe.analysis import cycling\n", "\n", "cycling_summary = cycling.summary(\n", " input_data=cell.procedure[\"Sample\"].experiment(\"Break-in Cycles\"),\n", ")\n", "print(type(cycling_summary))\n", "\n", "print(cycling_summary.data)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And it can be plotted as normal too:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "cycling_summary.plot(x=\"Capacity Throughput [Ah]\", y=\"Discharge Capacity [mAh]\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As the procedure that we imported without a README file does not contain experiment information, the `Break-in Cycles` will not work on it:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "cycling_summary = cycling.summary(\n", " input_data=cell.procedure[\"Sample Quick\"].experiment(\"Break-in Cycles\"),\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "However, all other filters will still work as expected." ] } ], "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.8" } }, "nbformat": 4, "nbformat_minor": 2 }