Fundamentals: Channels, labels, and collections¶
This notebook introduces the core backend data structures of vitabel: Channel, Label, IntervalLabel, and TimeDataCollection. Instead of loading data from external files, we build a small synthetic example from scratch to illustrate how these objects work together.
It is a good starting point if you want to understand how vitabel organizes time series, attached versus global labels, and interactive plotting layouts.
1. Imports¶
We import the core vitabel classes and create a deterministic random number generator so that the synthetic signals are reproducible.
import numpy as np
import pandas as pd
from vitabel import Channel, Label, IntervalLabel, TimeDataCollection
rng = np.random.default_rng(42)
2. Create channels¶
A Channel stores the primary signal data. Here, we create two channels with absolute timestamps: one longer, slowly varying signal and one shorter signal sampled at a higher rate.
time_a = pd.date_range("2020-02-02 00:00", "2020-02-05 00:00", periods=1001)
time_b = pd.date_range("2020-02-02 18:00", "2020-02-03 20:00", periods=4001)
ch1 = Channel(
name="synthetic trend",
time_index=time_a,
data=0.6 + 0.2 * np.sin(np.linspace(0, 6 * np.pi, len(time_a))) + 0.05 * rng.standard_normal(len(time_a)),
time_unit="s",
metadata={"source": "simulated example", "units": "a.u."},
)
ch2 = Channel(
name="synthetic waveform",
time_index=time_b,
data=2.0 + 0.15 * np.sin(np.linspace(0, 20 * np.pi, len(time_b))) + 0.03 * rng.standard_normal(len(time_b)),
time_unit="s",
metadata={"source": "simulated example", "units": "a.u."},
)
ch1, ch2
3. Create labels¶
Labels store annotations or derived values. In this example we create:
a local label attached to
ch1a global label that is not attached to any channel
a local interval label attached to
ch2a global interval label spanning a broader time window
Attached labels move together with their channel if a time offset is applied, whereas global labels remain independent.
lab1 = Label(
name="local markers",
time_index=["2020-02-02 19:34", "2020-02-03 12:34", "2020-02-04 12:34"],
data=[0.9, 0.95, 0.85],
time_unit="s",
anchored_channel=ch1,
)
lab2 = Label(
name="global events",
time_index=["2020-02-03 17:00", "2020-02-04 00:30"],
text_data=["review point", "handover"],
time_unit="s",
)
lab3 = IntervalLabel(
name="waveform intervals",
time_index=[
"2020-02-02 18:00",
"2020-02-02 23:15",
"2020-02-03 14:00",
"2020-02-03 18:42",
],
data=[2.0, 2.0],
time_unit="s",
anchored_channel=ch2,
)
lab4 = IntervalLabel(
name="study phase",
time_index=["2020-02-02 06:00", "2020-02-04 06:00"],
time_unit="s",
)
collection = TimeDataCollection(channels=[ch1, ch2], labels=[lab1, lab2, lab3, lab4])
4. Inspect the collection¶
A TimeDataCollection groups channels and labels into one object. It keeps track of local versus global labels and provides convenience methods for plotting and querying the stored data.
print(collection)
print()
collection.print_summary()
5. Plot channels with attached labels and automatic overviews¶
If include_attached_labels=True, vitabel automatically includes labels attached to the displayed channels. Setting channel_overviews=True adds overview panels to support navigation through a longer recording.
wg1 = collection.plot_interactive(
start="2020-02-02 00:00",
stop="2020-02-02 12:00",
time_unit="min",
include_attached_labels=True,
channel_overviews=True,
)
wg1
6. Plot with an explicit subplot layout¶
For more control, channels can also be assigned explicitly to subplots. This is the same mechanism used in the larger application-oriented example notebooks.
wg2 = collection.plot_interactive(
channels=[[0], [1]],
labels=[["global events"], ["study phase"]],
start="2020-02-02 00:00",
stop="2020-02-02 12:00",
time_unit="min",
)
wg2
Summary¶
This small synthetic example shows how vitabel represents time series and annotations independently of any specific file format. Once you are comfortable with these core objects, the larger examples in this documentation show how the same data structures scale to real workflows with imported medical device data.