{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Time Series Changes and Versioning with TimeDB\n",
"\n",
"This notebook demonstrates how to manually change values, tags, and annotations of a time series and view all versions of the changes.\n",
"\n",
"#### What you'll learn:\n",
"1. **Creating and inserting a time series** - Insert initial time series data\n",
"2. **Reading and visualizing time series** - Read and plot the original data\n",
"3. **Updating time series** - Manually change values, tags, and annotations\n",
"4. **Reading all versions** - Query all versions of the time series using `all_versions` flag\n",
"5. **Visualizing changes** - Plot original vs updated versions to see the differences\n",
"6. **Batch updates and version history** - Update multiple values and view complete version history with metadata\n",
"\n",
"**Key Concepts:**\n",
"- TimeDB maintains a full version history of all changes\n",
"- Each update creates a new version while keeping the old version for audit trail\n",
"- The `all_versions=True` flag allows you to see all historical versions with `changed_by` and `change_time` metadata\n",
"- The `tags_and_annotations=True` flag includes tags and annotations as DataFrame columns\n",
"- When using `all_versions=True` with `return_value_id=True`, the DataFrame uses a MultiIndex `(valid_time, value_id)` to preserve multiple versions\n",
"- Updates can modify values, annotations, and tags independently or together\n",
"- Using `value_id` from the initial read makes updates simple - no need to query the database again\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"✓ Imports successful\n"
]
}
],
"source": [
"import timedb as td\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"from datetime import datetime, timezone, timedelta\n",
"import numpy as np\n",
"\n",
"# Load environment variables (for database connection)\n",
"from dotenv import load_dotenv\n",
"load_dotenv()\n",
"\n",
"print(\"✓ Imports successful\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 1: Create and Insert a Time Series\n",
"\n",
"First, let's create the database schema and insert an initial time series.\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Creating database schema...\n",
"✓ Schema created successfully\n"
]
}
],
"source": [
"# Delete database schema\n",
"td.delete()\n",
"\n",
"# Create database schema (includes support for updates, tags, and annotations)\n",
"td.create()\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Data values inserted successfully.\n",
"✓ Time series inserted successfully!\n",
" Run ID: fe63180a-a3bd-41a7-a84d-4f64462c02a2\n",
" Series ID: b3af9adf-db64-4ef6-ade8-54333d06fae5\n",
" Time range: 2025-01-01 00:00:00+00:00 to 2025-01-01 23:00:00+00:00\n",
" Number of data points: 24\n"
]
}
],
"source": [
"# Create a time series with hourly data for 24 hours\n",
"base_time = datetime(2025, 1, 1, 0, 0, tzinfo=timezone.utc)\n",
"times = [base_time + timedelta(hours=i) for i in range(24)]\n",
"\n",
"# Generate sample data: temperature values with a daily pattern\n",
"# Starting at 15°C, rising to 25°C during the day, then cooling down\n",
"np.random.seed(42) # For reproducibility\n",
"base_temp = 20.0\n",
"amplitude = 5.0\n",
"temperature_values = [\n",
" base_temp + amplitude * np.sin(2 * np.pi * i / 24) + np.random.normal(0, 0.5)\n",
" for i in range(24)\n",
"]\n",
"temperature_values = [round(v, 2) for v in temperature_values]\n",
"\n",
"# Create DataFrame\n",
"df = pd.DataFrame({\n",
" 'valid_time': times,\n",
" 'temperature': temperature_values\n",
"})\n",
"\n",
"# Insert the time series\n",
"result = td.insert_batch(df=df)\n",
"\n",
"print(f\"✓ Time series inserted successfully!\")\n",
"print(f\" Run ID: {result.run_id}\")\n",
"print(f\" Series ID: {result.series_ids['temperature']}\")\n",
"print(f\" Time range: {times[0]} to {times[-1]}\")\n",
"print(f\" Number of data points: {len(df)}\")\n",
"\n",
"# Store the series_id for later use\n",
"series_id = result.series_ids['temperature']\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 2: Read and Plot the Original Time Series\n",
"\n",
"Now let's read back the time series and visualize it."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"✓ Read 24 data points\n",
"\n",
"DataFrame shape: (24, 2)\n",
"\n",
"Columns: ['temperature', 'value_id']\n",
"\n",
"First few rows:\n"
]
},
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
series_key
\n",
"
temperature
\n",
"
value_id
\n",
"
\n",
"
\n",
"
valid_time
\n",
"
\n",
"
\n",
"
\n",
" \n",
" \n",
"
\n",
"
2025-01-01 00:00:00+00:00
\n",
"
20.25
\n",
"
1
\n",
"
\n",
"
\n",
"
2025-01-01 01:00:00+00:00
\n",
"
21.22
\n",
"
2
\n",
"
\n",
"
\n",
"
2025-01-01 02:00:00+00:00
\n",
"
22.82
\n",
"
3
\n",
"
\n",
"
\n",
"
2025-01-01 03:00:00+00:00
\n",
"
24.3
\n",
"
4
\n",
"
\n",
"
\n",
"
2025-01-01 04:00:00+00:00
\n",
"
24.21
\n",
"
5
\n",
"
\n",
"
\n",
"
2025-01-01 05:00:00+00:00
\n",
"
24.71
\n",
"
6
\n",
"
\n",
"
\n",
"
2025-01-01 06:00:00+00:00
\n",
"
25.79
\n",
"
7
\n",
"
\n",
"
\n",
"
2025-01-01 07:00:00+00:00
\n",
"
25.21
\n",
"
8
\n",
"
\n",
"
\n",
"
2025-01-01 08:00:00+00:00
\n",
"
24.1
\n",
"
9
\n",
"
\n",
"
\n",
"
2025-01-01 09:00:00+00:00
\n",
"
23.81
\n",
"
10
\n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
"series_key temperature value_id\n",
"valid_time \n",
"2025-01-01 00:00:00+00:00 20.25 1\n",
"2025-01-01 01:00:00+00:00 21.22 2\n",
"2025-01-01 02:00:00+00:00 22.82 3\n",
"2025-01-01 03:00:00+00:00 24.3 4\n",
"2025-01-01 04:00:00+00:00 24.21 5\n",
"2025-01-01 05:00:00+00:00 24.71 6\n",
"2025-01-01 06:00:00+00:00 25.79 7\n",
"2025-01-01 07:00:00+00:00 25.21 8\n",
"2025-01-01 08:00:00+00:00 24.1 9\n",
"2025-01-01 09:00:00+00:00 23.81 10"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Read the time series with return_value_id=True so we can use value_id later for updates\n",
"df_read = td.read(return_value_id=True)\n",
"\n",
"print(f\"✓ Read {len(df_read)} data points\")\n",
"print(f\"\\nDataFrame shape: {df_read.shape}\")\n",
"print(f\"\\nColumns: {list(df_read.columns)}\")\n",
"print(f\"\\nFirst few rows:\")\n",
"df_read.head(10)\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAABKUAAAJOCAYAAABm7rQwAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAsetJREFUeJzs3QWYlGXbxvFz6W4QFJBQURQ7EBHFAOO1G33tBhVURCzEQhTFAMX2s30NVOxCUTERJQ0EFEFKpHvZ7zif29ligYWNqf/vOObYeWZmd+995tmJc677ujOysrKyBAAAAAAAAJSiMqX5ywAAAAAAAAAjlAIAAAAAAECpI5QCAAAAAABAqSOUAgAAAAAAQKkjlAIAAAAAAECpI5QCAAAAAABAqSOUAgAAAAAAQKkjlAIAAAAAAECpI5QCAAAAAABAqSOUAgCkhalTpyojIyP79MknnxT5Z5555pnZP2///fdXvOT+u5588skS+z3eZ7l/l/cp2J8AAACbilAKAJAwfvzxR1188cVq06aNatWqpQoVKmizzTbTAQccoAEDBmjBggXxHmLKhXOFPaWK9957T8ccc4y22GKL6PiqXr26ttxyS7Vr104XXXSRXnzxxXgPMWk5mN3Y46okQ9R0c+ONN2bv12bNmsV7OAAAFEq5wt0MAICSs3r1al1xxRW677771rpu9uzZ0Wn48OHq37+/nn32WXXq1Gmjf0edOnV05513Zm+3bNmyyOM++eSTtcMOO0TnmzRpolTnfZZ7H3qfJpMbbrhBN998c57LVq1apcWLF+uPP/7Ql19+GZ1OOumkUhlPsu9PAACAosrIysrKKvJPAQCgCFyhMmTIkOztzTffXCeeeKLq1aunsWPH6uWXX1ZmZmZ0natbPv74Y+2zzz6F+tkrV66Un+oqVqyYsvdR7kqmJ554IppWuC4LFy7Uww8/nOey7777Lk+F0IUXXrhWaHfllVcqmU2YMCEKEGMve1q1aqWjjjpKtWvX1rx586Iqvc8//1xbb721fvjhhxIdy5IlS1S5cmWVKZNaBes+hqZNm5bnsp49e2af33333dcK/A499FBtv/32pTbGRObHuBUrVqhKlSqbXCnVt2/f6Lyr/0prem1Rxw0ASHMOpQAAiJcvvvjCKUH2adddd81asGBBntt89NFHWWXKlMm+zfbbb5+VmZmZff1+++2Xfd0ZZ5yRNXbs2Kyjjjoqq06dOtFlo0ePzpoyZUqe3zN8+PA8v2Pu3LlZF154YdZmm22WValSpazddtst63//+190u9zf558T498Vu9xjyC339zzxxBNZ77//ftb++++fVbVq1axq1aplHXLIIVnjxo1ba3/ccccd0di33nrrrNq1a2eVK1cuq2bNmll77LFH1i233JK1ePHitb4n/+/aWP6e9e2bmI3ZFz///HPW0UcfnVWjRo3o7zjllFOyZs6cGd32ww8/zGrfvn1W5cqVs+rVq5d19tlnZ82bN6/A3zlixIisk046KatJkyZZFSpUyKpevXpW27ZtswYNGpS1cuXKQv+N9957b/b4fB8UtB+XLl2a9fHHHxf4/T/88EPWWWedldWiRYvo+PDP2HnnnbNuvfXWAn/Wlltumf37+vTpk/XZZ59lHXjggdH+8GX//PPPeven+Rh/6qmnsg4++OCs+vXrZ5UvXz7aX4cddljWW2+9VeA4X3/99azOnTtnNWjQIDp2vL88Zh9Tt912W57/m9KQ++/zMVKQN954I+vII4/MatiwYfQ31qpVK6tjx45ZzzzzTNaaNWvy3Db//7EfG+65556sbbbZJrpf/Njw9NNPR7f1/dKjR4+szTffPKtixYrR/TV06NAN3ldfffVVtM99X/l/tVOnTlnfffddgWP3Md27d++snXbaKbqtf0/Lli2zLr744qzff/99rdvn/z/xbU477bTo/srIyMge32OPPZZ1wgknZG277bZZdevWzb4v/XuuuuqqrDlz5mT/zPzHUUGn2OPC+h6zNub/e13j3pR9AgBIb4RSAIC4yv1mxycHFgVxqJH7dp988kmBodQuu+wSBQa5b7uhUMoBgd/8FfRm7ogjjihyKLXPPvtEb9zy/2y/2Zw9e3ae7/Nl63tz2aZNm6xFixYldCjVvHnzKIjKP/ZWrVpFIUvugDF26tChw1q/75prrlnvvth3330LDIQKctddd2V/n4OPb7/9ttD754EHHohCgXWNo3Xr1ll//fXXOoOOvffeO6ts2bJ5vmdDoZQDsoMOOmi9f//ll1++3vuxoNOyZcuyEiWUckD23//+d73jdTCzevXq7O/J/3/s8Lig7/N9tueee651uf8P8z/G5L6vHJb6+Mj/fQ5QHSzmNnLkyCgkXNfYHSY7VM0t9/+Jg2cHcbm/JxburOvvip222GKLrOnTp8cllFrfuDdlnwAA0hs9pQAAcfXZZ59ln/dUqgMPPLDA23naz/PPP5/n+/bbb7+1bjd69GiVK1dO//3vf6OpWD/99JMqVaq03jFcd9110e1i2rdvr44dO0a/Y9iwYSqqL774Qttuu62OPfbYaGrY22+/HV3+999/67HHHtPVV1+dfdvGjRtHv9vTb7w//L5+ypQp0dQoT/vydMYHHnhAV111lRKVx1u3bt1ojJMnT46mX9rPP/+s008/XQ0bNoymGH777bf66KOPoutGjBihr776Sm3bto22X3jhBd12223ZP7Nz587RlM1Zs2bp//7v/6I+UL5/evTosdZ0xILsuuuuefpI7bHHHmrdurX23HNP7bbbbtGx5Ab7+Y0cOVLdunXTmjVrom2P75BDDtGiRYuiccydOzeaGui/6/333y/wd7tPlac2nXbaaVGDdR+jZcuWXe94/Xd9+OGH2VNW3b/Mx7Pv/5deeik6Lu6+++5o7F26dIlu9+CDD2Z/v/++//znP1G/Nk+p+/rrrzVx4kQlkjvuuENPP/109hTU4447TjvttFN0/Phy30/+W3feeWddc801Bf6MUaNGRfeH/95HH31Uf/31V3S5F0ywI488MpoeeP/990fHjPeb+3it63HGUzi32WYbnXDCCfrzzz+jcfi+X7Zsmc4666zoccL3nafBHn300dH9b/5/9WOUp2X6eB8/fny0MIP/pl9//VU1a9Zc63f5cvPjgv/u33//Pft2DRo00BFHHBFNo3WvMf/O6dOnR48Dftzw+VtuuSV6LIj1JvPx98EHH0Tf78eO3PvM+6e4rGvcxbFPAABpKN6pGAAgvbkCIfYpuqfXrIurnXJ/4u6pIAVVSvn02muvrfX966qUWrVqVTTFJHZ5u3btsiszXMnhaURFrZTy1LOFCxdmX+dqrth1xx577FpjnT9/ftbbb7+dNWTIkKjC584774wqiWLfc8ABByR0pZRPn3/+efZ1nj6V+7pYlZL3Se6qlPvuu6/AfXT66afnGYenVcaucwXT33//Xai/09MJ11dNsuOOO641fe+YY47Jvt7TL3NPf/vmm2/yfP+PP/5YYPWNq6RGjRpV6P3pvyd3Zdbjjz+e5/t87Meu836K8fhjl3/55Zdr/T7//ESZvudx5K6oueGGG9aaxhq7ztWDsXHn/z/2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GjRImjjRbWH83tLvPf1+VWrXrmSOOc8O2nvvvaMqo+effz4KmcaPH6+ePXtGPZi9KFisvU1+K1euVIUKFbLfN8e4Uiq2DwraFw4oirshfO7fl/93Nm3aNFoFLsazoPy3ffjhh9mX1axZM2F7IOXmCrTY+7HCKMrxmP9+3lQFZQjxzBQSKs3wP4sDqaFDh+rjjz+O/gFza9asmTbffHP9/PPPeS7/5ZdftOWWW5byaAEg/vzp3dixXpm0fPSVNnMAAABF50Dqyiul77+XatXye9HwdfTocLmvL6kZQw4c3n//fe23335RgHPooYdGgc306dN17bXX5nl/fPPNN+v000+PZgGdf/75URWSQ48ffvgh+3ZvvPFGVNhRuXJldezYUf/3f/8X3Wb+/PnZC4zV8h/3L7fL8ZS7p59+OvodDohOPvnkPFO8HCK5r7O/z9VbrrRyz+fCKFu2rBo2bJh9qlatWlRNFdv2Ymf33HNPlAd4zDvttJNefvnl7O//5JNPovG7kswzp3ybAw44IOpB/c4770RFK94fXbp00dKlS7O/b//994/yBp/8N7ma7Prrr8/TZ8v9qK+88kptscUWqlq1qvbaa6/o98XE9lVsn7oAxgUy3377rQ4++ODoZ/pn+7773gdPrvvKjjnmmGjsse0zzzxzrcoptzHyWPOP25f753fu3Dm63DPLfGx4/2222Wb673//G1XWJZuECqX8D/jMM8/oueeeU/Xq1TVz5szotGzZsuh633lOiO+7777ooJw0aVJ0EP30008655xz4j18AChVfjF02mnSGWdkqFevGtFXb5fUiyQAAIB04A/5XCE1b5601VZStWoOUsLXli3DVL7Bg4v/w0D3+nHQcvHFF0dBS24Oa7zg14svvpgnRHGVkUOb0aNHR++N85syZYpOOOEEHXnkkVFQ5VY4uYOtdXHA9Nprr0UzmHz69NNPdfvtt2dfv2TJkqhNznfffRe103GljQOX4miY7bY87nM1ZMiQqEqsR48eOu2006Ix5ObwbNCgQRo5cmQ05fHEE0+MwiznCW+99VYU7N1///15vseBnAMw97q69957dffdd+vRRx/Nvt7hz5dffqkXXnhBY8aMifbdIYccol9//TX7Ng66+vfvH32fx+cQzYHdGWecEbUfcjWb+10fdthh2UGeQyt74oknoiqx2HZhedwOK7/4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l1/OGwcAwKbr2FFavVq6776w/fLLIZjq0oW9CgAAkJSNzoGS8Ouv0v/9X862A6natdnXAICiOfhg6aKLcraff1566SX2KgAAQFKGUp6m161bN+200046/vjjNWnSpJIdGVLekiWh70dmZtg+/nhp113jPSoAQKo47DDpvPNytp96KlTnAgAAIMlCqdNPP13jx4/X008/rZo1a6pTp05auXJlyY4OKct9PgYPlmbODNutWoXm5gAAFKcjj5RyLwj82GPSm2+yjwEAAJImlHL49NZbb6lHjx7acccddc0112jq1KkaO3ZsyY8QKemDD6TPPgvnq1YNy3h76W4AAIrbccfl/eDjoYekd99lPwMAACRFKFWhQgU1bNhQ33//fbQ9evRolSlTRptvvnlJjw8p6I8/whuCmEsukRo0iOeIAACp7uSTpRNPzNl+4AHpo4/iOSIAAAAUujblscceU5cuXTRs2DD98ssv6t+/vxo1asQexEbxjM/+/cNXO/RQaZ992IkAgJJ32mnSqlXS0KFhGvm994ZV+Tp0YO8DAAAkdCjlHlK///67fvrpJzVt2lT169cv2ZEhJT3ySKiUsi23lM49N94jAgCki4wM6ayzpNWrpWHDQjB1111h+ni7dvEeHQAAQPrZqC4+VatW1W677VZyo0HKWbNGGj9e+ucfacoU6Z13wpuCChWkXr3CVwAASoufg7winyum3FfKz1NeCbZ3b2mvvbgfAAAAShOtpVFiRo6UBg2SJk6UliyR5syRqlSRmjWTbrxRatKEnQ8AiE8wdfHFoWLqww+lzEzp9tul666T+OwNAAAgwRqd33333fr55583+ocvX748+t4///xzU8aGJA+krrxScm/8mjXDJ9JlykgLFkg+HBxOAQAQz2DKC23sv3/YdkB1663Sjz9ynwAAACRUKNWzZ0+NGjVqo3/4kiVLou91Y3SkD0+FcIXUvHnSVluFqXtLl4aeHXXqSJUqhVWPfDsAAOLFH5Z07y61bx+2/QHKTTdJ48ZxnwAAACTM9L2srCy9+uqrmjRp0kb98KVOIpB23EPKU/Y220yaOjVM24t9Ku2Qyo1lJ0wIt2vTJt6jBQCks7JlpSuuCIHU11+H1WH79pVuvlnadtt4jw4AACC1FbqnlEMpn4ANiVVGeaqee0nFNG3qZvmhd8esWeF2AADEmyt5vfjGbbdJ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/JNTLdWsWbxHBQAA0tkmhVL0kwIAAEjOaqlHHw3bL74o9eoV71EBAIB0tkk9pQAAAJB8Dj1UqlUrnP/iC+mPP+I9IgAAkM42OZTytL0XXnhBF1xwgY455hiNHTs2unzBggV69dVXNWvWrOIcJwAAAIqpWsqysliJDwAAJGEoNX/+fO2zzz7q0qWLnn/+eb3xxhuaM2dOdF21atV06aWX6t577y3usQIAAKAYqqVq1gznP/9cmjaNXQoAAJIolLr66qs1fvx4vffee5o8ebKy/FHbv8qWLavjjz9eb7/9dnGOEwAAAMWgYkWqpQAAQBKHUq+99pouueQSHXzwwQWusrfNNtvQDB0AACAJqqU++0z68894jwgAAKSjTQql3DeqefPm67x+1apVWr16dVHGBQAAgBJSqZJ0zDHhvAvevRIfAABAUoRSLVu21Pfff7/O699//321bt26KOMCAABACTr8cKlGjXD+00+l6dPZ3QAAIAlCqXPPPVePP/64Xnzxxex+Up7Gt2LFCl177bV69913o1X5AAAAkJiolgIAAPFWblO+6bLLLosanZ9yyimqVatWdJlX4vv777+jaXsOpM4555ziHisAAACKuVrq1VelRYukTz6RTjpJ2mILdjEAAEjgUMpVUY888ojOOOMMvfTSS5o0aZLWrFkTTes78cQT1aFDh+IfKQAAAIpV5cqht9RTT4XeUv/7n9SjBzsZAAAkcCgV0759++gEAACA5PSf/0hDh+ZUS518stSoUbxHBQAA0kGRQql58+bpww8/1NSpU6Ntr8h3wAEHqG7dusU1PgAAAJRwtdTRR0tPPy2tWRNW4uvenV0OAAASOJS68cYb1b9//6i5eW4VKlTQVVddpZtuuqk4xgcAAIBSqpZavFgaPjz0lqJaCgAAJOTqezfffHMUOh100EF655139Ntvv0Wnt99+O7rs1ltvjW4DAACAxFelinTUUeG8q6VeeineIwIAAOlgk0KpIUOG6IgjjtCwYcPUuXPnaNqeT4cccojefPNNHXbYYXrwwQeLf7QAAAAoEUccIVWtGs5/9JE0cyY7GgAAJGAotWDBgiiAWheHUovcLRMAAABJwYFU7mopr8QHAACQcKHUPvvso6+//nqd1/s63wYAAADJ48gjc6qlPv5Ymj073iMCAACpbJOn73355Zfq0aOHJk2apDVr1kQnn+/evbu++uqr6DYAAABIHg6kPI3PMjOplgIAAAm4+t6OO+4YhVD33XdfdCpTJmRbvswqVqwY3Sa3jIyMaNofAAAAEpen8L3xhrR0qfThh9KJJ0oNGsR7VAAAIBVtUih13HHHRSETAAAAUku1amEa3wsvhGopr8TXtWu8RwUAAFLRJoVSTz75ZPGPBAAAAAnBodTrr0vLluVUS9WvH+9RAQCAVLNJPaUAAACQuqpXz+kttXq19PLL8R4RAABIRZtUKRUzYsQITZ48Wf/884+ysrLyXOfpfW6EDgAAgORz9NGht9Ty5dL770snnCDVqxfvUQEAAKV7KPXDDz/opJNOilbbyx9GxRBKAQAAJH+1lHtKuVrKXy+6KN6jAgAASvdQ6txzz9Xs2bM1ZMgQ7bXXXqpZs2bxjwwAAABxr5YaNoxqKQAAkECh1Pjx43XTTTfpvPPOK/4RAQAAICHUqCH95z+hp5SrpV55RbrggniPCgAApHWj86233jqangcAAIDUr5aqWDGcf+89ad68eI8IAACkdSh14403avDgwZo+fXrxjwgAAAAJw10aXC1lq1axEh8AAIjz9L1jjz1Wy5cvV6tWrXTggQeqcePGKlu2bJ7buJLq3nvvLa5xAgAAIE6OOUZ6801pxYpQLXX88VKdOtwdAAAgDqHUp59+qosuukhLly7VMHe/LAChFAAAQOpUSx12mDR0qLRypfTqq174Jt6jAgAAaTl975JLLlGNGjX03nvvaf78+VqzZs1ap8zMzOIfLQAAAOLi2GOlChXC+XfeobcUAACIUyg1adIk9ezZUwcffHAUTgEAACC11aoVqqUsVi0FAABQ6qHU9ttvrwULFhTpFwMAACC5q6Xmz4/3iAAAQNqFUgMGDNBDDz2kb775pvhHBAAAgIRUu7Z06KHhPNVSAAAgLo3O77rrLlWvXl177723WrduraZNmxa4+t7rr79e5AECAAAgsaqlXCXlUOqtt6TjjguN0AEAAEollBozZkwUOjmMWrx4sSZMmLDWbXw9AAAAUkudOlLnzpIXYI5VS511VrxHBQAA0iaUmjp1avGPBAAAAEnh+OOld9+VVq0K1VKunqJaCgAAlEpPKQAAAKR3tdQhh4TzK1ZIr70W7xEBAIC0CqUyMzP1wgsv6IILLtAxxxyjsWPHRpd7Vb5XX31Vs2bNKs5xAgAAIIG4l1S5f2vu33xTWrgw3iMCAABpEUrNnz9f++yzj7p06aLnn39eb7zxhubMmRNdV61aNV166aW69957i3usAAAASBB164beUrZ8uTR0aLxHBAAA0iKUuvrqqzV+/Hi99957mjx5srKysrKv8yp8xx9/vN5+++3iHCcAAAASsLdU7mqpRYviPSIAAJDyodRrr72mSy65RAcffHCBq+xts802NEMHAABIcfXqSZ065VRL0VsKAACUeCjlvlHNmzdf5/WrVq3S6tWrN+VHAwAAIEmrpYYNo1oKAACUcCjVsmVLff/99+u8/v3331fr1q035UcDAAAgidSvLx10UDi/bJn0+uvxHhEAAEi5UGrEiBHZzczPPfdcPf7443rxxRez+0l5Gt+KFSt07bXX6t13341W5QMAAEDqO+GEvNVSixfHe0QAACClQqmOHTvqgw8+iM5fdtllOv3003XKKadE/aPMK/FVr15d/fr10/nnn69zzjmn5EYNAACAhNGgQU611NKlVEsBAIDC+fczrQ3LvcKeq6IeeeQRnXHGGXr55Zf166+/as2aNdG0vhNPPFEdOnQo7I8FAABAilRL+fPLzEzpjTeko46SqlWL96gAAEBKhFIFad++fXQCAABAenO11IEHurdoqJZyMNWlS7xHBQAAUqbRuSukAAAAgIKceKJUtmw471BqyRL2EwAAKKZQ6rTTTlPZsmULdSoX63YJAACAtLDZZtIBB4TzDqTc9BwAAGBdNio5Ouigg7IbmwMAAAAFVUt99JG0Zo302mvSEUdIVauynwAAQBFDKTc29yp7AAAAQEEaNvSqzSGYcrXUm29KJ53EvgIAAEWcvgcAAABsiEOoMv++ynS1lBufAwAA5EcoBQAAgGLVqJG0//7h/OLFoVoKAAAgP0IpAAAAlEi1VGzhZldLLVvGTgYAAJsYSq1Zs4Z+UgAAACiUzTfPqZZatIhqKQAAkOCVUiNGjNARRxyhzTffXBkZGXrNH6vlsnjxYnXr1k2NGzdW5cqV1bp1aw0ZMiRu4wUAAEDhqqWGDpWWL2dvAQBSg1eZHTvWOUb46m0keSi1ZMkS7bTTTho8eHCB119++eV699139cwzz2jixInq3r17FFK98cYbpT5WAAAArN8WW0j77RfOUy0FAEgVI0dKp50mnX66dOGF4au3fTmSOJQ69NBDdcstt+iYY44p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aYz3iygp5UrsJyNh/f777/r888+1ZMkS7bjjjmrbtm32k0yZMuSU6WLq1Kl68803tXDhQm2//fY66qij4j0kxMGYMWN0zDHH6Pzzz1ejRo20xRZbcD+k6ePBl19+qfnz52vbbbdVx44do+cDvwD18wPSw7Rp0/TVV19pzpw52nXXXaPXB0hPo0eP1m677aZ3331XnTp1ivdwECc//fSTbrzxxui5oVKlSnrttdd4r5CGfP9XqVJFFSpU4HVBGvvzzz81ceJELVq0SLvvvruaNm1abD+bUCrNjB07Nnqz0bp16+h8kyZNtPXWW+uVV16JnmQIptIniDjkkEO088476+eff1bDhg1VtmxZ/ec//4n30FCKfvvtNx100EE69dRTdfnll6t8+fJ5rufxID34ueDAAw+MAojx48erRo0a0WPC0KFDozchBFPpcxwcfvjh2mqrrfT9999HH1b897//1YUXXhjvoaGU/fjjj9pvv/3Uo0cPAqk05ucDHwdHHnmkmjdvrpdfflmnnXaannnmmeh6nhvSg0OIs846S0cffXT0mFCxYkXu+zR9jdCpUyc1btw4eo3gUKpdu3YaOHBgsfx8ymLSiCujXA1x0kkn6eOPP47CiF69ekUBxV577aXVq1dnB1NIXb/88osOPfRQnX322VGllKvm/AmIy/SRXuXXzz77bPSC008oDiUfeugh3XLLLerfv390PZWTqe/vv/+O3mT48eCNN97QqFGj1L17d7333ntRQDF37lyma6SByZMnR288fSy89dZbmjBhglq2bBkdB0gv48aNU/v27dW1a1fddddd0WtCV035uPDrRaSHxYsX6+KLL44+tHr88cd122236dxzz1WDBg2yb0MVber7448/dPLJJ0cfYvox4MEHH9SKFSui+56pfOljwYIF0esDHwsffPCBpkyZEr1GfP/994ttpg2hVBrxg4iDqcMOO0zlypWLnlhOPPHE6BMP9ww44IADotvFpmwgNY+BBx54QJ07d1afPn2iJxVP2XLFlBPwnj17FlvijcQVeyHpqTrbbLNNdN6fdjikGjZsmAYPHhxVU7pM1wiqU5ePAT/eX3DBBdF2rVq1oueCVq1aRY8JRxxxRHQ5AWVq94t5+umno089e/fuHX0Kvvnmm+u8887T8OHDo6mdSA9+rO/bt2/0WtGvEcwfYvkDTT8WdOnSRaecckq8h4lSCqX8gWXsDadfN/g1gYPqvffeOwouR44cGV3He4bU5PvVrwn9fOBAyq8XX3jhhTzBFK8P08M///yj5cuXR6GUXyd62p6r5m644Yaoks7PDUVFKJVGPCXD1VCukorxdJ0999xTjzzyiGbOnKnrrrsuupxPP1KTq2FcKXfppZdG973v51tvvVXPP/+8li5dGn0SMmTIkOhBB6nPLyb8yfeLL76o2rVrR5Vzfnz4+uuvo8eL4447LrodgURq8xsPB1AxfkNauXJl3XvvvZoxY4buvvvuuI4PJc8vMj2lu3r16tn/757C6fMrV67kLkgTvr/vv//+KKDcY4891KFDh6iHjD+ocG+hK664Ipq24QoapDa/JvCbUFfLucL+mmuuid4ruKrWx4EfM/xa0dW2vGdITb5fHUq6Qs7vFf3+wNO6/Z7BH3AvW7aMQoY0UaNGjSiIjAXR5tcLPj6uvfbaqMLWjw9FQSiVZg8uxx9/fNTE1I0rc1++zz77RJ+GeQUuB1dITa6Qc/NaV0aZX2gMGjQomrbz6KOP6tVXX42Sbx8Hv/76a7yHixLmfjF+QenwYcstt4yedBxGuHrunnvuiaZ0ejoXUtdmm22mFi1a6KmnnorCJz83+FNw9x50RYTfnHqqN1L3k3B/QHH66afrnHPOiS6LffLtUKp+/frR80ZM7g+1kJp8v/sDiqpVq2revHlRIOU3pK6S8PQNv4789ttvo+uQuo8Lrpj06wBP5XXPSVfHeIq/AykfA2547oVyXnrppXgPFyXIVVKxDyj9XOHHgzZt2kQVUw6pHFz6fWSszxhSU6VKlaIPKTx1z73mcl/uxwO/h/j000+L9DtodJ7CXPk0adKk6AWle0P4xaXfhHr+p4MIv/l0PxnzbRxU+A2JO+r7ExKk1nHgKik3ta9Xr172dX6R6UoZHxuxptZ169aNnnhq1qwZ13Gj5B4P3MjYx4Gn6Pn8c889l31/x6ok/PjgNyVebQWp+Xjg5wUHkA4lPVXHn3z6xaWrIFxBaZ7m7RVbkVpc/RRbRcliz/nejj0G+FNw95Hwp6N2/fXXR71l/KGFjxuk3rEQq3jx/72n7Th8ckhlfo3g1wa+711ZnX9hDKTWY4L5w2p/KOHVON0/xv1nY1N+fZmbn7vpMVKHw2a/TjDft/6wMvb+IDMzMwohXE15ySWXRMGUjxd/iO0Pth1aFOdqbIgff2A9ffr06D2Anw98HLjfqB8T3HvWrxH/v707gY2y6ho4fkorUKBlEQqyWSkEQShQxKJAwipRiSBCZTNshYC0JRFbFkWNaJFFQJAgiEYrRAUVJZJGQGgQJAppEWxYWqDsCLWyb6W9b871m/nKKsJ0pn3m/0t4S6eDzDtzuPfc89znXL2gqXStoJ+93nWheYOuH+4GRSmH0kKDbqnThYeriq3VbW1kqgOHbrmdPn26bWCnhSrdHaWnregApFdH4Mw40ElFr3bp6QmuhFKLUMq1ENFbt7RQQTHC2eOBFiC0R4hOLHq1UwvScXFxtmCt947r7jmdWIoWMeG8ONDPWx/TfmK60NDPXhcaShPRP//8UyIjI3390uFB2v9BC4/auFh3xRVdhBa9DUeTS72VU3MCfe6MGTNk06ZNFKQcHguuGNCLVdqD1MWVI+jOmWbNmtkCBpwbB65Y0M9ZY0HnDT2RVfvOKS1Qa9+pFi1a+Prlw0P0Nn69PVNzQr0Y0bp1a5sjuC5CaAxoYUpzQ31cc0a9rVPniN9++42ClINyxRdeeMEWqrU+oJ+/ft66c17HgG7dutn8UMcM1+YWLUxqDUFj5K4ZOM6JEydMw4YNzfjx483BgwfNr7/+akaPHm0CAwPNzJkz7XMyMzNNz549TaNGjUx4eLjp3LmzqVKlisnIyPD1y0cxx0FQUJCZPXu2OXfu3DXPz8vLMxMnTjT333+/2bFjB5+DH8SBazw4dOiQGTdunKlVq5apWrWqad26talZs6ZJT0/39cuHF+aF9957z5w9e/aa52dnZ5tJkybZeNi5cyefg0Ps37/fRERE2M+1TZs2ZvPmzfbxwsLCG56rc0JUVJTp3bu3KV++vNm6dasPXjFKQiyow4cPmwkTJpAj+Fkc6NdLly6ZpKQk06xZM9OkSRPTo0cPExYWxprBQXbt2mVq1KhhEhMT7ee6ePFi07FjRzNnzpwbxoWCggL7ddSoUTZu/vjjD5+9bnjW0aNHTd26de2/d/1cly9fbp577jlTrlw5s2zZMvscHSMiIyPtWqFVq1amV69eJjQ01Pz+++/39HdTlHKgrKws07hx4xsmi+TkZBMQEGAWLFhgvz9y5IhdmLzxxhvmo48+Mnv27PHRK4a346BMmTJm0aJF7snlxx9/NCNHjrQFSgqT/jkenD592i46NC5WrVplcnJyfPSK4evx4Pjx4+b111839erVozDpILqwfOmll8zzzz9vli5daotNmlDeqhihyakWrytVqsS84OexsGHDBhMbG2vq169PLPhZHLgKEDov6AJ1xIgRZtq0aawZHEQvSsXExNjPtqgBAwbYTQs3s3DhQptDcvHSWbZs2WKLzwcOHHA/ppsY4uPjbWEqNTXVnVN+/fXXdvyYOnWqRy5eUpRyIL2aWbZsWXfF8sqVK+6f6UKj6M/gv3Ggg4trR5QuPlJSUuwVM/jfeLB9+3YfvkKUtPEgPz/fFiX1wgWc5bvvvrMXodTPP/9sr4DeqhihheqxY8ea3bt3++z1omTEwsmTJ82KFSu4WOGnceAqTMGZ9N93QkKC+eKLL+z3V69etV+/+eYb06FDB/u967Gi9u3b5/XXiuK1Zs0aW2zUi9TK9W9fP//hw4fbu6r27t1bLH93gP6P5+5CREmhRztrL4jvv/9eqlWrZnuFaA8hvRdYewTofZ96iob2COC4d/+OAz09Qx8r2ksC/hcHixYtsp8/44Fz3em8UPS0NTibnpYzd+5c2bdvn+032LZtW9tLJCcnRxo3buyOEfhnLGjvOT3oQGOBHMG/40B70OrhOHAe/bethxroKZuu7zUf1Fzhrbfesr1mtVeQPqb9prTpNZwpPz/f9onSg3C0j5QeguRqdK9jgJ7KrIceaC8xzR3vqYfUdf7pWgjH0eZjGiyJiYly6tQpm1RqUGnwaMOy3Nxcu/BgAepsdxIHrgUHBSn/jgP9PeOBs93pvADn089dafKZkJBgT9HR+Ni4caONjy5dutgmxsSDf8dCUlKSdO3a1cYCOYJ/x4FrTIDz6L/t6wtSSk/Z1M/cVZB67bXXbEFCCxdwpqCgINvkXBuX6ymLeiHTtTbQkxX1pD09kVN5siBl/26P/tdQYuigoQG1fPlyO6noyXuuI591IVKlShU7qGjwkWg4F3EA4gCMB7ieJpmuxYfr9BxNQDt16mSTztWrV0ulSpV44/wAsQDiAC5F14S6S0ZP2nMVpGbNmiUbNmxg96xDmf/LCcaMGSPZ2dl2p5yewqufvcaBCgsLs6e2axFbn+vJGgK37zmQa5udXhHXW3KWLFkie/fulR49eshff/0la9eulc2bN9sjfeFcxAGIAzAe4HaKXhXXHGHTpk12Z8QjjzzCG+dniAUQByhqzZo18s4778ijjz5qL1r88ssv0rp1a94kP1g75ufn22LU+vXrbWGqZ8+esn//flm5cqW9nbNp06Ye/7spSjkkeG71uCYZWu387LPPbDDpDimtgBZHMMF3iAMQB2A8wJ3MC9fTC1jTpk2ziw8tSrVs2ZI30mGIBRAH+K/jwVdffWV7COnuWe01FhUVxZvoAAUFBTYGivaLLHpRouimhrS0NFm2bJntM1mjRg0ZP368NG/evFheF0WpUkibTmq1WgeK2w0uNKV0NuIAxAEYD3A388L19Opnw4YNuWDlIMQCiAPcy3iQnp4uEyZMkDlz5jA3OMSuXbvs57lz505bZNQdUB07drzhedfHh9YU9Fdx9p6lp1Qps2fPHnsShlYrdTvdsGHDbIDcbHBxVTwpTjkPcQDiAIwHuNt54XrPPvssb6aDEAsgDnCv44HumtXdUq6exCjdMjMzbd9IPYm5VatWsm7dOnsXle580j5RRbniwlVD8HT/qJthp1QpkpeXJwMGDHA3G9OTkoYMGSLDhw//T1dEUboRByAOwHgA5gWQI4BcEcWxZmBDg7McP37c9o3UXVEzZ860j+luKe0XpoVH/ZmvUcEoRa5cuSLh4eH2ND1tYK5HeH/66afy8ccf25+7eki5FP09nIM4AHEAxgMwL4AcAeSKKI41AyezO0tGRobUr19fhg4dar/XRuZNmjSRJ554whYqS0LdgJ1SpYSrYq2Vzpo1a7p/Hx8fb78OHjxYYmNj3YFWtHkZnIM4AHEAxgMwL4AcAeSKYM2AO+0ltXbtWomLi7vm8a5du9pb+l599VXxNXZKlXC6rbIovR9YC1Ja+a5Vq5bMnz/fftXT9bTqffnyZUlKSpLJkyf77DXD84gDEAdgPADzAsgRQK4I1gy407Wjfn344Yftbrmij6ugoCC5evWq+/uFCxfa0/Z8gZ1SJdju3btl3rx5cvbsWVuMSkxMtLukXPSoxsDAQDlx4oSMGTPGftXA0i16Gzdu5OhOhyAOQByA8QDMCyBHALkiWDPgXteOrl5iAwcOlMcee0zGjh0rkyZNklmzZsm2bdtsEcvbKEqVUNp8LDo62jYeO3funBw7dkz27dsnixcvlqefflrKlSt3TVAdPnzYNivTHVRpaWkSGRnp6/8L8ADiAMQBGA/AvAByBJArgjUDPLV2VL169bLNz/V5ycnJsmHDBltP8AmDEqewsNAMHTrU9OnTx/39uXPnzMiRI0358uVNSkqKKSgocD//0qVL9mchISFmx44dPnzl8CTiAMQBGA/AvAByBJArgjUDPL127N27twkODra/tmzZYnwpyDelMNyO9ow6ffq01K1b193cumLFivY+T61u6j2hjRo1krZt29qdUtrUPCsrS1avXi3NmjXjzXUI4gDEARgPwLwAcgSQK4I1Azy5dtSD0apUqSIhISHy008/+byGwO17JdSoUaNk/fr1tlu+q7F52bJl7c/69Oljt+Zt3bpVgoODff1SUYyIAxAHYDwA8wLIEUCuCNYM8OTaUftQh4aGSkREhPgap++VMFrRVKNHj7bBohVNbV6uwaRBpRISEmzjMm1idv2fgzMQByAOwHgA5gWQI4BcEawZ4Mm1oxasVKtWrUpEQUpRlCphtKKpmjRpIv3797eVzKSkJLvFzlXl1O75euqenr53/Z+DMxAHIA7AeADmBZAjgFwRrBngybWjtv8paegpVQK5ttnFxcXZCue3335rt9t9+OGHcuHCBVm6dKkNKNf9onAm4gDEARgPwLwAcgSQK4I1A5y8dqQoVcLo7icNJj26UZuOTZw4UR566CGZM2eONGjQQMLDw21QrVixwlY74UzEAYgDMB6AeQHkCCBXBGsGOH3tSKPzEkS30pUpU0YOHDgg7dq1kx49etjKpsu6deukatWqNpBq167t09eK4kMcgDgA4wGYF0COAHJFsGaAP6wdKUr5gDYX27Ztm/Tr1++Gn+Xm5srjjz8uXbp0kQULFtj7Q7VxGT2jnIc4AHEAxgMwL4AcAeSKYM0Af147cvuel2VlZUmbNm3k/PnzkpeXZzvjF6XBo03JYmNj3UFUWoIJd444AHEAxgMwL4AcAeSKYM0Af187slPKi06fPm0DSJuQNW3aVKZMmSLvv/++xMfHu+8F1eZjcDbiAMQBGA/AvAByBJArgjUD/o0/rB3ZKeVFZ8+elTp16kj79u2le/fuEhISImPHjrU/06DSe0HhfMQBiAMwHoB5AeQIIFcEawb8G79YOxp4VU5Ojvv358+fN9OnTzcBAQFm7ty57sfz8/NNbm4un4yDEQcgDsB4AOYFkCOAXBGsGeDva0d2SnmhG77e4+naUvfggw+6m45VqFDBVjf1+6LVznHjxkloaKhMnjzZHu2I0o84AHEAxgMwL4AcAeSKYM0A1o7X8XVVzMkyMzPNwIEDTZcuXcyoUaPMDz/8cE0l0+XixYu22lm2bFkTHR1tq57p6ek+etXwNOIAxAEYD8C8AHIEkCuCNQNYO96IRufFZPfu3RIdHS1PPfWUhIeHS2pqqtx33332XtDZs2fb51y9elWCgoLcDcw6d+4sOTk5kpaWJs2bNy+ulwYvIg5AHIDxAMwLIEcAuSJYM4C14y3cpFCFe1RYWGgmTZpkYmJi3I+dOXPGvP3226Zly5ZmxIgR7scLCgrsr8TERLtDavv27bz/DkEcgDgA4wGYF0COAHJFsGYAa8dbc0Cr9pJH+0UdPXpUjh8/7n5Mu+QnJCTIoEGDJCMjQ6ZNm2Yf1275ubm5tueQPs4OKecgDkAcgPEAzAsgRwC5IlgzgLXjrVGU8jBtWq6ioqKkoKDA3r5VtDA1bNgwadWqlaxcudIe76jCwsIkOTlZWrRo4emXAx8hDkAcgPEAzAsgRwC5IlgzgLXjv7jNLircg+zsbFO9enUzbNgwc/bsWfftXOrgwYP2Vr3U1FTeY4cjDkAcgPEAzAsgRwC5IlgzgLXjzf3TZRseFxERIcuWLbONzoODg+XNN9+U6tWr259pw/PIyEipXLky77zDEQcgDsB4AOYFkCOAXBGsGcDa8eYoShWjTp06yfLly6Vv375y7NgxiYmJscWolJQUOXHihNSrV684/3qUEMQBiAMwHoB5AeQIIFcEawawdrxRgG6Xusnj8KD09HR5+eWXJScnR4KCgiQwMFC+/PJL21sK/oM4AHEAxgMwL4AcAeSKYM0A1o7/j6KUl5w5c0by8vJsc/MHHnjAfSsf/AtxAOIAjAdgXgA5AsgVwZoBrB3/QVEKAAAAAAAAXlfG+38lAAAAAAAA/B1FKQAAAAAAAHgdRSkAAAAAAAB4HUUpAAAAAAAAeB1FKQAAAAAAAHgdRSkAAAAAAAB4HUUpAAAAAAAAeB1FKQAAAAAAAHgdRSkAAAAPGzJkiISHh/O+AgAA3EbQ7X4IAACAfwQEBNzRW7F+/XreMgAAgDsQYIwxd/JEAAAAf7ZkyZJrvk9JSZE1a9bI559/fs3j3bp1k2rVqklhYaGUK1fOy68SAACg9KAoBQAAcBfi4uJk/vz5wvU9AACAu0NPKQAAgGLuKZWTk2Nv/5s5c6YtZDVo0EAqVKggTz75pBw6dMgWtqZMmSJ169aV4OBg6dmzp+Tl5d3w301NTZUOHTpIxYoVJSQkRJ555hnJzMzk8wMAAKUSPaUAAAC8ZOnSpXLlyhWJj4+3Rafp06dLTEyMdO7cWdLS0mT8+PGSnZ0t8+bNk1deeUU++eQT95/V2wQHDx4s3bt3l2nTpsmFCxdkwYIF0r59e8nIyKCxOgAAKHUoSgEAAHjJkSNHJCsrSypXrmy/LygokKlTp8rFixdl69atEhT0T2p28uRJW8DSopP2pTp37pwkJCRIbGysLFq0yP3f0yJV48aNJTk5+ZrHAQAASgNu3wMAAPCSvn37ugtSKjo62n4dNGiQuyDlelx3VGkRS2lD9VOnTkn//v0lNzfX/SswMNA+lxP/AABAacROKQAAAC+pX7/+Nd+7ClT16tW76eN///23/aq7q5Te5nczoaGhxfJ6AQAAihNFKQAAAC/RnU3/5XHXyX6FhYXuvlK1atW64XlFd1kBAACUFmQwAAAAJVxERIT9GhYWJl27dvX1ywEAAPAIekoBAACUcHrint6ipw3N8/Pzb/i5NkYHAAAobdgpBQAAUMJpQUpP4nvxxRclKipK+vXrJzVq1JCDBw/KqlWrpF27dvLBBx/4+mUCAAD8JxSlAAAASoEBAwZI7dq15d1335UZM2bI5cuXpU6dOtKhQwcZOnSor18eAADAfxZgXB00AQAAAAAAAC+hpxQAAAAAAAC8jqIUAAAAAAAAvI6iFAAAAAAAALyOohQAAAAAAAC8jqIUAAAAAAAAvI6iFAAAAAAAALyOohQAAAAAAAC8jqIUAAAAAAAAvI6iFAAAAAAAALyOohQAAAAAAAC8jqIUAAAAAAAAvI6iFAAAAAAAALyOohQAAAAAAADE2/4H9GIJH5GfLFQAAAAASUVORK5CYII=",
"text/plain": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"✓ Original time series plotted successfully!\n"
]
}
],
"source": [
"# Plot the original time series\n",
"plt.figure(figsize=(12, 6))\n",
"plt.plot(df_read.index, df_read['temperature'], marker='o', linewidth=2, markersize=6, \n",
" label='Original Temperature', color='blue', alpha=0.7)\n",
"\n",
"plt.xlabel('Time', fontsize=12)\n",
"plt.ylabel('Temperature [°C]', fontsize=12)\n",
"plt.title('Original Time Series - Temperature', fontsize=14, fontweight='bold')\n",
"plt.legend()\n",
"plt.grid(True, alpha=0.3)\n",
"plt.xticks(rotation=45)\n",
"plt.tight_layout()\n",
"plt.show()\n",
"\n",
"print(\"✓ Original time series plotted successfully!\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 3: Update the Time Series\n",
"\n",
"Now we'll make an update to change a value, add a tag, and add an annotation. We'll update the value at hour 2 (early in the series) to correct what appears to be an anomalous reading.\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Original value at 2025-01-01 02:00:00+00:00: 22.82 dimensionless°C\n",
"Value ID for update: 3\n",
"\n",
"Updating to: 24.5°C\n",
"Adding annotation: 'Manual correction: sensor reading was anomalous'\n",
"Adding tags: ['reviewed', 'corrected']\n",
"\n",
"✓ Update completed!\n",
" Updated records: 1\n",
" Skipped (no-op): 0\n",
" New value ID: 25\n"
]
}
],
"source": [
"# The time point we want to update (hour 2, early in the series for better visibility)\n",
"update_time = base_time + timedelta(hours=2)\n",
"\n",
"# Get the original value for reference\n",
"original_value = df_read.loc[update_time, 'temperature']\n",
"print(f\"Original value at {update_time}: {original_value}°C\")\n",
"\n",
"# Get the value_id for the time point we want to update (from the first read)\n",
"value_id = df_read.loc[update_time, 'value_id']\n",
"print(f\"Value ID for update: {value_id}\")\n",
"\n",
"# Create an update that:\n",
"# 1. Changes the value to a corrected temperature (e.g., 24.5°C instead of the original)\n",
"# 2. Adds an annotation explaining the correction\n",
"# 3. Adds tags to mark this as reviewed and corrected\n",
"corrected_value = 24.5\n",
"\n",
"print(f\"\\nUpdating to: {corrected_value}°C\")\n",
"print(f\"Adding annotation: 'Manual correction: sensor reading was anomalous'\")\n",
"print(f\"Adding tags: ['reviewed', 'corrected']\")\n",
"\n",
"# Create the update record using value_id (simplest approach - no need for run_id, tenant_id, etc.)\n",
"record_update = {\n",
" \"value_id\": value_id,\n",
" \"value\": corrected_value, # New corrected value\n",
" \"annotation\": \"Manual correction: sensor reading was anomalous\", # Annotation explaining the change\n",
" \"tags\": [\"reviewed\", \"corrected\"], # Tags for quality tracking\n",
" \"changed_by\": \"analyst@example.com\", # Who made the change\n",
"}\n",
"\n",
"# Execute the update using the SDK (handles connection internally)\n",
"result = td.update_records(updates=[record_update])\n",
"\n",
"print(f\"\\n✓ Update completed!\")\n",
"print(f\" Updated records: {len(result['updated'])}\")\n",
"print(f\" Skipped (no-op): {len(result['skipped_no_ops'])}\")\n",
"if result['updated']:\n",
" print(f\" New value ID: {result['updated'][0]['value_id']}\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 4: Read All Versions of the Time Series\n",
"\n",
"Now let's read the time series again, but this time with `all_versions=True` to see both the original version and the updated version.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"✓ Read 25 data points (including all versions)\n",
"\n",
"DataFrame shape: (25, 5)\n",
"\n",
"Columns: ['temperature', 'changed_by', 'change_time', 'tags', 'annotation']\n",
"\n",
"Index: None\n",
"\n",
"Note: With all_versions=True, we get both current and historical versions.\n",
"\n",
"First few rows:\n"
]
},
{
"data": {
"text/html": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"✓ Comparison plot created successfully!\n",
"\n",
"Key observation:\n",
" - The original time series (blue dashed line) shows the initial values\n",
" - The updated time series (red solid line) shows the corrected value at hour 12\n",
" - The green dotted line marks the point where the update was made\n"
]
}
],
"source": [
"# Read current version (default behavior - only is_current=true)\n",
"df_current = td.read(\n",
" series_id=series_id,\n",
" start_valid=base_time,\n",
" end_valid=base_time + timedelta(hours=24),\n",
" all_versions=False # Only current versions\n",
")\n",
"\n",
"# Create a DataFrame with original values for comparison (from our initial read)\n",
"df_original_plot = df_read.copy()\n",
"\n",
"# Plot both versions\n",
"plt.figure(figsize=(14, 7))\n",
"\n",
"# Plot original time series\n",
"plt.plot(df_original_plot.index, df_original_plot['temperature'], \n",
" marker='o', linewidth=2, markersize=6, \n",
" label='Original Time Series', color='blue', alpha=0.6, linestyle='--')\n",
"\n",
"# Plot current (updated) time series\n",
"plt.plot(df_current.index, df_current['temperature'], \n",
" marker='s', linewidth=2, markersize=6, \n",
" label='Updated Time Series (Current)', color='red', alpha=0.8)\n",
"\n",
"# Highlight the updated point\n",
"if update_time in df_current.index:\n",
" updated_value = df_current.loc[update_time, 'temperature']\n",
" original_value_at_update = df_original_plot.loc[update_time, 'temperature']\n",
" \n",
" # Draw a vertical line at the update point\n",
" plt.axvline(x=update_time, color='green', linestyle=':', linewidth=2, alpha=0.7, label='Update Point')\n",
" \n",
" # Annotate the change\n",
" plt.annotate(\n",
" f'Updated: {original_value_at_update:.2f}°C → {updated_value:.2f}°C',\n",
" xy=(update_time, updated_value),\n",
" xytext=(10, 20),\n",
" textcoords='offset points',\n",
" bbox=dict(boxstyle='round,pad=0.5', facecolor='yellow', alpha=0.7),\n",
" arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=0'),\n",
" fontsize=10,\n",
" fontweight='bold'\n",
" )\n",
"\n",
"plt.xlabel('Time', fontsize=12)\n",
"plt.ylabel('Temperature [°C]', fontsize=12)\n",
"plt.title('Original vs Updated Time Series - Showing the Change', fontsize=14, fontweight='bold')\n",
"plt.legend(loc='best', fontsize=10)\n",
"plt.grid(True, alpha=0.3)\n",
"plt.xticks(rotation=45)\n",
"plt.tight_layout()\n",
"plt.show()\n",
"\n",
"print(\"✓ Comparison plot created successfully!\")\n",
"print(f\"\\nKey observation:\")\n",
"print(f\" - The original time series (blue dashed line) shows the initial values\")\n",
"print(f\" - The updated time series (red solid line) shows the corrected value at hour 2\")\n",
"print(f\" - The green dotted line marks the point where the update was made\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Let's also create a detailed view showing just the updated time point\n",
"# Read with all_versions and return_value_id to see both versions\n",
"# Include tags_and_annotations to see tags and annotations\n",
"df_update_point = td.read(\n",
" series_id=series_id,\n",
" start_valid=update_time,\n",
" end_valid=update_time + timedelta(hours=1),\n",
" all_versions=True,\n",
" return_value_id=True,\n",
" tags_and_annotations=True\n",
")\n",
"\n",
"print(\"Detailed view of the updated time point:\")\n",
"print(\"=\" * 80)\n",
"\n",
"# Get current and original values\n",
"df_current_at_update = td.read(\n",
" series_id=series_id,\n",
" start_valid=update_time,\n",
" end_valid=update_time + timedelta(hours=1),\n",
" all_versions=False,\n",
" return_value_id=True\n",
")\n",
"\n",
"if update_time in df_current_at_update.index:\n",
" current_row = df_current_at_update.loc[update_time]\n",
" print(f\"\\nCurrent Version:\")\n",
" print(f\" Valid Time: {update_time}\")\n",
" print(f\" Value: {current_row['temperature']}°C\")\n",
" print(f\" Value ID: {current_row['value_id']}\")\n",
" \n",
" # Get original value from our initial read\n",
" if update_time in df_original_plot.index:\n",
" original_value_at_update = df_original_plot.loc[update_time, 'temperature']\n",
" print(f\"\\nOriginal Version (from initial data):\")\n",
" print(f\" Valid Time: {update_time}\")\n",
" print(f\" Value: {original_value_at_update}°C\")\n",
" print(f\" Note: Original version is marked is_current=false in database\")\n",
"\n",
"print(\"\\n\" + \"=\" * 80)\n",
"print(f\"\\nSummary:\")\n",
"print(f\" - TimeDB maintains both versions in the database\")\n",
"print(f\" - The original version is marked is_current=false\")\n",
"print(f\" - The updated version is marked is_current=true\")\n",
"print(f\" - Both versions are preserved for audit trail and historical analysis\")\n",
"print(f\" - Using value_id makes updates simple - no need for run_id, tenant_id, etc.\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 6: Update Multiple Values and View All Versions\n",
"\n",
"Now let's update multiple values (including the one we already updated) and then display all versions of these values in a pandas DataFrame.\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Prepared update for 2025-01-01 02:00:00+00:00: 24.5 dimensionless°C → 26.5°C\n",
"Prepared update for 2025-01-01 03:00:00+00:00: 24.3 dimensionless°C → 26.3°C\n",
"Prepared update for 2025-01-01 04:00:00+00:00: 24.21 dimensionless°C → 26.21°C\n",
"\n",
"✓ Batch update completed!\n",
" Updated records: 3\n",
" Skipped (no-op): 0\n"
]
}
],
"source": [
"# Read the current time series to get value_ids for multiple updates\n",
"df_current = td.read(series_id=series_id, return_value_id=True)\n",
"\n",
"# Define multiple time points to update (including the one we already updated at hour 2)\n",
"update_times = [\n",
" base_time + timedelta(hours=2), # Already updated, will update again\n",
" base_time + timedelta(hours=3), # New update\n",
" base_time + timedelta(hours=4), # New update\n",
"]\n",
"\n",
"# Prepare update records for all time points\n",
"updates = []\n",
"for update_time in update_times:\n",
" if update_time in df_current.index:\n",
" value_id = df_current.loc[update_time, 'value_id']\n",
" original_value = df_current.loc[update_time, 'temperature']\n",
" \n",
" # Create a new value (slightly different for each)\n",
" new_value = float(original_value) + 2.0 # Add 2°C to each value\n",
" \n",
" update_record = {\n",
" \"value_id\": value_id,\n",
" \"value\": new_value,\n",
" \"annotation\": f\"Batch correction: adjusted temperature by +2.0°C\",\n",
" \"tags\": [\"batch_corrected\", \"reviewed\"],\n",
" \"changed_by\": \"batch_processor@example.com\",\n",
" }\n",
" updates.append(update_record)\n",
" print(f\"Prepared update for {update_time}: {original_value}°C → {new_value}°C\")\n",
"\n",
"# Execute all updates\n",
"if updates:\n",
" result = td.update_records(updates=updates)\n",
" print(f\"\\n✓ Batch update completed!\")\n",
" print(f\" Updated records: {len(result['updated'])}\")\n",
" print(f\" Skipped (no-op): {len(result['skipped_no_ops'])}\")\n",
"else:\n",
" print(\"No updates to perform\")\n"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"All versions of the updated time points:\n",
"====================================================================================================\n",
"\n",
"DataFrame shape: (9, 5)\n",
"\n",
"Columns: ['temperature', 'changed_by', 'change_time', 'tags', 'annotation']\n",
"\n",
"Index type: \n",
"Index levels: ['valid_time', 'value_id']\n",
"\n",
"====================================================================================================\n"
]
},
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
series_key
\n",
"
temperature
\n",
"
changed_by
\n",
"
change_time
\n",
"
tags
\n",
"
annotation
\n",
"
\n",
"
\n",
"
valid_time
\n",
"
value_id
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
" \n",
" \n",
"
\n",
"
2025-01-01 01:00:00+00:00
\n",
"
2
\n",
"
21.22
\n",
"
None
\n",
"
2025-12-31 18:02:49.216106+00:00
\n",
"
None
\n",
"
None
\n",
"
\n",
"
\n",
"
2025-01-01 02:00:00+00:00
\n",
"
3
\n",
"
22.82
\n",
"
None
\n",
"
2025-12-31 18:02:49.216106+00:00
\n",
"
None
\n",
"
None
\n",
"
\n",
"
\n",
"
25
\n",
"
24.5
\n",
"
analyst@example.com
\n",
"
2025-12-31 18:02:55.195082+00:00
\n",
"
[corrected, reviewed]
\n",
"
Manual correction: sensor reading was anomalous
\n",
"
\n",
"
\n",
"
26
\n",
"
26.5
\n",
"
batch_processor@example.com
\n",
"
2025-12-31 18:05:03.277187+00:00
\n",
"
[batch_corrected, reviewed]
\n",
"
Batch correction: adjusted temperature by +2.0°C
\n",
"
\n",
"
\n",
"
2025-01-01 03:00:00+00:00
\n",
"
4
\n",
"
24.3
\n",
"
None
\n",
"
2025-12-31 18:02:49.216106+00:00
\n",
"
None
\n",
"
None
\n",
"
\n",
"
\n",
"
27
\n",
"
26.3
\n",
"
batch_processor@example.com
\n",
"
2025-12-31 18:05:03.277187+00:00
\n",
"
[batch_corrected, reviewed]
\n",
"
Batch correction: adjusted temperature by +2.0°C
\n",
"
\n",
"
\n",
"
2025-01-01 04:00:00+00:00
\n",
"
5
\n",
"
24.21
\n",
"
None
\n",
"
2025-12-31 18:02:49.216106+00:00
\n",
"
None
\n",
"
None
\n",
"
\n",
"
\n",
"
28
\n",
"
26.21
\n",
"
batch_processor@example.com
\n",
"
2025-12-31 18:05:03.277187+00:00
\n",
"
[batch_corrected, reviewed]
\n",
"
Batch correction: adjusted temperature by +2.0°C
\n",
"
\n",
"
\n",
"
2025-01-01 05:00:00+00:00
\n",
"
6
\n",
"
24.71
\n",
"
None
\n",
"
2025-12-31 18:02:49.216106+00:00
\n",
"
None
\n",
"
None
\n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
"series_key temperature changed_by \\\n",
"valid_time value_id \n",
"2025-01-01 01:00:00+00:00 2 21.22 None \n",
"2025-01-01 02:00:00+00:00 3 22.82 None \n",
" 25 24.5 analyst@example.com \n",
" 26 26.5 batch_processor@example.com \n",
"2025-01-01 03:00:00+00:00 4 24.3 None \n",
" 27 26.3 batch_processor@example.com \n",
"2025-01-01 04:00:00+00:00 5 24.21 None \n",
" 28 26.21 batch_processor@example.com \n",
"2025-01-01 05:00:00+00:00 6 24.71 None \n",
"\n",
"series_key change_time \\\n",
"valid_time value_id \n",
"2025-01-01 01:00:00+00:00 2 2025-12-31 18:02:49.216106+00:00 \n",
"2025-01-01 02:00:00+00:00 3 2025-12-31 18:02:49.216106+00:00 \n",
" 25 2025-12-31 18:02:55.195082+00:00 \n",
" 26 2025-12-31 18:05:03.277187+00:00 \n",
"2025-01-01 03:00:00+00:00 4 2025-12-31 18:02:49.216106+00:00 \n",
" 27 2025-12-31 18:05:03.277187+00:00 \n",
"2025-01-01 04:00:00+00:00 5 2025-12-31 18:02:49.216106+00:00 \n",
" 28 2025-12-31 18:05:03.277187+00:00 \n",
"2025-01-01 05:00:00+00:00 6 2025-12-31 18:02:49.216106+00:00 \n",
"\n",
"series_key tags \\\n",
"valid_time value_id \n",
"2025-01-01 01:00:00+00:00 2 None \n",
"2025-01-01 02:00:00+00:00 3 None \n",
" 25 [corrected, reviewed] \n",
" 26 [batch_corrected, reviewed] \n",
"2025-01-01 03:00:00+00:00 4 None \n",
" 27 [batch_corrected, reviewed] \n",
"2025-01-01 04:00:00+00:00 5 None \n",
" 28 [batch_corrected, reviewed] \n",
"2025-01-01 05:00:00+00:00 6 None \n",
"\n",
"series_key annotation \n",
"valid_time value_id \n",
"2025-01-01 01:00:00+00:00 2 None \n",
"2025-01-01 02:00:00+00:00 3 None \n",
" 25 Manual correction: sensor reading was anomalous \n",
" 26 Batch correction: adjusted temperature by +2.0°C \n",
"2025-01-01 03:00:00+00:00 4 None \n",
" 27 Batch correction: adjusted temperature by +2.0°C \n",
"2025-01-01 04:00:00+00:00 5 None \n",
" 28 Batch correction: adjusted temperature by +2.0°C \n",
"2025-01-01 05:00:00+00:00 6 None "
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Read all versions of the updated time points\n",
"# Use all_versions=True to see all historical versions, including change_time\n",
"df_all_versions = td.read(\n",
" series_id=series_id,\n",
" start_valid=base_time + timedelta(hours=1), # Start from hour 1\n",
" end_valid=base_time + timedelta(hours=6), # End at hour 6 to show the updated values\n",
" all_versions=True,\n",
" return_value_id=True,\n",
" tags_and_annotations=True\n",
")\n",
"\n",
"print(\"All versions of the updated time points:\")\n",
"print(\"=\" * 100)\n",
"print(f\"\\nDataFrame shape: {df_all_versions.shape}\")\n",
"print(f\"\\nColumns: {list(df_all_versions.columns)}\")\n",
"print(f\"\\nIndex type: {type(df_all_versions.index)}\")\n",
"if isinstance(df_all_versions.index, pd.MultiIndex):\n",
" print(f\"Index levels: {df_all_versions.index.names}\")\n",
"print(\"\\n\" + \"=\" * 100)\n",
"\n",
"# Display the DataFrame\n",
"df_all_versions\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Summary\n",
"\n",
"This notebook demonstrated:\n",
"\n",
"1. **Creating and inserting a time series**: Using `td.insert_batch()` to create and store initial time series data\n",
"\n",
"2. **Reading and visualizing time series**: Using `td.read()` with `return_value_id=True` to retrieve data and get value_ids for later updates\n",
"\n",
"3. **Updating time series**: Using `td.update_records()` with dictionary inputs to manually change:\n",
" - **Values**: Correcting erroneous data points\n",
" - **Tags**: Adding quality flags (e.g., \"reviewed\", \"corrected\")\n",
" - **Annotations**: Adding explanatory notes about the changes\n",
"\n",
"4. **Reading all versions**: Using `all_versions=True` flag to retrieve both current and historical versions of the data, including:\n",
" - `changed_by`: Who made the change\n",
" - `change_time`: When the change was made\n",
" - `tags` and `annotation`: When `tags_and_annotations=True`\n",
"\n",
"5. **Visualizing changes**: Plotting original vs updated versions to see the differences\n",
"\n",
"6. **Batch updates and version history**: Updating multiple values and viewing complete version history with all metadata columns\n",
"\n",
"**Key Takeaways:**\n",
"- TimeDB maintains a complete version history of all changes\n",
"- Each update creates a new version while preserving the old version\n",
"- The `all_versions=True` flag allows you to access the full audit trail with `changed_by` and `change_time` columns\n",
"- The `tags_and_annotations=True` flag includes tags and annotations as DataFrame columns\n",
"- When `all_versions=True` and `return_value_id=True`, the DataFrame uses a MultiIndex `(valid_time, value_id)` to preserve multiple versions\n",
"- Updates can modify values, annotations, and tags independently or together\n",
"- The `is_current` flag indicates which version is the active one\n",
"- All versions are preserved for compliance, auditing, and historical analysis\n",
"- Using `value_id` makes updates simple - no need for run_id, tenant_id, etc.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"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.14.2"
}
},
"nbformat": 4,
"nbformat_minor": 2
}