{ "cells": [ { "cell_type": "markdown", "id": "88ccedb1-c6ad-49f6-b330-a4770bbd20f6", "metadata": {}, "source": [ "# Cycle Times\n", "The \"time\" a event occurs in a battery time series occurs can have many meanings.\n", "A \"date time\" is the moment it occured accordingly to a calendar, a \"test time\" is the elapsed time between, and so on.\n", "The battery data toolkit provides the `TimeEnhancer` to compute the many ways of describing time for a time series,\n", "and the `CycleTimesSummarizer` to produce summaries of times for each cycle" ] }, { "cell_type": "code", "execution_count": 1, "id": "516fdd56-ba75-409e-9596-01f46ffc9c08", "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "from matplotlib import pyplot as plt\n", "from batdata.postprocess.timing import CycleTimesSummarizer, TimeEnhancer\n", "from batdata.data import BatteryDataset\n", "from datetime import datetime, timedelta\n", "import pandas as pd" ] }, { "cell_type": "markdown", "id": "4cfcf498-de49-4f7f-9fef-0f918f59a16f", "metadata": {}, "source": [ "## Load Example Dataset\n", "The \"single-resistor\" datasets provided with battery-data-toolkit includes only a single cycle. \n", "We'll duplicate it to provide an example for this cycle." ] }, { "cell_type": "code", "execution_count": 2, "id": "a332ad81-d7b0-4392-9a59-5b12e1ef438a", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "C:\\Users\\lward\\Work\\ROVI\\battery-data-toolkit\\batdata\\data.py:90: UserWarning: Metadata was created in a different version of batdata. supplied=0.2.0, current=0.3.2.\n", " warnings.warn(f'Metadata was created in a different version of batdata. supplied={supplied_version}, current={__version__}.')\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
test_timecurrentvoltagecycle_number
23967188.01.03.0966670
23977191.01.03.0975000
23987194.01.03.0983330
23997197.01.03.0991670
24007200.01.03.1000000
\n", "
" ], "text/plain": [ " test_time current voltage cycle_number\n", "2396 7188.0 1.0 3.096667 0\n", "2397 7191.0 1.0 3.097500 0\n", "2398 7194.0 1.0 3.098333 0\n", "2399 7197.0 1.0 3.099167 0\n", "2400 7200.0 1.0 3.100000 0" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dataset = BatteryDataset.from_batdata_hdf('../../tests/files/example-data/single-resistor-constant-charge_from-charged.hdf')\n", "dataset.raw_data.tail()" ] }, { "cell_type": "markdown", "id": "726e3954-0174-4883-920d-893a4d592598", "metadata": {}, "source": [ "Make a copy of the cycle, increment the `cycle_number` and advance the `test_time`." ] }, { "cell_type": "code", "execution_count": 3, "id": "139131c6-7dbc-4061-b0d9-e7a8565d1024", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
test_timecurrentvoltagecycle_number
07203.0-1.02.8991671
17206.0-1.02.8983331
27209.0-1.02.8975001
37212.0-1.02.8966671
47215.0-1.02.8958331
\n", "
" ], "text/plain": [ " test_time current voltage cycle_number\n", "0 7203.0 -1.0 2.899167 1\n", "1 7206.0 -1.0 2.898333 1\n", "2 7209.0 -1.0 2.897500 1\n", "3 7212.0 -1.0 2.896667 1\n", "4 7215.0 -1.0 2.895833 1" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cycle_two = dataset.raw_data.copy()\n", "cycle_two['cycle_number'] += 1\n", "cycle_two['test_time'] += cycle_two['test_time'].max() + cycle_two['test_time'].iloc[1]\n", "cycle_two.head()" ] }, { "cell_type": "markdown", "id": "9192f92b-79d1-4e9a-8130-ad4ea0fe3558", "metadata": {}, "source": [ "As an example, we'll replace the test time with a date time so that we can show to recove the test time using `TimeEnhancer`" ] }, { "cell_type": "code", "execution_count": 4, "id": "14af4975-a21d-4ec2-ae89-2d0f0331391a", "metadata": {}, "outputs": [], "source": [ "timeseries = pd.concat([dataset.raw_data, cycle_two], ignore_index=True)" ] }, { "cell_type": "code", "execution_count": 5, "id": "dddcefee-f58c-4129-91f3-34ac256d08f5", "metadata": {}, "outputs": [], "source": [ "now = datetime.now()\n", "timeseries['date_time'] = timeseries['test_time'].apply(lambda x: now + timedelta(seconds=x))\n", "timeseries.drop(columns='test_time', inplace=True)" ] }, { "cell_type": "code", "execution_count": 6, "id": "57565c54-3794-4604-a95b-41fbd4f972fb", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
currentvoltagecycle_numberdate_time
0-1.02.89916702024-07-09 14:15:30.812201
1-1.02.89833302024-07-09 14:15:33.812201
2-1.02.89750002024-07-09 14:15:36.812201
3-1.02.89666702024-07-09 14:15:39.812201
4-1.02.89583302024-07-09 14:15:42.812201
\n", "
" ], "text/plain": [ " current voltage cycle_number date_time\n", "0 -1.0 2.899167 0 2024-07-09 14:15:30.812201\n", "1 -1.0 2.898333 0 2024-07-09 14:15:33.812201\n", "2 -1.0 2.897500 0 2024-07-09 14:15:36.812201\n", "3 -1.0 2.896667 0 2024-07-09 14:15:39.812201\n", "4 -1.0 2.895833 0 2024-07-09 14:15:42.812201" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dataset.raw_data = timeseries\n", "dataset.raw_data.head()" ] }, { "cell_type": "markdown", "id": "f9b3327a-6d87-4f6b-ac6e-0b061b741847", "metadata": {}, "source": [ "## Recover the Test Time\n", "The `TimeEnhancer` class computes a test time and cycle time (time since the start of a cycle) given the date time for measurements. It produces:\n", "- `test_time`: Time since the beginning of the time series\n", "- `cycle_time`: Time since the beginning of a cycle" ] }, { "cell_type": "code", "execution_count": 12, "id": "40cdc996-9c6c-45f1-9580-7766f4816c2b", "metadata": {}, "outputs": [], "source": [ "computer = TimeEnhancer()" ] }, { "cell_type": "code", "execution_count": 13, "id": "e2a505e0-c9ad-493c-bb2a-0be9bca15adf", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
test_timecycle_time
479714391.07188.0
479814394.07191.0
479914397.07194.0
480014400.07197.0
480114403.07200.0
\n", "
" ], "text/plain": [ " test_time cycle_time\n", "4797 14391.0 7188.0\n", "4798 14394.0 7191.0\n", "4799 14397.0 7194.0\n", "4800 14400.0 7197.0\n", "4801 14403.0 7200.0" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "computer.compute_features(dataset).tail()" ] }, { "cell_type": "markdown", "id": "1aa49dc1-7431-4220-a252-f07824da4ef5", "metadata": {}, "source": [ "The dataset now contains these additional ways of representing time." ] }, { "cell_type": "markdown", "id": "ce8e2051-098c-48cd-aa7f-b199bdbaa1c6", "metadata": {}, "source": [ "## Compute the Cycle Time\n", "`CycleTimesSummarizer` class computes two features describing entire cycles: \n", "- `cycle_start`: The time elapsed between first measurement of the cycle and the first measurement for the battery\n", "- `cycle_duration`: The time elapsed between the start of the cycle and the beginning of the next cycle" ] }, { "cell_type": "code", "execution_count": 16, "id": "dcaf8726-8d67-4c78-af25-fde515219910", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['cycle_start', 'cycle_duration']" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "computer = CycleTimesSummarizer()\n", "computer.column_names" ] }, { "cell_type": "markdown", "id": "e3405363-9d7c-4549-8a36-2cac95ec0949", "metadata": {}, "source": [ "Compute them by calling the `compute_features` function." ] }, { "cell_type": "code", "execution_count": 17, "id": "4dc5847d-bd14-4695-b30e-745c3a509d28", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
cycle_numbercycle_startcycle_duration
000.07203.0
117203.07200.0
\n", "
" ], "text/plain": [ " cycle_number cycle_start cycle_duration\n", "0 0 0.0 7203.0\n", "1 1 7203.0 7200.0" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "computer.compute_features(dataset)" ] }, { "cell_type": "markdown", "id": "28999d8b-f662-4b02-9bb1-e538792c9e41", "metadata": {}, "source": [ "The first cycle starts at 0 seconds and the second starts 7203 seconds later, yielding a cycle duration of 7203 seconds.\n", "\n", "There is no third cycle in our data file, so we only report the duration of the next cycle as the time between its first and last measurement: 7200 seconds." ] }, { "cell_type": "code", "execution_count": null, "id": "e4425056-fe3a-40e8-a413-26137ab79d81", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "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.9.19" } }, "nbformat": 4, "nbformat_minor": 5 }