{
"cells": [
{
"cell_type": "markdown",
"id": "8217d056-c75e-446a-930d-24c5364d2041",
"metadata": {},
"source": [
"# Use Case 2: Data from multiple sources in an animal experiment\n",
"\n",
"
\n",
"\n",
"This notebook illustrates the usage of the `vitabel` module to visualize, annotate and process time-series data from the medical field. Please find the detailed, searchable documentation here: \n",
"[](https://vitabel.readthedocs.io/en/latest/?badge=latest)\n",
"\n",
"In this case we analyze data collected in an animal laboratory experiment of cardiopulmonary resuscitation. This notebook in particular demonstrates the capabilities of `vitabel` to **align** time-series data recorded by **multiple devices** with unsynchronized clocks.\n",
"\n",
"
\n",
"\n",
"If you have never worked with _Jupyter Notebooks_ before, you may find this guide helpful: **[Beginners Guide to Jupyter Notebooks](https://mybinder.org/v2/gh/jupyter/notebook/HEAD?urlpath=%2Fdoc%2Ftree%2Fdocs%2Fsource%2Fexamples%2FNotebook%2FRunning+Code.ipynb)**"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8865d157-3791-4855-a97f-54350306fd38",
"metadata": {},
"outputs": [],
"source": [
"from vitabel import Vitals, IntervalLabel\n",
"\n",
"from pathlib import Path\n",
"import pandas as pd"
]
},
{
"cell_type": "markdown",
"id": "53b87624-1de6-4b01-a602-11836d567ac6",
"metadata": {},
"source": [
"## 1. Loading Data"
]
},
{
"cell_type": "markdown",
"id": "d33399f4-a038-46fe-add0-d65e80608df5",
"metadata": {},
"source": [
"
\n",
"\n",
"We begin by specifying the file paths for the multiple data sources. In this use case, three different types of \n",
"files are read: data from the mechanical CPR device is stored in an XML export from a proprietary format. Invasive blood pressure was recorded from\n",
"a patient monitor via [VitalRecorder](https://doi.org/10.1038/s41598-018-20062-4).\n",
"Airflow, airway pressure were recorded each by a separate single board computer and stored in CSV files.\n",
"\n",
"
\n",
"\n",
"A new instance of the `Vitals` class is initialized and all data is loaded from the files.\n",
"As ventilatory parameters were recorded in UNIX time, `time_start` and `time_unit` must be set accordingly.\n",
"\n",
"
\n",
"\n",
"By calling `get_channel_infos` with **keyword arguments (`kwargs`)** we can filter the list of channels, for example by the _source_ set in their `metadata`. \n",
"The argument `kwargs` can be used the same way with other functions to retrieve channels and labels or details on them.\n",
"\n",
"
\n",
"\n",
"We generated a new `IntervalLabel` to later annotate noisy segements of the invasive blood pressure recordings, for example due to sampling of blood gas samples.\n",
"\n",
"
\n",
"\n",
"Calling the `print_data_summary` method gives us information about channels and labels and their **attachment**.\n",
"Shifting the time index of a channel will also shift all labels attached to it accordingly.\n",
"\n",
"
\n",
"\n",
"The plotstyle of the channels is adapted by the `set_channel_plotstyle` method. All keyword arguments of matplotlib's [axes.plot](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.plot.html) can be set in the plotstyle dictionary.\n",
"\n",
"
"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "861e6074-5eb9-434d-8465-55817baa2dc8",
"metadata": {},
"outputs": [],
"source": [
"case.set_channel_plotstyle(capno_channel, color=\"goldenrod\", lw=1, alpha=0.8)\n",
"case.set_channel_plotstyle(\"airflow\", color=\"blue\", lw=1, alpha=0.8) # another way to call the channel by its name\n",
"case.get_channel(\"airway_pressure\").plotstyle = {\"color\": \"green\", \"lw\": 1, \"alpha\": 0.8} # the plotstyle can also be set by direct assignment\n",
"case.set_channel_plotstyle(ibp_channel, color=\"red\", lw=1, alpha=0.8)\n",
"case.set_channel_plotstyle(cc_channel, color=\"purple\", marker=\"o\", alpha=0.8, linestyle=\"\", label=\"chest compressions\") # be aware that we define the _label_ of the plot legend here\n",
"case.set_label_plotstyle(aline_noise, color=\"dimgray\", lw=3, alpha=0.8)"
]
},
{
"cell_type": "markdown",
"id": "b006ed0c-31cf-44ef-9a85-1d8cfbb60343",
"metadata": {},
"source": [
"
\n",
"\n",
"An interactive plot is initialized. The menu an explanation to **align** the channels is given in the tab `Align Timelines`. We can first align the chest compressions to the IBP and than select both and align them with the first artefact of a chest compression in the airway pressure. Afterward, we can **label** noisy segments in the blood-pressure signal the the menu offered in the `Annotate`-Tab. Be aware that we have added an `IntervaLabel` which has to be defined by a start and an end, thus clicking twice.\n",
"\n",
"
"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8e202974-35f4-481c-aa54-2241b42a8670",
"metadata": {},
"outputs": [],
"source": [
"plot = case.plot_interactive(\n",
" channels=[\n",
" [flow_channel, \"cc\"], # flow_channel is added directly, while the cc channel is added by its name\n",
" [4], # the capnography channel is added via its channel index\n",
" [pressure_channel],\n",
" [ibp_channel],\n",
" ],\n",
" labels=[[], [], [], [\"IBP noise\"]],\n",
" channel_overviews=[[ibp_channel]],\n",
" time_unit=\"s\",\n",
" subplots_kwargs={\"figsize\": (16.5, 8)},\n",
")\n",
"\n",
"plot"
]
},
{
"cell_type": "markdown",
"id": "2fd99fa9-f56c-4966-a83d-03222a258c75",
"metadata": {},
"source": [
"## 4. Storing Data\n"
]
},
{
"cell_type": "markdown",
"id": "8bc7ac13",
"metadata": {},
"source": [
"
\n",
"\n",
"As we have seen already, the `Vitals.info` method prints a compact overview of all channels and labels contained in a given collection.\n",
"\n",
"