How to Query Timestamps

TimeStamp, TimeIntervalStamp, boundary tables, PyArrow

How to Query Timestamps

Boundary tables, filtered timestamps, the TimeStamp / TimeIntervalStamp objects, and the underlying PyArrow tables.

import numpy as np

from timetoalign import TimeUnit
from timetoalign.timelines import Timeline

Setup: A Hierarchical Timeline

parent = Timeline(length=100, unit=TimeUnit.seconds, uid="parent")
parent.add_events(
    [
        {"id": "p1", "temporal_type": "instant", "event_type": "Beat", "instant": 0.0},
        {"id": "p2", "temporal_type": "instant", "event_type": "Beat", "instant": 50.0},
    ]
)

child1 = Timeline(length=20, unit=TimeUnit.seconds, uid="child1")
child1.add_events(
    [
        {"id": "c1a", "temporal_type": "instant", "event_type": "Note", "instant": 0.0},
        {
            "id": "c1b",
            "temporal_type": "instant",
            "event_type": "Note",
            "instant": 10.0,
        },
    ]
)

child2 = Timeline(length=15, unit=TimeUnit.seconds, uid="child2")
child2.add_events(
    [
        {"id": "c2a", "temporal_type": "instant", "event_type": "Note", "instant": 5.0},
    ]
)

parent.add_child(child1, offset=10)  # child1 spans [10, 30] on parent
parent.add_child(child2, offset=60)  # child2 spans [60, 75] on parent

Custom Coordinates

coords = [0.0, 15.0, 25.0, 50.0, 65.0, 100.0]
parent.to_dataframe(coordinates=coords)
axis (seconds) parent (seconds) child1 (seconds) child2 (seconds)
0 0.0 0.0 NaN NaN
1 15.0 15.0 5.0 NaN
2 25.0 25.0 15.0 NaN
3 50.0 50.0 NaN NaN
4 65.0 65.0 NaN 5.0
5 100.0 100.0 NaN NaN
# Efficient numpy array query
coords = np.linspace(0, 100, 21)
parent.to_dataframe(coordinates=coords)
axis (seconds) parent (seconds) child1 (seconds) child2 (seconds)
0 0.0 0.0 NaN NaN
1 5.0 5.0 NaN NaN
2 10.0 10.0 0.0 NaN
3 15.0 15.0 5.0 NaN
4 20.0 20.0 10.0 NaN
5 25.0 25.0 15.0 NaN
6 30.0 30.0 20.0 NaN
7 35.0 35.0 NaN NaN
8 40.0 40.0 NaN NaN
9 45.0 45.0 NaN NaN
10 50.0 50.0 NaN NaN
11 55.0 55.0 NaN NaN
12 60.0 60.0 NaN 0.0
13 65.0 65.0 NaN 5.0
14 70.0 70.0 NaN 10.0
15 75.0 75.0 NaN 15.0
16 80.0 80.0 NaN NaN
17 85.0 85.0 NaN NaN
18 90.0 90.0 NaN NaN
19 95.0 95.0 NaN NaN
20 100.0 100.0 NaN NaN

Boundary Tables

parent.get_boundary_table().to_pandas()
axis parent child1 child2
0 0.0 0.0 NaN NaN
1 10.0 10.0 0.0 NaN
2 30.0 30.0 20.0 NaN
3 60.0 60.0 NaN 0.0
4 75.0 75.0 NaN 15.0
5 100.0 100.0 NaN NaN

Filtering Events

parent.get_events(event_type="Note", include_children=True).to_dataframe()
id name temporal_type event_type start end duration source_timeline
0 c1a NaN instant Note 10.0 None None child1
1 c1b NaN instant Note 20.0 None None child1
2 c2a NaN instant Note 65.0 None None child2
parent.get_events(event_type="Beat", include_children=True).to_dataframe()
id name temporal_type event_type start end duration source_timeline
0 p1 NaN instant Beat 0.0 None None NaN
1 p2 NaN instant Beat 50.0 None None NaN

PyArrow Tables

For large datasets, get_timestamp_table() returns a PyArrow Table directly — convert to pandas only when needed.

table = parent.get_timestamp_table()
{
    "rows": table.num_rows,
    "columns": table.column_names,
}
{'rows': 8, 'columns': ['axis', 'parent', 'child1', 'child2']}
table.to_pandas().head()
axis parent child1 child2
0 0.0 0.0 NaN NaN
1 10.0 10.0 0.0 NaN
2 20.0 20.0 10.0 NaN
3 30.0 30.0 20.0 NaN
4 50.0 50.0 NaN NaN

The TimeStamp Object

Query a single coordinate and get all related values on demand.

ts = parent.get_timestamp(15.0)
ts.to_dict()
{'parent': 15.0, 'child1': 5.0, 'child2': None}
# Access child coordinates via subscript
{
    "parent": ts.axis,
    "child1": ts["child1"],
    "child2": ts["child2"],
}
{'parent': 15.0, 'child1': 5.0, 'child2': None}

TimeIntervalStamp

interval = parent.get_interval_stamp(20.0, 60.0)
{
    "axis_duration": interval.duration,
    "child1_interval": interval["child1"],
}
{'axis_duration': 40.0, 'child1_interval': None}
interval.zip_intervals()
{'parent': (20.0, 60.0)}

Coordinates with Units

TimeStamp and TimeIntervalStamp can produce proper Coordinate objects that carry their unit.

ts = parent.get_timestamp(25.0)
axis_coord = ts.axis_coordinate
{
    "value": axis_coord.value,
    "unit": axis_coord.unit,
}
{'value': 25.0, 'unit': "seconds"}
child1_coord = ts.get_coordinate("child1")
{
    "child1 value": child1_coord.value,
    "child1 unit": child1_coord.unit,
}
{'child1 value': 15.0, 'child1 unit': "seconds"}

Unit Metadata in PyArrow Tables

table = parent.get_timestamp_table(coordinates=[0.0, 25.0, 50.0])

for field in table.schema:
    if field.metadata:
        unit = field.metadata.get(b"unit", b"N/A").decode()
        tl_id = field.metadata.get(b"timeline_id", b"N/A").decode()
        print(f"{field.name}: unit={unit}, timeline_id={tl_id}")
axis: unit=seconds, timeline_id=parent
parent: unit=seconds, timeline_id=parent
child1: unit=seconds, timeline_id=child1
child2: unit=seconds, timeline_id=child2