Timeline

timelines.Timeline(
    length=0,
    unit=None,
    number_type=None,
    id_prefix='tl',
    uid=None,
    name=None,
    locked=False,
    meta=None,
)

A positive coordinate axis with events and nested child timelines.

A Timeline represents a temporal dimension in one of three domains (Logical, Physical, Graphical) with either continuous or discrete coordinates. It stores events in an EventData and can contain nested child timelines (segments) at specified offsets.

Intended usage: This base class provides the full Timeline API but does not enforce domain or modality constraints. For typical usage, prefer one of the six concrete subclasses or the create_timeline() factory function:

  • ContinuousLogicalTimeline – beats, quarters, measures (Fraction)
  • DiscreteLogicalTimeline – ticks (int)
  • ContinuousPhysicalTimeline – seconds, ms, minutes (float)
  • DiscretePhysicalTimeline – samples, frames (int)
  • ContinuousGraphicalTimeline – cm, inches, points (float)
  • DiscreteGraphicalTimeline – pixels (int)

These subclasses restrict allowed units and number types to prevent accidental cross-domain errors and provide sensible defaults.

Direct instantiation of Timeline is appropriate for internal use, generic algorithms that operate across domains, or advanced scenarios where domain constraints are intentionally relaxed.

If you have a Timeline instance and need the appropriate typed subclass, use :meth:to_typed.

Attributes

Name Type Description
id str Unique identifier for this timeline.
unit TimeUnit The time unit for coordinates (e.g., seconds, quarters, pixels).
number_type NumberType The numeric type for coordinates (int, float, Fraction).
domain Domain The temporal domain (derived from unit).
origin Coordinate The start coordinate (always 0).
length Coordinate The end coordinate.
is_locked bool Whether the timeline can be modified.
is_discrete bool Whether the timeline uses discrete coordinates.
is_continuous bool Whether the timeline uses continuous coordinates.

Examples

>>> # Preferred: use concrete subclasses
>>> from timetoalign.timelines import ContinuousPhysicalTimeline
>>> audio = ContinuousPhysicalTimeline(length=180.0)
>>> # Or use the factory to auto-select the right subclass
>>> from timetoalign.timelines import create_timeline
>>> tl = create_timeline(loader)
>>> # Direct base class (internal/advanced use)
>>> from timetoalign.core import TimeUnit
>>> tl = Timeline(length=100, unit=TimeUnit.seconds)

Methods

Name Description
add_child Embed a child timeline at the specified offset.
add_conversion_map Add a ConversionMap to this timeline.
add_events Add events to the timeline.
add_external_references Append incoming external references to this timeline.
add_flow_map Add a FlowMap to this timeline.
add_region Add or create a named Region on this timeline.
append_child Append a child timeline at the current end of this timeline.
apply_flow Yield the unfolded timeline for an attached FlowMap.
as_segment_line Cast a structurally contiguous hierarchy to a parameterized line.
convert_to Convert coordinates to another unit using attached C-Maps.
create_child Create and embed a child selected by this timeline’s spawn hook.
create_child_from_region Create a child timeline from a named region (partitioning).
create_children_from_boundaries Create children spanning consecutive boundary coordinates.
create_children_from_regions Create children from multiple regions (batch partitioning).
create_flow_map Construct a FlowMap from interval-like descriptors, attach it, return it.
create_region Create a new named Region and attach it to this timeline.
create_regions_by_grouping Create regions by grouping adjacent events on a field value.
create_regions_by_splitting Create contiguous regions by splitting at events matching a predicate.
create_regions_from_boundaries Create contiguous regions from boundary coordinates.
create_segment_line Create a SegmentLine by segmenting at boundary coordinates.
create_segment_line_by_grouping Create a SegmentLine by grouping adjacent events on a field value.
create_segment_line_by_splitting Create a SegmentLine by splitting at events matching a predicate.
create_segment_line_from_regions Create a SegmentLine from contiguous regions.
derive Create a derivative timeline in a different unit via C-Map conversion.
diagram Generate ASCII diagram for this timeline.
empty Create an empty Timeline with length 0.
export_to_csv Export timeline data to a CSV file.
fold Convert an unfolded coordinate to a folded coordinate.
from_dict Create a Timeline from a dictionary.
from_event_data Create a Timeline from an existing EventData.
from_events Create a Timeline from event dictionaries.
get_boundary_table Get timestamps for timeline boundaries only.
get_child Retrieve a child timeline by ID.
get_child_offset Get the offset of a child timeline.
get_children_at Return all children whose extent contains the given coordinate.
get_conversion_map Get a conversion map by target unit or by name/id.
get_coordinate Dispatch a positional or event-key coordinate query.
get_coordinate_at Resolve one position onto this timeline’s canonical axis.
get_coordinate_for Return an event’s start coordinate on this timeline.
get_coordinates_at Resolve a collection of positions onto this timeline.
get_coordinates_for Return event-start coordinates for a collection of event IDs.
get_event Look up a single event by its id field.
get_events Filter and retrieve events.
get_events_at Get all events active at a specific coordinate.
get_flow_map Get an attached FlowMap by id.
get_interval_stamp Get a TimeIntervalStamp for a coordinate range.
get_region Get a Region by name.
get_regions_at Return all regions containing the given coordinate.
get_slice Extract a portion of this timeline as a new, independent timeline.
get_timestamp Get a timestamp whose axis is written in this timeline’s own type.
get_timestamp_at Alias for get_timestamp() for API consistency with TimelineGroup.
get_timestamp_of Get the timestamp for a specific event by its ID.
get_timestamp_table Generate a timestamp table as a PyArrow Table.
get_timestamps_of Get timestamps for multiple events, returned as a DataFrame.
has_child Check if a child with the given ID exists.
has_flow_map Check if a FlowMap with the given id is attached.
has_region Check if a region exists.
is_segment_line Return whether children exactly and contiguously cover this timeline.
iter_children Iterate over child timelines.
iter_regions Iterate over all regions in insertion order.
list_children List child timeline IDs.
list_flow_maps List all attached FlowMap ids.
list_regions List all region names.
make_coordinate Create a Coordinate in this timeline’s unit.
resolve_subclass Return the most specific Timeline subclass for a unit/number_type pair.
summary Get a summary of the timeline.
to_dataframe Generate timestamps as a pandas DataFrame with formatted field names.
to_dict Convert timeline to a dictionary for serialization.
to_typed Return this timeline re-instantiated as the appropriate typed subclass.
unfold_coordinate Convert a folded coordinate to unfolded coordinates.
validate_child Validate that a timeline can be added as a child.

add_child

timelines.Timeline.add_child(
    child,
    offset,
    allow_expansion=False,
    use_conversion_map=None,
)

Embed a child timeline at the specified offset.

The child timeline will be locked after being added. Parent-child coordinate conversion uses exact offset arithmetic.

A timeline can accommodate events and other timelines, called Children, as long as they use the same measuring unit.

When the child uses a different unit than the parent, set use_conversion_map to automatically convert the child to the parent’s unit via a C-Map. The parent must have a C-Map whose target_unit matches the child’s unit, so that inverting it yields the child_unit -> parent_unit conversion. The child’s events are copied with converted coordinates; the original child is NOT modified.

The converted child receives the ID {child.id}[{parent.unit}].

Parameters

Name Type Description Default
child Timeline The timeline to embed. required
offset CoordinateSpec The start coordinate on this timeline, in the parent’s unit. When use_conversion_map is set, the offset must already be expressed in the parent’s unit (e.g. samples). required
allow_expansion bool If True, expand this timeline if needed. False
use_conversion_map ConversionMapsSpec Conversion map specification for unit conversion. Accepts the same formats as the conversion_maps parameter in timestamp functions: - None (default): No conversion; units must match. - True: Auto-select a parent C-Map whose target unit matches the child’s unit. - str: Look up by C-Map ID or target unit name. - TimeUnit: Find by target unit. - ConversionMap: Use directly. None

Raises

Name Type Description
TypeError If child is not a Timeline.
ValueError If units don’t match (and no conversion map given) or would exceed bounds.
RuntimeError If this timeline is locked.

add_conversion_map

timelines.Timeline.add_conversion_map(cmap)

Add a ConversionMap to this timeline.

Any map with a target_unit is automatically registered in the unified timestamp system so that :meth:get_timestamp can resolve coordinates in that unit. The map is stored as-is: TableMap instances honor their own kind (nearest/previous/next/linear) and extrapolate policy directly, and analytical maps (e.g. ScalarMap, LinearMap) are likewise stored directly.

Parameters

Name Type Description Default
cmap ConversionMap[Any] The ConversionMap to add. required

Raises

Name Type Description
ValueError If the map’s source unit is incompatible.

add_events

timelines.Timeline.add_events(rows, allow_expansion=False)

Add events to the timeline.

Only event_type and a coordinate are strictly required per dict. Missing fields are filled in automatically:

  • id: auto-generated (e000001, e000002, …).
  • temporal_type: inferred from keys – "interval" when both start and end (or duration) are present, "instant" otherwise.

Parameters

Name Type Description Default
rows list[dict[str, Any]] List of event dictionaries. Required keys: - event_type: class name (e.g. "Beat", "Note") - instant: coordinate (for instant events), or - start, end: coordinates (for interval events) required
allow_expansion bool If True, expand timeline if events exceed length. False

Raises

Name Type Description
ValueError If events exceed length and expansion not allowed.
RuntimeError If timeline is locked and expansion not allowed.

Examples

>>> tl.add_events([
...     {"event_type": "Beat", "instant": 0.0},
...     {"event_type": "Note", "start": 0.0, "end": 0.5},
... ])

add_external_references

timelines.Timeline.add_external_references(rows, *, validate=True)

Append incoming external references to this timeline.

Rows are appended to the existing table; nothing is replaced or deduplicated. access_points defaults to an empty list and comment to None when a row omits them.

Parameters

Name Type Description Default
rows list[dict[str, Any]] | pa.Table Row dicts (or a PyArrow table) with the canonical columns event_id, external_id, access_points, and comment. Unknown columns are rejected. required
validate bool If True (default), every event_id must name an event of this timeline’s own event table. True

Returns

Name Type Description
Self self, so calls can be chained.

Raises

Name Type Description
KeyError If validate is True and one or more event_id values are absent from this timeline’s events. The message names all missing ids, sorted.
TypeError If a row or an access point has the wrong type.
ValueError If a row carries unknown columns or ill-typed values.

Examples

>>> tl.add_external_references([
...     {
...         "event_id": "e1",
...         "external_id": "p2",
...         "access_points": [
...             {"uri": "Analisi_1/L1.pnml", "kind": "relative_path"}
...         ],
...         "comment": "Analisi_1_L1_A",
...     }
... ])

add_flow_map

timelines.Timeline.add_flow_map(flow_map, id=None)

Add a FlowMap to this timeline.

FlowMaps enable coordinate transformation for timelines with flow control (repeats, jumps, D.S., D.C., etc.). They are created by timetoalign.ScoreFlowController and added to the timeline for later use.

Design Decision: Timelines store FlowMaps, NOT FlowControllers. FlowControllers are factories that produce FlowMaps.

Parameters

Name Type Description Default
flow_map 'FlowMap' The FlowMap to add. required
id str | None Identifier for this FlowMap. If None, uses flow_map.id. Common values: “default”, “atomic”, “single”. None

Examples

>>> controller = ScoreFlowController(measure_data)
>>> flow_map = controller.create_flow_map()
>>> timeline.add_flow_map(flow_map)
>>> timeline.get_flow_map("default")  # Retrieve later
FlowMap(default: 5 sections)

add_region

timelines.Timeline.add_region(
    region_or_name,
    start=None,
    end=None,
    *,
    meta=None,
)

Add or create a named Region on this timeline.

Overloaded for backward compatibility: - add_region(Region) — attach a pre-existing Region object. - add_region(name, start, end) — delegate to :meth:create_region.

Under the unified verb×noun API, add means “attach an existing object” while create means “construct + attach + return”.

Parameters

Name Type Description Default
region_or_name Region | str A Region object (new) or a string name (legacy). required
start CoordinateSpec | None Start coordinate (only when region_or_name is a string). None
end CoordinateSpec | None End coordinate (only when region_or_name is a string). None
meta dict[str, Any] | None Optional metadata dictionary. None

Returns

Name Type Description
Region The Region object (either the one passed in or the newly created one).

Raises

Name Type Description
ValueError If region name already exists, end < start, or arguments are inconsistent.

Examples

>>> # New API — attach a pre-existing Region
>>> r = Region("Chorus", Coordinate(10, TimeUnit.seconds),
...            Coordinate(30, TimeUnit.seconds))
>>> tl.add_region(r)
>>> # Legacy API (delegates to create_region)
>>> tl.add_region("Verse", 30, 50, meta={"repeat": 2})

append_child

timelines.Timeline.append_child(child, *, name=None, uid=None)

Append a child timeline at the current end of this timeline.

The child is placed at offset = self.length, so successive calls stack children end-to-end and expand this timeline. Because the child is a fresh, unlocked timeline, its identity may be set here: uid becomes the child’s ID (the key under which it is stored and retrieved) and name its human-readable name — both applied before the child is locked by :meth:add_child.

Parameters

Name Type Description Default
child 'Timeline' The timeline to append. Must be fresh (parentless) and share this timeline’s unit. required
name str | None Human-readable name for the child. Applied when given. None
uid str | None Identifier for the child; also the key for :meth:get_child. Applied when given. None

Raises

Name Type Description
TypeError If child is not a Timeline.
ValueError If units don’t match.
RuntimeError If this timeline is locked.

Examples

>>> parent = ContinuousLogicalTimeline(length=0)
>>> parent.append_child(
...     ContinuousLogicalTimeline(length=8), uid="A", name="A"
... )
>>> parent.append_child(
...     ContinuousLogicalTimeline(length=8), uid="B", name="B"
... )
>>> parent.list_children()
['A', 'B']
>>> float(parent.get_child_offset("B").value)
8.0

apply_flow

timelines.Timeline.apply_flow(
    id='default',
    *,
    include_children=True,
    uid=None,
    name=None,
    fill_gaps=False,
)

Yield the unfolded timeline for an attached FlowMap.

Slices this timeline at each of the attached FlowMap’s sections and places the slices, in target (unfolded) order, as children of a new timeline of this timeline’s same concrete type. Each section also becomes a matching named Region on the result, in unfolded coordinates.

Each slice sits at its section’s target coordinate. Ordinary concatenating FlowMaps stack the slices end to end; a FlowMap that places its spans apart — a restored cut, or any FlowMap’s :meth:~timetoalign.timelines.flow.FlowMap.inverse — leaves the result empty between them.

Each appended child (and its Region) takes the source section’s name — the region name a played span was built from. A span visited more than once (a repeat) is suffixed -rend2, -rend3 … so every child and Region has a unique name. Section events live in the appended children; the flattened coordinates remain reachable via get_events(include_children=True).

The returned timeline carries a reverse FlowMap (id "source") for tracing coordinates back to the folded source, plus the forward FlowMap (id f"forward_{flow_map.id}").

Parameters

Name Type Description Default
id str Which attached FlowMap to unfold along. Passed positionally, so timeline.apply_flow("A8") selects the FlowMap stored under "A8". 'default'
include_children bool If True (default), child timelines are recursively sliced and included in each section. True
uid str | None Optional identifier for the returned timeline. None
name str | None Optional name for the returned timeline. Defaults to f"{self.name}_unfolded". None
fill_gaps bool If True, each hole between the placed spans becomes an empty child (plus a matching Region), so the result tiles its axis contiguously. Required when this timeline is a SegmentLine, which admits no gaps between its segments. False

Returns

Name Type Description
'Timeline' The unfolded timeline (same concrete type as self), with one
'Timeline' child and matching Region per played section, each placed at its
'Timeline' target coordinate.

Raises

Name Type Description
ValueError If no FlowMap with the given id is attached.

Examples

>>> child.create_flow_map(["A8_1", "A8_2"], id="A8")
FlowMap(A8: 2 sections)
>>> unfolded = child.apply_flow("A8")
>>> unfolded.n_children
2
>>> unfolded.list_children()
['A8_1', 'A8_2']
>>> # Applying the inverse puts the spans back where they came
>>> # from, restoring the hole the cut left:
>>> restored = unfolded.apply_flow("source")
>>> float(restored.get_child_offset("A8_2").value)
129.0

as_segment_line

timelines.Timeline.as_segment_line()

Cast a structurally contiguous hierarchy to a parameterized line.

convert_to

timelines.Timeline.convert_to(values, target_unit)

Convert coordinates to another unit using attached C-Maps.

Parameters

Name Type Description Default
values CoordinateValue | Coordinate | np.ndarray Coordinate value(s) to convert. Can be: - Scalar (int, float, Fraction): Returns a Coordinate object - Coordinate: Returns a Coordinate object - numpy array: Returns a numpy array of converted values required
target_unit TimeUnit | str Target unit. required

Returns

Name Type Description
Coordinate | np.ndarray - For scalar/Coordinate input: Coordinate object in the target unit
Coordinate | np.ndarray - For array input: numpy array of converted values

Raises

Name Type Description
ValueError If no suitable map is found.

Examples

>>> timeline.add_conversion_map(ScalarMap(scalar=1/300, ...))
>>> coord = timeline.convert_to(15343, "inches")
>>> coord
Coordinate(51.1, inches)
>>> arr = timeline.convert_to(np.array([100, 200]), "inches")
>>> arr
array([0.333, 0.666])

create_child

timelines.Timeline.create_child(
    length,
    offset=0,
    uid=None,
    name=None,
    allow_expansion=False,
    child_class=None,
)

Create and embed a child selected by this timeline’s spawn hook.

By default, this is equivalent to:

child_type = parent._spawn_class()
child = child_type(length=length, unit=parent.unit, uid=uid, name=name)
parent.add_child(child, offset=offset)

child_class=Timeline deliberately selects the experimental base class.

Parameters

Name Type Description Default
length CoordinateSpec Child length in the parent’s unit. required
offset CoordinateSpec Child start coordinate. Defaults to zero. 0
uid str | None Unique identifier for the child. Auto-generated if None. None
name str | None Human-readable name for the child. None
allow_expansion bool If True, expand the parent when needed. False
child_class type['Timeline'] | None Explicit class override for the child. None

Returns

Name Type Description
'Timeline' The newly created and embedded child Timeline.

Raises

Name Type Description
ValueError If coordinates are invalid or the child exceeds bounds.

Examples

>>> parent = ContinuousLogicalTimeline(length=8)
>>> child = parent.create_child(length=4)
>>> type(child) is ContinuousLogicalTimeline
True

create_child_from_region

timelines.Timeline.create_child_from_region(
    region_name,
    *,
    copy_events=True,
    uid=None,
)

Create a child timeline from a named region (partitioning).

The child’s length = region duration, offset = region start. The child’s class matches the parent’s concrete class. If copy_events, events in [start, end) are copied with adjusted coordinates.

Parameters

Name Type Description Default
region_name str Name of an existing region. required
copy_events bool Copy events within the region to the child. True
uid str | None Explicit child ID. Defaults to region name. None

Returns

Name Type Description
'Timeline' The newly created and attached child timeline.

Raises

Name Type Description
KeyError If region_name not found.
RuntimeError If timeline is locked.

Examples

>>> tl.create_regions_by_splitting("breaks", prefix="movement")
>>> mov4 = tl.create_child_from_region("movement_4")

create_children_from_boundaries

timelines.Timeline.create_children_from_boundaries(
    boundaries,
    *,
    names=None,
    name_format='{prefix}_{n}',
    prefix='section',
    allow_expansion=False,
)

Create children spanning consecutive boundary coordinates.

Source events are not copied into the children.

Parameters

Name Type Description Default
boundaries Sequence[CoordinateSpec] k+1 monotonically increasing coordinates. required
names Sequence[str] | None Explicit names for the k children. None
name_format str Format with {prefix}, {i}, and {n} placeholders. '{prefix}_{n}'
prefix str Prefix for auto-generated names. 'section'
allow_expansion bool If True, expand the parent when needed. False

Returns

Name Type Description
list['Timeline'] Child timelines in boundary order.

Raises

Name Type Description
ValueError If the boundaries or number of names are invalid.

create_children_from_regions

timelines.Timeline.create_children_from_regions(
    region_names=None,
    *,
    copy_events=True,
)

Create children from multiple regions (batch partitioning).

Each region becomes a child. Regions may overlap — resulting children are independent.

Parameters

Name Type Description Default
region_names Sequence[str] | None Region names. None = all regions in insertion order. None
copy_events bool Copy events to children. True

Returns

Name Type Description
list['Timeline'] List of child timelines in region order.

Raises

Name Type Description
KeyError If any region_name not found.
RuntimeError If timeline is locked.

Examples

>>> tl.create_regions_by_grouping("@pageIndex",
...                               name_format="page_{value}")
>>> tl.create_children_from_regions()  # All pages as children

create_flow_map

timelines.Timeline.create_flow_map(
    intervals,
    *,
    id='default',
    at=None,
    target_length=None,
)

Construct a FlowMap from interval-like descriptors, attach it, return it.

Mirrors the create_* verb×noun convention (as in :meth:create_region and :meth:create_regions_from_boundaries): it constructs the FlowMap, attaches it to this timeline under id, and returns it.

By default the played spans described by intervals concatenate contiguously in the unfolded (target) axis; coordinates falling in a gap between spans map to nothing (an empty unfold_coordinate result).

To lay the spans out with holes between them instead — which is what restoring a cut needs — state the placement in any of three ways: mix :class:~timetoalign.timelines.flow.Gap entries into intervals, give each span its target coordinate in at, or pass intervals as a {target coordinate -> span} mapping.

Parameters

Name Type Description Default
intervals Any One interval-like descriptor, a collection of them, or a {target coordinate -> span} mapping. Accepted descriptor forms are region names (str, resolved via :meth:get_region), Region objects, (start, end) coordinate pairs, Timeline objects, and interval events. Gap entries may be mixed into a collection to space the spans apart. required
id str Identifier for the FlowMap. Defaults to "default". 'default'
at 'Sequence[Any] | None' Target coordinate for each played span, in the order given. One entry per span, or None for a span that should follow its predecessor. Cannot be combined with Gap entries. None
target_length CoordinateSpec | None Total extent of the unfolded axis. Needed only when the flow ends in a gap, which no section would imply. None

Returns

Name Type Description
'FlowMap' The constructed FlowMap (also attached to this timeline).

Examples

>>> child.create_flow_map(["A8_1", "A8_2"], id="A8")
FlowMap(A8: 2 sections)
>>> child.create_flow_map([(0, 123), (129, child.length)], id="A8")
FlowMap(A8: 2 sections)
>>> # Restore the two skipped measures as a 6-quarter hole:
>>> child.create_flow_map(["A8_1", Gap(6), "A8_2"], id="restored")
FlowMap(restored: 2 sections, 1 gap)
>>> # The same placement, stated as coordinates:
>>> child.create_flow_map(["A8_1", "A8_2"], at=[0, 129], id="restored")
FlowMap(restored: 2 sections, 1 gap)
>>> # ... or as a mapping pairing each coordinate with its span:
>>> child.create_flow_map({0: "A8_1", 129: "A8_2"}, id="restored")
FlowMap(restored: 2 sections, 1 gap)

create_region

timelines.Timeline.create_region(name, start, end, *, meta=None)

Create a new named Region and attach it to this timeline.

Under the unified verb×noun API, create constructs a new object, attaches it, and returns it.

Parameters

Name Type Description Default
name str Unique name for this region. required
start CoordinateSpec Start coordinate. required
end CoordinateSpec End coordinate (must be >= start). required
meta dict[str, Any] | None Optional metadata dictionary. None

Returns

Name Type Description
Region The created Region object.

Raises

Name Type Description
ValueError If name already exists or end < start.

Examples

>>> tl.create_region("Chorus", 10.0, 30.0)
>>> tl.create_region("Verse", 30.0, 50.0, meta={"repeat": 2})

create_regions_by_grouping

timelines.Timeline.create_regions_by_grouping(field, *, name_format='{value}')

Create regions by grouping adjacent events on a field value.

For each run of consecutive events that share the same value in the specified field, creates a region spanning the run’s coordinate extent [min_start, max_end). Only adjacent events with the same value are grouped — non-adjacent occurrences of the same value produce separate regions.

This “run-length” semantics is essential for musical data where, e.g., the same time signature may recur after a change (4/4 → 3/4 → 4/4) and each occurrence should be its own region.

Parameters

Name Type Description Default
field str Event field name to group by. required
name_format str Format string. Placeholders: {value}, {i} (0-based), {n} (1-based), {run} (1-based run index for this value). '{value}'

Returns

Name Type Description
list[Region] List of Region objects ordered by start coordinate.

Raises

Name Type Description
ValueError If field does not exist in events.

Examples

>>> # Time-signature regions (adjacent grouping)
>>> tl.create_regions_by_grouping("timesig")
[Region('4/4', 0-64), Region('3/4', 64-88), Region('4/4', 88-120)]

create_regions_by_splitting

timelines.Timeline.create_regions_by_splitting(
    predicate,
    *,
    names=None,
    name_format='{prefix}_{n}',
    prefix='section',
    include_before_first=True,
    include_after_last=True,
)

Create contiguous regions by splitting at events matching a predicate.

Finds events matching the predicate, uses their coordinates as split points, creates contiguous regions between consecutive split points.

The predicate can be: - A string: field name. Events where this field is truthy (non-null, non-empty, non-zero) are split points. - A dict: keyword filters in the same style as EventData.filter(). For example {"breaks": "section"} selects events whose breaks field equals "section". - A callable: receives event dict, returns True for split points.

For each matching event the split coordinate is the event’s end (interval events) or start/instant (instant events).

Parameters

Name Type Description Default
predicate str | dict[str, Any] | Callable[[dict], bool] Field name, filter dict, or callable identifying split-point events. required
names Sequence[str] | None Explicit region names. None
name_format str Format string. Placeholders: {prefix}, {i}, {n}. '{prefix}_{n}'
prefix str Prefix for auto-generated names. 'section'
include_before_first bool Create a region from timeline origin to first split point. True
include_after_last bool Create a region from last split point to timeline end. True

Returns

Name Type Description
list[Region] List of contiguous Region objects in coordinate order.

Examples

>>> # Split at section breaks
>>> tl.create_regions_by_splitting("breaks", prefix="movement")
>>> # Split at specific break types
>>> tl.create_regions_by_splitting(
...     {"breaks": "section"}, prefix="movement"
... )

create_regions_from_boundaries

timelines.Timeline.create_regions_from_boundaries(
    boundaries,
    *,
    names=None,
    name_format='{prefix}_{n}',
    prefix='section',
)

Create contiguous regions from boundary coordinates.

Given k+1 sorted boundary coordinates, creates k regions where region_i spans [boundaries[i], boundaries[i+1]).

Parameters

Name Type Description Default
boundaries Sequence[CoordinateSpec] k+1 monotonically increasing coordinates. required
names Sequence[str] | None Explicit names for the k regions. Mutually exclusive with name_format/prefix. None
name_format str Format string. Placeholders: {prefix}, {i} (0-based), {n} (1-based). '{prefix}_{n}'
prefix str Prefix for auto-generated names. 'section'

Returns

Name Type Description
list[Region] List of k Region objects in boundary order.

Raises

Name Type Description
ValueError If fewer than 2 boundaries or not monotonically increasing.

Examples

>>> tl.create_regions_from_boundaries(
...     [0, 30, 60, 90],
...     prefix="movement",
... )
[Region('movement_1', 0-30), Region('movement_2', 30-60),
 Region('movement_3', 60-90)]

create_segment_line

timelines.Timeline.create_segment_line(boundaries, *, copy_events=True)

Create a SegmentLine by segmenting at boundary coordinates.

Given k+1 sorted coordinates, produces a new SegmentLine with k contiguous segments. Each segment’s class matches self’s class.

Does NOT modify self. Returns a new independent SegmentLine.

Parameters

Name Type Description Default
boundaries Sequence[CoordinateSpec] k+1 monotonically increasing coordinates. required
copy_events bool Copy events into their respective segments. True

Returns

Name Type Description
'SegmentLine' A new SegmentLine with k segments.

Raises

Name Type Description
ValueError If fewer than 2 boundaries or not monotonically increasing.

Examples

>>> measures = audio_tl.create_segment_line(
...     [0.0] + measure_times.tolist() + [float(audio_tl.length)]
... )

create_segment_line_by_grouping

timelines.Timeline.create_segment_line_by_grouping(
    field,
    *,
    copy_events=True,
    name_format='{value}',
)

Create a SegmentLine by grouping adjacent events on a field value.

Groups must form contiguous, non-overlapping spans. This is validated and raises if not satisfied.

Does NOT modify self. Does NOT add intermediate regions to self.

Parameters

Name Type Description Default
field str Event field to group by. required
copy_events bool Copy events into segments. True
name_format str Format string for segment names. '{value}'

Returns

Name Type Description
'SegmentLine' A new SegmentLine.

Raises

Name Type Description
ValueError If groups are not contiguous.

Examples

>>> systems = page.create_segment_line_by_grouping("spacing_run_id")

create_segment_line_by_splitting

timelines.Timeline.create_segment_line_by_splitting(
    predicate,
    *,
    copy_events=True,
    names=None,
    name_format='{prefix}_{n}',
    prefix='section',
    include_before_first=True,
    include_after_last=True,
)

Create a SegmentLine by splitting at events matching a predicate.

Shortcut for finding split points and creating a SegmentLine directly. Does NOT modify self (no intermediate regions are created).

The predicate follows the same semantics as :meth:create_regions_by_splitting.

Parameters

Name Type Description Default
predicate str | dict[str, Any] | Callable[[dict], bool] Column name, filter dict, or callable identifying split-point events. required
copy_events bool Copy events into segments. True
names Sequence[str] | None Explicit segment names. None
name_format str Format string for segment names. '{prefix}_{n}'
prefix str Prefix for auto-generated names. 'section'
include_before_first bool Include segment before first split point. True
include_after_last bool Include segment after last split point. True

Returns

Name Type Description
'SegmentLine' A new SegmentLine.

Examples

>>> sl = tl.create_segment_line_by_splitting(
...     {"breaks": "section"}, prefix="movement"
... )

create_segment_line_from_regions

timelines.Timeline.create_segment_line_from_regions(
    region_names=None,
    *,
    copy_events=True,
)

Create a SegmentLine from contiguous regions.

Validates that regions are contiguous and non-overlapping (each region’s end == next region’s start).

Does NOT modify self.

Parameters

Name Type Description Default
region_names Sequence[str] | None Ordered region names. None = all regions sorted by start coordinate. None
copy_events bool Copy events into segments. True

Returns

Name Type Description
'SegmentLine' A new SegmentLine.

Raises

Name Type Description
ValueError If regions are not contiguous or empty.

Examples

>>> tl.create_regions_by_grouping("timesig")
>>> seg_line = tl.create_segment_line_from_regions()

derive

timelines.Timeline.derive(target_unit, name=None, copy_events=False)

Create a derivative timeline in a different unit via C-Map conversion.

A ConversionMap implies the presence of a derived timeline in the target unit. The derive() method makes this implicit timeline explicit.

The derived timeline: - Has coordinates in the target unit - Has length equal to the converted source length - Automatically has an inverse C-Map back to the source unit - Optionally copies and converts events from the source

This operation creates a NEW timeline, NOT a child timeline. The source and derived timelines have different units, so per TTA specification, they cannot be parent-child (children must share the parent’s unit). Use TimelineGroup to connect them.

Parameters

Name Type Description Default
target_unit TimeUnit | str The unit for the derived timeline. required
name str | None Optional name for the derived timeline. None
copy_events bool If True, copy and convert events to the derived timeline. False

Returns

Name Type Description
'Timeline' A new Timeline in the target unit.

Raises

Name Type Description
ValueError If no C-Map exists for the target unit.
ValueError If C-Map is not invertible (needed for roundtrip).

Examples

>>> # Create physical timeline with tempo C-Map
>>> audio = ContinuousPhysicalTimeline(length=60.0)
>>> audio.add_conversion_map(LinearMap(2.0, 0.0,
...     source_unit=TimeUnit.seconds, target_unit=TimeUnit.quarters))
>>> # Derive a logical timeline
>>> score = audio.derive(TimeUnit.quarters, name="score")
>>> score.unit
TimeUnit.quarters
>>> score.length
Coordinate(120.0, quarters)  # 60 seconds * 2 q/s

diagram

timelines.Timeline.diagram(
    width=70,
    show_children=True,
    max_children=6,
    unicode=True,
    show=None,
    depth=True,
)

Generate ASCII diagram for this timeline.

Parameters

Name Type Description Default
width int Total width of the diagram in characters. 70
show_children bool Whether to show child timelines (one per row). True
max_children int Maximum children to show before truncating. 6
unicode bool Use Unicode characters (True) or ASCII fallback (False). True
show set[str] | None Optional set controlling which elements appear. Supported values: "children", "regions", and "cmaps" (attached conversion maps). When None, behaviour is exactly as before. None
depth bool | int Child levels to render. True renders all levels, False renders direct children only, and a non-negative integer renders at most that many levels below this timeline. In particular, 0 renders no child rows. True

Returns

Name Type Description
'Diagram' Diagram object (displays as ASCII in terminal, rich HTML in Jupyter).

Raises

Name Type Description
ValueError If depth is a negative integer.

Examples

>>> print(timeline.diagram())
DiscreteGraphicalTimeline[dgt1:1] (11 events, 5 children)
0 ∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶ 4835 pixels
  ├─ system_1     0   ∶∶∶∶∶∶∶                        967
  ├─ system_2   967          ∶∶∶∶∶∶∶∶               1934
  └─ ...

empty

timelines.Timeline.empty(unit=None, number_type=None, **kwargs)

Create an empty Timeline with length 0.

Parameters

Name Type Description Default
unit TimeUnit | str | None The time unit. Defaults to class default. None
number_type NumberType | str | None The number type. Defaults to class default. None
**kwargs Any Additional arguments passed to init. {}

Returns

Name Type Description
Self A new empty Timeline.

export_to_csv

timelines.Timeline.export_to_csv(
    filepath,
    coordinates=None,
    conversion_maps=True,
    recursion_limit=None,
    include_events=True,
    include_boundaries=False,
    *,
    fields=None,
    units=True,
    sep=',',
    header=True,
    index=False,
)

Export timeline data to a CSV file.

This is a convenience method that generates a timestamp DataFrame and writes it to a CSV file. For more control over the output, use to_dataframe() and save manually.

Parameters

Name Type Description Default
filepath str Output CSV file path. required
coordinates CoordinateSpec | Sequence[CoordinateSpec] | None Explicit coordinates to use as the axis. None
conversion_maps ConversionMapsSpec C-Maps to include as additional fields. Defaults to True (all). True
recursion_limit int | None Maximum depth for child traversal. None
include_events bool If True and coordinates is None, extract from events. True
include_boundaries bool If True, include timeline boundary coordinates. False
fields 'ColumnNaming | Callable[[str, dict], str] | list[str] | None' How to name the DataFrame fields (see to_dataframe). None
units bool If True (default), append units to field names. True
sep str Field separator. Default “,” (comma). ','
header bool If True (default), write field headers. True
index bool If True, write row indices. Default False. False

Returns

Name Type Description
int Number of rows written.

Examples

>>> timeline.export_to_csv("timestamps.csv")
100
>>> # Tab-separated, no header
>>> timeline.export_to_csv("data.tsv", sep="\t", header=False)
100

fold

timelines.Timeline.fold(coord, id='default')

Convert an unfolded coordinate to a folded coordinate.

Convenience method that delegates to the attached FlowMap.

Parameters

Name Type Description Default
coord CoordinateSpec Coordinate in the unfolded timeline. required
id str Which FlowMap to use. 'default'

Returns

Name Type Description
float Coordinate in the folded timeline.

Raises

Name Type Description
ValueError If no FlowMap with the given id is attached, or if the coordinate is outside the flow range.

from_dict

timelines.Timeline.from_dict(data)

Create a Timeline from a dictionary.

Every rational wire dict in datalength, the child offsets, and the event coordinate structs — is decoded by :func:~timetoalign.core.wire_to_rational, so an exact ratio comes back as a Fraction and an inexact one as a float. Feeding the result back through :meth:to_dict with the same flags reproduces the input dictionary.

The "events" and "external_references" keys are optional: a dictionary produced without them reconstructs a timeline with zero events and an empty reference table. External references are restored without event validation, so a payload carrying references but no events round-trips intact.

Parameters

Name Type Description Default
data dict[str, Any] Dictionary from to_dict(). required

Returns

Name Type Description
Self A new Timeline instance.

from_event_data

timelines.Timeline.from_event_data(data, **kwargs)

Create a Timeline from an existing EventData.

Parameters

Name Type Description Default
data EventData The EventData containing events. required
**kwargs Any Additional arguments passed to init (except unit/number_type). {}

Returns

Name Type Description
Self A new Timeline wrapping the EventData.

from_events

timelines.Timeline.from_events(rows, unit=None, number_type=None, **kwargs)

Create a Timeline from event dictionaries.

The timeline length is automatically set to accommodate all events.

Parameters

Name Type Description Default
rows list[dict[str, Any]] List of event dictionaries with keys: - id: unique identifier - temporal_type: “instant” or “interval” - event_type: class name (e.g., “Note”, “Beat”) - instant: coordinate (for instant events) - start, end: coordinates (for interval events) required
unit TimeUnit | str | None The time unit. Defaults to class default. None
number_type NumberType | str | None The number type. Defaults to class default. None
**kwargs Any Additional arguments passed to init. {}

Returns

Name Type Description
Self A new Timeline containing the events.

get_boundary_table

timelines.Timeline.get_boundary_table(
    conversion_maps=True,
    recursion_limit=None,
)

Get timestamps for timeline boundaries only.

Returns a timestamp table containing only start (0) and end (length) coordinates for this timeline and all children.

Parameters

Name Type Description Default
conversion_maps ConversionMapsSpec C-Maps to include as fields (see get_timestamp_table). True
recursion_limit int | None Maximum depth for child traversal. None

Returns

Name Type Description
pa.Table PyArrow Table with boundary timestamps.

Examples

>>> table = timeline.get_boundary_table()
>>> table.to_pandas()
   axis  tl:1  child:1
0   0.0   0.0      NaN
1  10.0  10.0     10.0
2  50.0   NaN      0.0
3  60.0   NaN     10.0

get_child

timelines.Timeline.get_child(child_id)

Retrieve a child timeline by ID.

Parameters

Name Type Description Default
child_id str The ID of the child to retrieve. required

Returns

Name Type Description
Timeline The child Timeline.

Raises

Name Type Description
KeyError If no child with that ID exists.

get_child_offset

timelines.Timeline.get_child_offset(child_id)

Get the offset of a child timeline.

Parameters

Name Type Description Default
child_id str The ID of the child. required

Returns

Name Type Description
Coordinate The offset Coordinate.

Raises

Name Type Description
KeyError If no child with that ID exists.

get_children_at

timelines.Timeline.get_children_at(coord)

Return all children whose extent contains the given coordinate.

A child contains coord if offset <= coord < offset + child.length.

Parameters

Name Type Description Default
coord CoordinateSpec The coordinate to query. required

Returns

Name Type Description
list['Timeline'] List of child Timeline objects, ordered by offset.
list['Timeline'] Empty list if no children contain coord.

get_conversion_map

timelines.Timeline.get_conversion_map(target_unit)

Get a conversion map by target unit or by name/id.

When target_unit is a valid TimeUnit value (or an alias such as "seconds"), the method returns the first attached map whose target_unit matches.

When target_unit is a string that does not correspond to any TimeUnit member, the method falls back to a name-based lookup: it searches first by cmap.id, then by cmap.name. This is useful for maps where source and target units are identical (e.g. a ShiftMap named "raw_quarters" that maps normalised quarters back to raw partitura quarters).

Parameters

Name Type Description Default
target_unit TimeUnit | str A TimeUnit member, a unit alias string, or a conversion-map name/id string. required

Returns

Name Type Description
ConversionMap[Any] | None A matching ConversionMap, or None if not found.

Examples

>>> timeline.get_conversion_map(TimeUnit.seconds)
ScalarMap(...)
>>> timeline.get_conversion_map("raw_quarters")
ShiftMap(offset=-0.5, ...)

get_coordinate

timelines.Timeline.get_coordinate(
    at,
    timeline_id=None,
    *,
    format='id_coordinate',
    rounding='round',
)

Dispatch a positional or event-key coordinate query.

Parameters

Name Type Description Default
at CoordinateInput | CoordinateCollection | str | KeyCollection Scalar or plural coordinate position or event key. required
timeline_id str | None Optional result-axis validator. None
format CoordinateFormat Requested coordinate output format. 'id_coordinate'
rounding Rounding Integral projection mode. 'round'

Returns

Name Type Description
CoordinateResult | list[CoordinateResult] | pd.Series The selected precise-getter result.

get_coordinate_at

timelines.Timeline.get_coordinate_at(
    at,
    timeline_id=None,
    *,
    format='id_coordinate',
    rounding='round',
)

Resolve one position onto this timeline’s canonical axis.

Parameters

Name Type Description Default
at CoordinateInput Coordinate position to resolve. required
timeline_id str | None Optional result-axis validator. None
format CoordinateFormat Requested coordinate output format. 'id_coordinate'
rounding Rounding Integral projection mode. 'round'

Returns

Name Type Description
CoordinateResult | pd.Series One coordinate projection or a length-one Series.

Raises

Name Type Description
KeyError If the result or embedded source timeline is unknown.
ValueError If a unit has no unique invertible conversion path.
TypeError If at is not a scalar coordinate input.

get_coordinate_for

timelines.Timeline.get_coordinate_for(
    key,
    timeline_id=None,
    *,
    format='id_coordinate',
    rounding='round',
)

Return an event’s start coordinate on this timeline.

Parameters

Name Type Description Default
key str Event ID to find recursively. required
timeline_id str | None Optional result-axis validator. None
format CoordinateFormat Requested coordinate output format. 'id_coordinate'
rounding Rounding Integral projection mode. 'round'

Returns

Name Type Description
CoordinateResult | pd.Series The event-start coordinate projection.

get_coordinates_at

timelines.Timeline.get_coordinates_at(
    at,
    timeline_id=None,
    *,
    format='id_coordinate',
    rounding='round',
)

Resolve a collection of positions onto this timeline.

Parameters

Name Type Description Default
at CoordinateCollection Coordinate positions to resolve. required
timeline_id str | None Optional result-axis validator. None
format CoordinateFormat Requested coordinate output format. 'id_coordinate'
rounding Rounding Integral projection mode. 'round'

Returns

Name Type Description
list[CoordinateResult] | pd.Series A list of projections or canonical-value Series.

get_coordinates_for

timelines.Timeline.get_coordinates_for(
    keys,
    timeline_id=None,
    *,
    format='id_coordinate',
    rounding='round',
)

Return event-start coordinates for a collection of event IDs.

Parameters

Name Type Description Default
keys KeyCollection Event IDs to retrieve. required
timeline_id str | None Optional result-axis validator. None
format CoordinateFormat Requested coordinate output format. 'id_coordinate'
rounding Rounding Integral projection mode. 'round'

Returns

Name Type Description
list[CoordinateResult] | pd.Series A list of projections or canonical-value Series.

get_event

timelines.Timeline.get_event(event_id)

Look up a single event by its id field.

Searches this timeline’s events first, then recursively searches all children. When found in a child, coordinates are adjusted to the root timeline’s coordinate system.

Parameters

Name Type Description Default
event_id str The event identifier to search for. required

Returns

Name Type Description
dict[str, Any] | None A dictionary representing the event row, or None if not
dict[str, Any] | None found anywhere in the hierarchy.

Examples

>>> event = timeline.get_event("notes:note:000001")
>>> event["id"]
'notes:note:000001'
>>> timeline.get_event("nonexistent") is None
True

get_events

timelines.Timeline.get_events(
    temporal_type=None,
    event_type=None,
    include_children=True,
    min_coord=None,
    max_coord=None,
    **field_filters,
)

Filter and retrieve events.

When include_children=True (the default), events from all children are included with their coordinates adjusted to the root timeline’s coordinate system. Segment events (internal bookkeeping) are always excluded.

Parameters

Name Type Description Default
temporal_type Literal['instant', 'interval'] | None Filter by “instant” or “interval”. None
event_type str | None Filter by event type name. None
include_children bool If True (default), include events from all children with root-relative coordinates. True
min_coord CoordinateSpec | None Minimum coordinate (inclusive). Can be a float in native units or a Coordinate with a different unit (converted via inverse C-Map). None
max_coord CoordinateSpec | None Maximum coordinate (exclusive). Same conversion rules as min_coord. None
**field_filters Any Additional field equality filters. Each kwarg name is a field name, and the value is the required value (or a list of values for OR logic). {}

Returns

Name Type Description
EventData A filtered EventData with all matching events.

Examples

>>> # Filter by coordinate range
>>> events = tl.get_events(min_coord=10.0, max_coord=20.0)
>>> # Filter with a Coordinate in a different unit
>>> from timetoalign import Coordinate, TimeUnit
>>> coord = Coordinate(5.0, TimeUnit.seconds)
>>> events = tl.get_events(min_coord=coord)
>>> # Arbitrary field filters
>>> events = tl.get_events(pitch=60)  # Only middle C
>>> events = tl.get_events(pitch=[60, 62, 64])  # C, D, E

get_events_at

timelines.Timeline.get_events_at(coord, tolerance=0.0, include_children=True)

Get all events active at a specific coordinate.

Returns events from this timeline and all children that are active (containing or at) the specified coordinate.

For instant events, an event is “at” the coordinate if its instant is within tolerance of the query coordinate.

For interval events, an event is “active” if the coordinate falls within [start, end).

Parameters

Name Type Description Default
coord CoordinateSpec Coordinate to query (in this timeline’s unit). required
tolerance float Tolerance for instant event matching (default 0). 0.0
include_children bool If True, include events from children. True

Returns

Name Type Description
dict[str, list[dict[str, Any]]] Dict mapping timeline_id to list of events active at that coordinate.
dict[str, list[dict[str, Any]]] Child events have coordinates in their local coordinate system.

Examples

>>> events = score.get_events_at(50.0)
>>> events["score:1"]  # Events in root at coord 50
[{"id": "n1", "event_type": "Note", ...}]
>>> events["measure_5"]  # Events in measure 5
[...]

get_flow_map

timelines.Timeline.get_flow_map(id='default')

Get an attached FlowMap by id.

Parameters

Name Type Description Default
id str Identifier of the FlowMap. Default is “default”. 'default'

Returns

Name Type Description
'FlowMap | None' The FlowMap if found, None otherwise.

get_interval_stamp

timelines.Timeline.get_interval_stamp(
    start,
    end,
    unit=None,
    *,
    conversion_maps=True,
)

Get a TimeIntervalStamp for a coordinate range.

Parameters

Name Type Description Default
start CoordinateSpec Start coordinate. required
end CoordinateSpec End coordinate. required
unit TimeUnit | str | None If provided, interpret both coords as being in this unit. None
conversion_maps ConversionMapsSpec C-Maps available through the returned stamps. True

Returns

Name Type Description
TimeIntervalStamp TimeIntervalStamp with start and end TimeStamps.

Examples

>>> from timetoalign.timelines import Timeline
>>> parent = Timeline(length=20, unit=TimeUnit.seconds, uid="timeline:1")
>>> child = Timeline(length=15, unit=TimeUnit.seconds, uid="child:1")
>>> parent.add_child(child, offset=0)
>>> interval = parent.get_interval_stamp(0.0, 10.0)
>>> interval.duration
Duration(10.0, seconds)
>>> interval.get_interval("child:1")
Interval(start=Coordinate(0.0, seconds), end=Coordinate(10.0, seconds))

get_region

timelines.Timeline.get_region(name)

Get a Region by name.

Parameters

Name Type Description Default
name str The region name. required

Returns

Name Type Description
Region The Region object.

Raises

Name Type Description
KeyError If no region with that name exists.

get_regions_at

timelines.Timeline.get_regions_at(coord)

Return all regions containing the given coordinate.

A region contains coord if region.start <= coord < region.end (left-inclusive, right-exclusive).

Parameters

Name Type Description Default
coord CoordinateSpec The coordinate to query. required

Returns

Name Type Description
list[Region] List of Region objects containing coord, ordered by start
list[Region] coordinate. Empty list if no regions contain coord.

Examples

>>> tl.get_regions_at(75.0)
[Region('verse_1', 30-90), Region('chorus', 60-120)]

get_slice

timelines.Timeline.get_slice(
    start,
    end,
    *,
    truncate_events=True,
    include_children=True,
    copy_cmaps=True,
)

Extract a portion of this timeline as a new, independent timeline.

Returns a new timeline containing all events within [start, end). The returned timeline has its coordinate origin at 0, with all coordinates shifted by -start.

Slicing creates a new timeline that is a structural copy of the specified interval of the source.

Parameters

Name Type Description Default
start CoordinateSpec Start coordinate (inclusive). required
end CoordinateSpec End coordinate (exclusive). required
truncate_events bool If True (default), interval events straddling the slice boundaries are clipped to [start, end). If False, events must be fully contained to be included. True
include_children bool If True (default), child timelines whose span overlaps [start, end) are recursively sliced and included. True
copy_cmaps bool If True (default), ConversionMaps are bounded-copied for the slice range. True

Returns

Name Type Description
'Timeline' New Timeline (same concrete subclass) with length = end - start,
'Timeline' coordinates shifted to [0, end-start).

Raises

Name Type Description
ValueError If start >= end or either is outside timeline bounds.

Examples

>>> source = ContinuousLogicalTimeline(length=100)
>>> source.add_events([
...     {"event_type": "Note", "start": 10, "end": 30},
...     {"event_type": "Beat", "instant": 25},
... ])
>>> sliced = source.get_slice(20, 40)
>>> sliced.length.value  # 40 - 20 = 20
Fraction(20, 1)

get_timestamp

timelines.Timeline.get_timestamp(coord, unit=None, *, conversion_maps=True)

Get a timestamp whose axis is written in this timeline’s own type.

The caller may pass a coordinate in any numeric form; the axis is expressed in the timeline’s declared number_type, so a query of 9.5 on a fraction-canonical timeline gives an axis of Fraction(19, 2).

Parameters

Name Type Description Default
coord CoordinateSpec Coordinate to resolve on this timeline. required
unit TimeUnit | str | None Optional unit in which coord is expressed. None
conversion_maps ConversionMapsSpec C-Maps available through the returned stamp. True

Returns

Name Type Description
TimeStamp A timestamp with exact scalar provenance when one exists.

get_timestamp_at

timelines.Timeline.get_timestamp_at(coord, unit=None, *, conversion_maps=True)

Alias for get_timestamp() for API consistency with TimelineGroup.

TimelineGroup uses get_timestamp_at(coord, tl_id) with an additional timeline_id parameter. This alias provides a consistent verb across the hierarchy.

Parameters

Name Type Description Default
coord CoordinateSpec Coordinate value (see get_timestamp() for details). required
unit TimeUnit | str | None Optional unit for coordinate interpretation. None
conversion_maps ConversionMapsSpec C-Maps available through the returned stamp. True

Returns

Name Type Description
TimeStamp TimeStamp object for the resolved coordinate.

See Also

get_timestamp: The primary coordinate resolution method. timetoalign.TimelineGroup.get_timestamp_at: Group-level version.

get_timestamp_of

timelines.Timeline.get_timestamp_of(event_id, *, conversion_maps=True)

Get the timestamp for a specific event by its ID.

Returns a TimeStamp for instant events, or a TimeIntervalStamp for interval events. Searches recursively through children if the event is not found on this timeline directly.

Parameters

Name Type Description Default
event_id str The event identifier to look up. required
conversion_maps ConversionMapsSpec C-Maps available through the returned stamp or stamps. True

Returns

Name Type Description
TimeStamp | TimeIntervalStamp TimeStamp for instant events, TimeIntervalStamp for interval events.

Raises

Name Type Description
KeyError If no event with the given ID exists.

Examples

>>> from timetoalign.timelines import Timeline
>>> parent = Timeline(length=20, unit=TimeUnit.seconds, uid="timeline:1")
>>> child = Timeline(length=10, unit=TimeUnit.seconds, uid="clt1")
>>> parent.add_child(child, offset=5)
>>> parent.add_events([{"event_type": "Note", "instant": 5.0}])
>>> child.add_events(
...     [{"id": "clt1:note:000001", "event_type": "Note", "start": 0.0, "end": 2.5}]
... )
>>> ts = parent.get_timestamp_of("note:000001")
>>> ts.axis  # For instant events
IdCoordinate(5.0, seconds, 'timeline:1')
>>> ts = parent.get_timestamp_of("clt1:note:000001")
>>> ts.start.axis  # For interval events
IdCoordinate(5.0, seconds, 'timeline:1')
>>> ts.end.axis
IdCoordinate(7.5, seconds, 'timeline:1')

See Also

get_timestamp: Get timestamp by coordinate. get_event: Get the raw event dict by ID.

get_timestamp_table

timelines.Timeline.get_timestamp_table(
    coordinates=None,
    conversion_maps=True,
    recursion_limit=None,
    include_events=True,
    include_boundaries=False,
)

Generate a timestamp table as a PyArrow Table.

A Timestamp is a cross-section through the timeline hierarchy showing synchronous coordinates. This method computes local coordinates for each timeline in the hierarchy at each axis coordinate.

Supports IdCoordinate for automatic child offset resolution:

>>> # IdCoordinates from child timeline - offsets auto-applied!
>>> child_coords = [IdCoordinate(v, unit, "child_id") for v in values]
>>> df = parent.to_dataframe(coordinates=child_coords)

Parameters

Name Type Description Default
coordinates CoordinateSpec | Sequence[CoordinateSpec] | None Explicit coordinates to use as the axis. If None, coordinates are extracted from events (and optionally boundaries). Accepts IdCoordinate objects - if timeline_id matches a child, the offset is automatically applied. None
conversion_maps ConversionMapsSpec C-Maps to include as fields. Flexible input: - True: Include all attached conversion maps - str: Map ID or target unit name (e.g., “inches”, “seconds”) - TimeUnit: Find map by target unit enum - ConversionMap: Include the specific map - list: Mix of the above - None/False: No conversion maps True
recursion_limit int | None Maximum depth for child traversal. None = unlimited. None
include_events bool If True and coordinates is None, extract from events. True
include_boundaries bool If True, include timeline boundary coordinates. False

Returns

Name Type Description
pa.Table PyArrow Table with schema: - axis: float64 (root coordinate) - {timeline_id}: float64 (nullable, local coordinate per timeline) - {cmap_id}: varies (converted value per C-Map)
pa.Table Each field includes metadata: - unit: TimeUnit.value string (e.g., “seconds”, “pixels”) - timeline_id: Timeline ID (for timeline fields) - cmap_id: C-Map ID (for C-Map fields)
pa.Table Access metadata via: table.schema.field(col_name).metadata

Examples

>>> table = timeline.get_timestamp_table()
>>> table.column_names
['axis', 'tl:1', 'notes', 'measures']
>>> # Include all attached C-Maps
>>> table = timeline.get_timestamp_table(conversion_maps=True)
>>> # Include specific C-Maps by target unit
>>> table = timeline.get_timestamp_table(conversion_maps=["inches", "cm"])
>>> # Access unit metadata
>>> table.schema.field('axis').metadata[b'unit']
b'seconds'

get_timestamps_of

timelines.Timeline.get_timestamps_of(event_ids)

Get timestamps for multiple events, returned as a DataFrame.

For each event, includes fields for start coordinate, end coordinate (if interval), event type, and temporal type.

Parameters

Name Type Description Default
event_ids Sequence[str] Sequence of event identifiers to look up. required

Returns

Name Type Description
pd.DataFrame DataFrame indexed by event_id with fields:
pd.DataFrame - start: Start coordinate value
pd.DataFrame - end: End coordinate value (NaN for instant events)
pd.DataFrame - event_type: The event type name
pd.DataFrame - temporal_type: “instant” or “interval”

Raises

Name Type Description
KeyError If any event ID is not found.

Examples

>>> df = timeline.get_timestamps_of(["note:000001", "note:000002"])
>>> df.loc["note:000001", "start"]
0.0

See Also

get_timestamp_of: Get a single event’s timestamp. get_events: Filter events by type or coordinate range.

has_child

timelines.Timeline.has_child(child_id)

Check if a child with the given ID exists.

Parameters

Name Type Description Default
child_id str The child ID to check. required

Returns

Name Type Description
bool True if such a child exists.

has_flow_map

timelines.Timeline.has_flow_map(id='default')

Check if a FlowMap with the given id is attached.

Parameters

Name Type Description Default
id str Identifier to check. 'default'

Returns

Name Type Description
bool True if a FlowMap with that id exists.

has_region

timelines.Timeline.has_region(name)

Check if a region exists.

Parameters

Name Type Description Default
name str Name of the region. required

Returns

Name Type Description
bool True if the region exists.

is_segment_line

timelines.Timeline.is_segment_line()

Return whether children exactly and contiguously cover this timeline.

iter_children

timelines.Timeline.iter_children(
    order='sorted',
    recursion_limit=None,
    include_self=False,
)

Iterate over child timelines.

Parameters

Name Type Description Default
order TraversalOrder Traversal order - “sorted” (by offset), “depth_first”, or “breadth_first”. 'sorted'
recursion_limit int | None Maximum recursion depth. None for unlimited. None
include_self bool If True, yield this timeline first. False

Yields

Name Type Description
tuple[Coordinate, Timeline] Tuples of (offset_coordinate, child_timeline).

iter_regions

timelines.Timeline.iter_regions()

Iterate over all regions in insertion order.

Yields

Name Type Description
Region Region objects.

list_children

timelines.Timeline.list_children()

List child timeline IDs.

Returns

Name Type Description
list[str] List of child IDs in insertion order.

list_flow_maps

timelines.Timeline.list_flow_maps()

List all attached FlowMap ids.

Returns

Name Type Description
list[str] List of id strings.

list_regions

timelines.Timeline.list_regions()

List all region names.

Returns

Name Type Description
list[str] List of region names in insertion order.

make_coordinate

timelines.Timeline.make_coordinate(value)

Create a Coordinate in this timeline’s unit.

Public API for creating coordinates compatible with this timeline.

Parameters

Name Type Description Default
value CoordinateValue The numeric value for the coordinate. required

Returns

Name Type Description
Coordinate A Coordinate with this timeline’s unit.

resolve_subclass

timelines.Timeline.resolve_subclass(unit, number_type=None)

Return the most specific Timeline subclass for a unit/number_type pair.

Inspects all subclasses and selects the one whose _allowed_units includes unit. Among candidates the selection prefers, in order:

  1. A class whose default unit uses number_type (when supplied).
  2. The class with the smallest _allowed_units set (most specific domain).

Further-derived subclasses participate in the lookup and can be selected when they are the most specific matching candidate, such as a specialized BeatGrid subclass.

Falls back to the base Timeline if no subclass claims the unit.

Parameters

Name Type Description Default
unit TimeUnit | str The time unit to look up. required
number_type NumberType | str | None Optional number type for disambiguation (e.g. NumberType.fraction selects a fractional logical timeline over DiscreteLogicalTimeline). None

Returns

Name Type Description
type[Timeline] The most specific Timeline subclass that accepts unit.

Examples

>>> Timeline.resolve_subclass(TimeUnit.quarters, NumberType.fraction)
<class 'timetoalign.timelines.types.ContinuousLogicalTimeline'>
>>> Timeline.resolve_subclass(TimeUnit.pixels)
<class 'timetoalign.timelines.types.DiscreteGraphicalTimeline'>

summary

timelines.Timeline.summary()

Get a summary of the timeline.

Returns

Name Type Description
dict[str, Any] Dict with timeline information.

to_dataframe

timelines.Timeline.to_dataframe(
    coordinates=None,
    conversion_maps=True,
    recursion_limit=None,
    include_events=True,
    include_boundaries=False,
    *,
    fields=None,
    units=True,
    format='pandas',
    include_ids=True,
    as_fractions=None,
)

Generate timestamps as a pandas DataFrame with formatted field names.

This is the recommended high-level method for getting timestamp data. It builds on get_timestamp_table() and applies field formatting.

Parameters

Name Type Description Default
coordinates CoordinateSpec | Sequence[CoordinateSpec] | None Explicit coordinates to use as the axis. None
conversion_maps ConversionMapsSpec C-Maps to include as additional fields. Defaults to True (all). True
recursion_limit int | None Maximum depth for child traversal. None
include_events bool If True and coordinates is None, extract from events. True
include_boundaries bool If True, include timeline boundary coordinates. False
fields 'ColumnNaming | Callable[[str, dict], str] | list[str] | None' How to name the DataFrame fields. Options: - None or ColumnNaming.name (default): Use timeline/cmap name - ColumnNaming.id: Use timeline/cmap id - Callable: Function taking (name, metadata_dict) -> new_name - list[str]: Explicit field names None
units bool If True (default), append units to field names like “name (unit)”. True
format str Output format. Currently only “pandas” is supported. 'pandas'
include_ids bool If True (default), add event IDs as the DataFrame index when coordinates are collected from events. True
as_fractions bool | None If True, render float coordinate fields as Fraction objects. If None, enable this for fraction-based timelines. None

Returns

Name Type Description
pd.DataFrame pandas DataFrame with:
pd.DataFrame - Fields named according to the fields parameter
pd.DataFrame - Units appended if units=True
pd.DataFrame - Integer fields using pandas nullable Int64 dtype

Examples

>>> df = timeline.to_dataframe()
>>> df.columns
Index(['axis (pixels)', 'dgt1 (pixels)', 'pixels_to_inches (inches)'])
>>> # Without units in field names
>>> df = timeline.to_dataframe(units=False)
>>> df.columns
Index(['axis', 'dgt1', 'pixels_to_inches'])

to_dict

timelines.Timeline.to_dict(events=False, external_references=False)

Convert timeline to a dictionary for serialization.

The default output describes the timeline’s structure only: the "events" and "external_references" keys are absent unless explicitly requested, which keeps the payload small for the common case of persisting a hierarchy rather than its contents.

Coordinate-valued members — length and every child offset — are emitted as the canonical rational wire dict (:func:~timetoalign.core.rational_to_wire), so the result is JSON-serializable whatever the timeline’s number type, and Fraction coordinates survive the round trip exactly.

Parameters

Name Type Description Default
events bool If True, include an "events" key holding this timeline’s event rows. False
external_references bool If True, include an "external_references" key holding the reference table as a list of row dicts (access_points as a nested list of {"uri": ..., "kind": ...} dicts). Included even when the table is empty. False

Returns

Name Type Description
dict[str, Any] A JSON-serializable dictionary representation of the timeline.

Examples

>>> "events" in tl.to_dict()
False
>>> "events" in tl.to_dict(events=True)
True

to_typed

timelines.Timeline.to_typed()

Return this timeline re-instantiated as the appropriate typed subclass.

Uses the timeline’s unit and number type to determine the correct concrete subclass (e.g., ContinuousPhysicalTimeline for seconds/float). If the timeline is already an instance of the correct subclass, returns self unchanged.

This is useful after deserialization (e.g., Timeline.from_dict()) or when working with generic Timeline instances that should carry domain-specific type information.

Events, external references, conversion maps, regions, flow maps, and metadata are preserved. Children are recursively re-typed.

Returns

Name Type Description
'Timeline' A Timeline instance of the appropriate typed subclass, or self
'Timeline' if it is already the correct type.

Examples

>>> tl = Timeline(length=10.0, unit=TimeUnit.seconds)
>>> typed = tl.to_typed()
>>> type(typed).__name__
'ContinuousPhysicalTimeline'
>>> typed.is_continuous
True
>>> # Already typed -- returns self
>>> cpt = ContinuousPhysicalTimeline(length=10.0)
>>> cpt.to_typed() is cpt
True

unfold_coordinate

timelines.Timeline.unfold_coordinate(coord, id='default')

Convert a folded coordinate to unfolded coordinates.

Convenience method that delegates to the attached FlowMap. Since repeats can cause a folded coordinate to appear multiple times in the unfolded timeline, this returns a list.

Parameters

Name Type Description Default
coord CoordinateSpec Coordinate in the folded timeline. required
id str Which FlowMap to use. 'default'

Returns

Name Type Description
list[float] List of coordinates in the unfolded timeline.

Raises

Name Type Description
ValueError If no FlowMap with the given id is attached.

validate_child

timelines.Timeline.validate_child(child, offset)

Validate that a timeline can be added as a child.

A timeline can accommodate events and other timelines, called Children, as long as they use the same measuring unit.

For cross-domain relationships (e.g., physical to logical), use TimelineGroup instead of parent-child nesting.

Parameters

Name Type Description Default
child Timeline The timeline to validate. required
offset CoordinateSpec The proposed start coordinate. required

Raises

Name Type Description
TypeError If child is not a Timeline.
ValueError If units don’t match or child already has a parent.