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.get_timestamps(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.get_timestamps(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

Filtered Timestamps

parent.get_timestamps_filtered({"event_type": "Note"})
/tmp/ipykernel_32896/42739212.py:1: DeprecationWarning: get_timestamps_filtered() is deprecated. Use get_events(**filters) combined with get_timestamps() instead.
  parent.get_timestamps_filtered({"event_type": "Note"})
axis parent child1 child2
0 10.0 10.0 0.0 NaN
1 20.0 20.0 10.0 NaN
2 65.0 65.0 NaN 5.0
parent.get_timestamps_filtered({"event_type": "Beat"})
/tmp/ipykernel_32896/681909530.py:1: DeprecationWarning: get_timestamps_filtered() is deprecated. Use get_events(**filters) combined with get_timestamps() instead.
  parent.get_timestamps_filtered({"event_type": "Beat"})
axis parent child1 child2
0 0.0 0.0 NaN NaN
1 50.0 50.0 NaN 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