AlignmentBundle

alignment.AlignmentBundle(
    id='',
    name=None,
    timelines=dict(),
    groups=dict(),
    timeline_to_group=dict(),
    meta=dict(),
    cross_group_claims=list(),
    cross_group_claim_fields=list(),
    support_policy=SupportPolicy.omit,
    _uid_to_timeline_id=dict(),
    _timeline_id_to_uid=dict(),
    _warp_map_cache=dict(),
    _matchline_cache=dict(),
    _matchgraph_cache=dict(),
    _cache_claims_hash=0,
)

The primary entry point for all alignment workflows.

An AlignmentBundle manages timelines and their alignment relationships. Within a group, coordinate transfer uses linear interpolation (TimelineGroup.convert()). Across groups, transfer is mediated by the MatchClaimMatchLineWarpMap pipeline.

The bundle provides:

  • Timeline registration and lookup
  • Group management (collections of perfectly aligned timelines)
  • Coordinate transfer between any two timelines (same-group or cross-group via MatchClaim/WarpMap)

IMPORTANT: The resulting bundle structure is order-independent. Adding timelines in any order produces the same alignment relationships and coordinate transfer results.

Attributes

Name Type Description
id str Unique identifier for this bundle.
name str | None Optional human-readable name.
timelines dict[str, 'Timeline'] Dictionary mapping bundle UIDs to Timeline objects.
groups dict[str, TimelineGroup] Dictionary mapping group IDs to TimelineGroup objects.
timeline_to_group dict[str, str] Mapping from bundle UID to its containing group ID.
cross_group_claims list[MatchClaim] MatchClaims connecting timelines across groups (the per-claim Python-list store).
cross_group_claim_fields list[MatchClaimField] Columnar MatchClaimField stores of dense synchronous-instant pairwise claims, queried vectorized without materialising the full claim list.

Note

The two claim stores are interchangeable as far as queries are concerned: every reader consults both, so a bundle whose claims live in a MatchClaimField answers exactly as a bundle holding the same claims in the Python list. What differs is cost — MatchClaimField queries stay vectorized, and get_claim_fields() is the accessor that keeps them that way.

Note

The bundle maintains a UID mapping layer. Users interact with bundle UIDs (e.g., “tl1”, “tl2”), while groups internally use the actual timeline.id. The bundle translates between these two namespaces transparently.

Examples

>>> bundle = AlignmentBundle()
>>> bundle.add_timeline(score_timeline, uid="score")
>>> bundle.add_timeline(audio_timeline, uid="audio", aligned_to="score")
>>> stamp = bundle.get_matchstamp_at(100.0, "score")
>>> stamp.get("audio")
45.5

Methods

Name Description
add_group Add a pre-built TimelineGroup with all its timelines at once.
add_match_claim_field Add a columnar MatchClaimField of cross-group claims.
add_match_claims Add MatchClaims connecting timelines across different groups.
add_timeline Add a timeline, optionally aligned to an existing timeline.
are_commensurable Check if two timelines can be connected via transfer.
create_match_claims Create MatchClaims from a list of event pairs.
diagram Generate ASCII diagram for this bundle.
from_bundles Merge multiple bundles’ groups, standalone timelines, and claims.
get_claim_fields Query the columnar claim stores, materialising nothing.
get_group Get a group by ID.
get_group_for_timeline Get the group containing a timeline.
get_match_claims Query MatchClaims connecting timelines across groups.
get_matchstamp_at Get a cross-group MatchStamp at a coordinate on a timeline.
get_matchstamp_table Get a PyArrow table of MatchStamps for alignment queries.
get_matchstamps Get MatchStamps for a list of MatchClaims or query coordinates.
get_timeline Get a timeline by ID.
get_timelines Get multiple timelines by their IDs.
summary Get a summary of the bundle contents.
transfer Transfer a coordinate from one timeline to another.
transfer_interval Transfer an interval from one timeline to another.

add_group

alignment.AlignmentBundle.add_group(group, *, uid_map=None)

Add a pre-built TimelineGroup with all its timelines at once.

This is the bulk-registration counterpart of add_timeline(..., as_group=...). It registers the group and every timeline it already contains into the bundle’s bookkeeping (UID mapping, timeline registry, group registry).

Parameters

Name Type Description Default
group TimelineGroup A TimelineGroup that already contains timelines. required
uid_map dict[str, str] | None Optional mapping from timeline.id to desired bundle UID. If not provided, each timeline’s id is used as its bundle UID. None

Returns

Name Type Description
'AlignmentBundle' self (for method chaining)

Raises

Name Type Description
ValueError If the group ID already exists in the bundle, or if any timeline UID would collide with an existing one.

Examples

Add a recording group with 5 DPTs:

>>> grp = TimelineGroup(id="normal", timelines=[dpt1, dpt2, dpt3])
>>> bundle.add_group(grp)

With custom UIDs:

>>> bundle.add_group(grp, uid_map={"dpt:1": "audio", "dpt:2": "midi"})

add_match_claim_field

alignment.AlignmentBundle.add_match_claim_field(claim_field)

Add a columnar MatchClaimField of cross-group claims.

This is the columnar counterpart of :meth:add_match_claims. The field is stored as-is (one PyArrow struct column) and queried vectorized by :meth:get_matchstamp_at / :meth:_get_or_build_matchgraph, which filter the struct column and materialise only the handful of claims at the queried coordinate. A dense whole-work field (on the order of a million claims) is therefore never exploded into a Python list.

It complements the per-claim list path: a bundle may hold both a Python-list cross_group_claims and one or more cross_group_claim_fields at once.

Parameters

Name Type Description Default
claim_field MatchClaimField A :class:MatchClaimField of synchronous instant pairwise claims. required

Returns

Name Type Description
'AlignmentBundle' self (for method chaining)

add_match_claims

alignment.AlignmentBundle.add_match_claims(claims)

Add MatchClaims connecting timelines across different groups.

MatchClaims encode coordinate correspondences between timelines in different groups (e.g., EEP recording notes matched to ABC score notes). They enable cross-group coordinate transfer via MatchLineWarpMap.

WarpMaps are built lazily on first transfer() or get_matchstamp_at() call, so adding claims is cheap.

Parameters

Name Type Description Default
claims list[MatchClaim] List of MatchClaim objects. Each synchronous claim connects two timelines via its start_anchor. required

Returns

Name Type Description
'AlignmentBundle' self (for method chaining)

add_timeline

alignment.AlignmentBundle.add_timeline(
    timeline,
    *,
    uid=None,
    aligned_to=None,
    as_group=None,
    start=None,
    end=None,
)

Add a timeline, optionally aligned to an existing timeline.

This is the primary method for adding timelines to the bundle. Timelines can be standalone or aligned to existing timelines.

Parameters

Name Type Description Default
timeline 'Timeline' The Timeline to add. required
uid str | None Optional explicit ID. If None, uses timeline.id. None
aligned_to str | None ID of existing timeline to align with. If provided, both timelines become part of the same group. If the target timeline is not yet in a group, a new group is created with the target as reference. None
as_group str | None Name for the group if creating a new one. None
start CoordinateSpec | None Where this timeline’s 0-origin starts in the group. - CoordinateSpec: Coordinate in the aligned_to timeline - IdCoordinate: Coordinate with explicit timeline_id (preferred) - float: Coordinate in the aligned_to timeline - None: Use group’s current start (default for linear alignment) None
end CoordinateSpec | None Where this timeline’s end (length) aligns in the group. - Same options as start - None: Use group’s current end (default for linear alignment) None

Returns

Name Type Description
'AlignmentBundle' self (for method chaining)

Raises

Name Type Description
ValueError If uid already exists in bundle.
KeyError If aligned_to references a non-existent timeline.

Examples

Linear (full-extent) alignment:

>>> bundle.add_timeline(audio, uid="dgt1")
>>> bundle.add_timeline(midi, uid="dlt1", aligned_to="dgt1")

Partial alignment (SUPRA piano roll) using IdCoordinate:

>>> from timetoalign import IdCoordinate, TimeUnit
>>> bundle.add_timeline(image, uid="dgt1")  # Full image
>>> bundle.add_timeline(
...     holes,
...     uid="dgt1_holes",
...     aligned_to="dgt1",
...     start=IdCoordinate(15343.0, TimeUnit.pixels, "dgt1"),
...     end=IdCoordinate(293119.0, TimeUnit.pixels, "dgt1"),
... )

are_commensurable

alignment.AlignmentBundle.are_commensurable(timeline_a, timeline_b)

Check if two timelines can be connected via transfer.

Two timelines are commensurable if they share the same group or if a cross-group path exists via MatchClaims.

Parameters

Name Type Description Default
timeline_a str First timeline ID (bundle UID). required
timeline_b str Second timeline ID (bundle UID). required

Returns

Name Type Description
bool True if coordinates can be transferred between them.

create_match_claims

alignment.AlignmentBundle.create_match_claims(
    event_pairs,
    *,
    synchronous=True,
    agent='user',
    agent_identifier='manual',
)

Create MatchClaims from a list of event pairs.

Convenience factory for creating multiple MatchClaims from paired events. Each tuple specifies two events and their timeline IDs.

Parameters

Name Type Description Default
event_pairs list[tuple[dict | str | None, str, dict | str | None, str]] List of tuples, each containing: (event_a, timeline_a_id, event_b, timeline_b_id). event_a/event_b are each one of: an event dict (must have at least a start key with a coordinate; an end key on both sides produces an interval match), the id string of an existing event on the paired timeline (resolved via Timeline.get_event()), or None. Exactly one of event_a/event_b may be None, producing a NOMATCH claim for the other side’s event. The forms may be mixed within a pair. required
synchronous bool Whether the matches are temporally synchronous. Ignored for NOMATCH pairs, which are always non-synchronous. True
agent str Name of the agent creating the claims (for provenance). 'user'
agent_identifier str The agent’s stable identifier — a version string for a software agent or a URI for a human agent (e.g. "manual", "dynamic_time_warping"). Stored as Agent.identifier. 'manual'

Returns

Name Type Description
list[MatchClaim] List of MatchClaim objects. Also automatically adds them to
list[MatchClaim] the bundle’s cross_group_claims.

Raises

Name Type Description
ValueError If event dicts are missing required keys, an event id string doesn’t resolve to an existing event, or both event_a and event_b are None.

Examples

>>> pairs = [
...     ({"start": 0.0}, "score", {"start": 45.5}, "audio"),
...     ("note:000010", "score", "note:000042", "audio"),
...     ("note:000099", "score", None, "audio"),  # NOMATCH
... ]
>>> claims = bundle.create_match_claims(pairs, agent="manual_alignment")
>>> len(claims)
3

diagram

alignment.AlignmentBundle.diagram(
    width=80,
    show_children=True,
    max_children=6,
    max_standalone=6,
    unicode=True,
)

Generate ASCII diagram for this bundle.

Parameters

Name Type Description Default
width int Total width of the diagram in characters. 80
show_children bool Whether to expand child timelines. True
max_children int Maximum children per timeline. 6
max_standalone int Maximum standalone timelines to display before truncating with an ellipsis. 6
unicode bool Use Unicode characters (True) or ASCII fallback (False). True

Returns

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

Examples

>>> print(bundle.diagram())
AlignmentBundle[thoresen_alignment]

TimelineGroup[dgt1_group] (2 timelines, 2 timestamps) ┌──────────────────────────────────────────────────────┐ │ DiscreteGraphicalTimeline[dgt1:1] (11 events) │ │ 0 ∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶∶ 4835 pixels │ └──────────────────────────────────────────────────────┘ Timestamps: 2

MatchClaims: 5

from_bundles

alignment.AlignmentBundle.from_bundles(bundles, *, id='', name=None)

Merge multiple bundles’ groups, standalone timelines, and claims.

Registers every group and standalone timeline from each source bundle into a new bundle, preserving each source’s bundle-UID namespace, and carries over every cross-group MatchClaim (both the per-claim list and any columnar MatchClaimField stores) unchanged. Groups from different source bundles remain distinct — merging does not itself align timelines across bundles. Add cross-group MatchClaims (e.g. via :meth:create_match_claims) afterwards to align them.

Parameters

Name Type Description Default
bundles list['AlignmentBundle'] The bundles to merge, in order. required
id str Explicit ID for the merged bundle. Auto-generated if omitted. ''
name str | None Optional human-readable name for the merged bundle. None

Returns

Name Type Description
'AlignmentBundle' A new AlignmentBundle containing every group, standalone
'AlignmentBundle' timeline, and cross-group claim from bundles.

Raises

Name Type Description
ValueError If two source bundles share a group ID, or a timeline UID collision would occur across bundles.

Examples

>>> merged = AlignmentBundle.from_bundles([score_bundle, audio_bundle])
>>> merged.groups.keys() == score_bundle.groups.keys() | audio_bundle.groups.keys()
True

get_claim_fields

alignment.AlignmentBundle.get_claim_fields(
    timeline_id=None,
    timeline_ids=None,
    id_pattern=None,
    between=None,
    synchronous_only=False,
    nomatch_only=False,
    include_domains=None,
    include_units=None,
)

Query the columnar claim stores, materialising nothing.

This is the scalable counterpart of :meth:get_match_claims for bundles whose claims live in a MatchClaimField — a dense pairwise alignment can hold hundreds of thousands of claims, and turning each one into a Python object costs orders of magnitude more than the columnar answer. Every filter is applied as a vectorized PyArrow mask, and the result is a list of filtered fields, one per store that still has rows.

The filter parameters are exactly those of :meth:get_match_claims and carry the same meaning. Because a MatchClaimField holds synchronous claims only, synchronous_only is a no-op here and nomatch_only returns nothing.

Parameters

Name Type Description Default
timeline_id str | None Keep claims involving this bundle UID. None
timeline_ids set[str] | None Keep claims involving any of these bundle UIDs. None
id_pattern str | None Regex matched against bundle UIDs via re.search(). None
between tuple[str, str] | None Keep claims connecting exactly these two bundle UIDs (order-independent). None
synchronous_only bool No-op (every stored claim is synchronous). False
nomatch_only bool Returns an empty list. False
include_domains set['Domain'] | None Only timelines in these domains. None
include_units set['TimeUnit'] | None Only timelines with these units. None

Returns

Name Type Description
list[MatchClaimField] Filtered MatchClaimField objects, empty stores dropped.

Examples

>>> fields = bundle.get_claim_fields(timeline_id="rec-a:cpt1")
>>> sum(len(f) for f in fields)
66780

get_group

alignment.AlignmentBundle.get_group(uid)

Get a group by ID.

Supports partial string and regex matching: 1. Exact match: If uid matches an ID exactly, returns it. 2. Substring match: If uid is a substring of exactly one ID, returns that group. If multiple match, returns the first and warns. 3. Regex match: If uid is a valid regex, matches via re.search(). Same first-match logic with warning.

Parameters

Name Type Description Default
uid str The group’s unique identifier, or a partial/regex pattern. required

Returns

Name Type Description
TimelineGroup The TimelineGroup object.

Raises

Name Type Description
KeyError If no group matches the pattern.

Examples

>>> bundle.get_group("score")            # Substring match
>>> bundle.get_group(r"^perf")           # Regex match

get_group_for_timeline

alignment.AlignmentBundle.get_group_for_timeline(timeline_id)

Get the group containing a timeline.

Parameters

Name Type Description Default
timeline_id str The timeline’s unique identifier. required

Returns

Name Type Description
TimelineGroup | None The TimelineGroup containing the timeline, or None if standalone.

get_match_claims

alignment.AlignmentBundle.get_match_claims(
    timeline_id=None,
    timeline_ids=None,
    id_pattern=None,
    between=None,
    synchronous_only=False,
    nomatch_only=False,
    include_domains=None,
    include_units=None,
)

Query MatchClaims connecting timelines across groups.

This is the primary interface for accessing alignment information. All parameters are optional; when none are provided, returns all claims.

Filters are combined with AND logic: a claim must satisfy every non-None criterion. Uses the Unified Filter API.

Both claim stores are queried: the per-claim Python list and every columnar MatchClaimField. The columnar matches are filtered vectorized but then materialised, one MatchClaim per surviving row — for a dense pairwise alignment that is O(n) Python objects. Use :meth:get_claim_fields when the columnar answer suffices, or narrow the query first.

Parameters

Name Type Description Default
timeline_id str | None Return claims involving this bundle UID. None
timeline_ids set[str] | None Return claims involving any of these bundle UIDs. None
id_pattern str | None Regex pattern matched against bundle UIDs via re.search(). Example: r"^perf:" matches all performance timelines. None
between tuple[str, str] | None Return claims connecting exactly these two bundle UIDs (order-independent). None
synchronous_only bool Exclude non-synchronous (NOMATCH) claims. False
nomatch_only bool Return only non-synchronous (NOMATCH) claims. False
include_domains set['Domain'] | None Only timelines in these domains. None
include_units set['TimeUnit'] | None Only timelines with these units. None

Returns

Name Type Description
list[MatchClaim] Filtered list of MatchClaims.

Examples

Get all synchronous claims for a performer::

>>> claims = bundle.get_match_claims(
...     id_pattern=r"dlt1$", synchronous_only=True
... )

Get NOMATCH claims for a specific pair::

>>> nomatches = bundle.get_match_claims(
...     between=("score:clt1", "perf:dlt5"),
...     nomatch_only=True,
... )

get_matchstamp_at

alignment.AlignmentBundle.get_matchstamp_at(
    coordinate,
    timeline_id=None,
    *,
    support_policy=None,
    conversion_maps=False,
    timeline_ids=None,
    id_pattern=None,
    include_domains=None,
    include_units=None,
)

Get a cross-group MatchStamp at a coordinate on a timeline.

This is the primary interface for cross-domain coordinate transfer. Given a coordinate on one timeline, returns coordinates on ALL connected timelines across ALL groups.

The stamp is the transitive cross-group union reachable from the query. Exact-anchor coordinates from the coordinate’s MatchGraph are overlaid first (exact wins over interpolated), then the assembly walks outward across groups to closure: every reached timeline expands into its own group (by interpolation) and warps into not-yet-reached groups (by WarpMap). is_interpolated is False exactly when the query node itself carries an explicit anchor.

A timeline whose transferred coordinate falls outside alignment support — the entering coordinate lies outside the transferring WarpMap’s source-anchor hull, or the produced coordinate would fall outside [0, length] — is handled by support_policy. No policy ever yields a negative coordinate or one beyond a timeline’s length.

Parameters

Name Type Description Default
coordinate CoordinateSpec The query coordinate. Can be: - int/float/Fraction: Raw value, timeline_id required. - Coordinate: Value with unit, timeline_id required. - IdCoordinate: Value with unit AND timeline_id (timeline_id param optional). required
timeline_id str | None Bundle UID of the source timeline. Required unless coordinate is an IdCoordinate, in which case the coordinate’s own timeline_id is used. None
support_policy 'SupportPolicy | str | None' How to treat out-of-support timelines (omit / clamp / extrapolate). Accepts a :class:~timetoalign.core.SupportPolicy or its string name. None (the default) uses the bundle’s support_policy setting, itself omit by default. The query timeline’s own coordinate is never dropped, clamped, or altered. None
conversion_maps 'ConversionMapsSpec' C-map conversions available through unit lookup and display. Opt-in: defaults to False. False
timeline_ids set[str] | None Only include these bundle UIDs in the result. None
id_pattern str | None Regex filter for bundle UIDs in the result. None
include_domains set['Domain'] | None Only these domains in the result. None
include_units set['TimeUnit'] | None Only these units in the result. None

Returns

Name Type Description
MatchStamp MatchStamp spanning all connected timelines.

Raises

Name Type Description
TypeError If coordinate is not int/float/Fraction/Coordinate/ IdCoordinate.
ValueError If timeline_id is None and coordinate is not an IdCoordinate.
KeyError If timeline_id is not in the bundle.

Examples

>>> ms = bundle.get_matchstamp_at(10.0, "score:clt1")
>>> ms.n_timelines
23  # score + 22 performers

get_matchstamp_table

alignment.AlignmentBundle.get_matchstamp_table(
    claims=None,
    *,
    coordinates=None,
    timeline_id=None,
    timeline_filter=None,
    from_graph=False,
    conversion_maps=False,
)

Get a PyArrow table of MatchStamps for alignment queries.

Analogous to get_timestamp_table() but for cross-group alignment. Fields are timeline IDs holding their coordinate values; what a row is depends on from_graph:

  • from_graph=False (default) — one row per synchronous claim. A pairwise claim fills exactly two cells and leaves the rest null, so a dense pairwise alignment produces one sparse row per claim.
  • from_graph=True — one row per connected component of the (timeline_id, coordinate) graph the claims induce. The pairwise rows above collapse into the cross-section they describe: one row per aligned instant, every participating timeline filled.

When claims is None both claim stores are read: the per-claim Python list and every columnar MatchClaimField. The columnar stores are read four Arrow columns at a time — no MatchClaim is ever materialised — which is what keeps a hundreds-of-thousands-of-rows alignment tabulable.

When coordinates is given instead of claims, each coordinate is resolved through :meth:get_matchstamp_at and becomes exactly one row — a full transitive cross-section, every reached timeline filled — in input order. from_graph does not apply on this path (the stamps are already collapsed cross-sections) and is ignored.

Parameters

Name Type Description Default
claims list[MatchClaim] | None List of MatchClaims to tabulate. If None, uses every cross-group claim in the bundle (both stores). When given, only those claims are tabulated. Mutually exclusive with coordinates. None
coordinates Iterable[CoordinateSpec] | None Query coordinates to resolve through :meth:get_matchstamp_at, one row per coordinate in input order. Each element is a raw int/float/Fraction or Coordinate (needing timeline_id) or an IdCoordinate (carrying its own timeline). Mutually exclusive with claims. None
timeline_id str | None Source timeline for the coordinates batch; may be None when every element is an IdCoordinate. Ignored on the claims path. None
timeline_filter set[str] | None Only include these timeline fields. None
from_graph bool Collapse claims into one row per connected component instead of one row per claim. Ignored on the coordinates path. False
conversion_maps 'ConversionMapsSpec' C-map conversions to add as derived columns, one per (timeline, enabled unit-conversion map). Opt-in: defaults to False. Only numeric unit-conversion maps (a target_unit set) become columns; label/structured maps appear in stamp display but never as table columns. False

Returns

Name Type Description
'pa.Table' PyArrow Table with one field per timeline. Non-synchronous claims
'pa.Table' are excluded. Empty input yields an empty table.

Raises

Name Type Description
ValueError If both claims and coordinates are given.

Note

Collapsed rows are ordered by the coordinate on the lexicographically smallest timeline ID present in the component, then by that ID — a total order, since two components can never share a (timeline_id, coordinate) node. A component that somehow carries two coordinates for one timeline (which a well-formed alignment never does) keeps the smaller one.

Examples

>>> table = bundle.get_matchstamp_table()
>>> table.num_rows
100
>>> table.column_names
['score:clt1', 'perf:dlt1', 'perf:dlt2', ...]
>>> bundle.get_matchstamp_table(from_graph=True).num_rows
25
>>> bundle.get_matchstamp_table(
...     coordinates=[0.0, 50.0], timeline_id="score:clt1"
... ).num_rows
2

get_matchstamps

alignment.AlignmentBundle.get_matchstamps(
    claims=None,
    *,
    coordinates=None,
    timeline_id=None,
    from_graph=True,
    conversion_maps=False,
)

Get MatchStamps for a list of MatchClaims or query coordinates.

Convenience method for retrieving MatchStamps for multiple claims at once. Uses the bundle’s caching mechanism for efficient retrieval.

When coordinates is given instead of claims, each coordinate is resolved through :meth:get_matchstamp_at — the coordinate-first entry point for callers who hold coordinates rather than MatchClaim objects. Input order is preserved and every coordinate yields exactly one stamp (a full transitive cross-section).

Parameters

Name Type Description Default
claims list[MatchClaim] | None List of MatchClaims to get stamps for. If None, uses every cross-group claim in the bundle — the per-claim list and every columnar MatchClaimField (see :meth:get_match_claims, which materialises the columnar rows). Mutually exclusive with coordinates. None
coordinates Iterable[CoordinateSpec] | None Query coordinates to resolve through :meth:get_matchstamp_at, one stamp per coordinate in input order. Each element is a raw int/float/Fraction or Coordinate (needing timeline_id) or an IdCoordinate (carrying its own timeline). Mutually exclusive with claims. None
timeline_id str | None Source timeline for the coordinates batch; may be None when every element is an IdCoordinate. Ignored on the claims path. None
from_graph bool If True (default), return full MatchStamps from the MatchGraph (all connected timelines). If False, return reduced 2-timeline stamps. Ignored on the coordinates path, where each stamp is already a full cross-section. True
conversion_maps 'ConversionMapsSpec' C-map conversions available through unit lookup and display. Opt-in: defaults to False. False

Returns

Name Type Description
list[MatchStamp] List of MatchStamp objects. Non-synchronous claims yield None
list[MatchStamp] entries (filtered out).

Raises

Name Type Description
ValueError If both claims and coordinates are given.

Examples

>>> stamps = bundle.get_matchstamps()
>>> len(stamps)
100
>>> stamps[0].n_timelines
23
>>> coord_stamps = bundle.get_matchstamps(
...     coordinates=[0.0, 50.0], timeline_id="score:clt1"
... )
>>> coord_stamps[1].get("score:clt1")
50.0

get_timeline

alignment.AlignmentBundle.get_timeline(uid)

Get a timeline by ID.

Supports partial string and regex matching: 1. Exact match: If uid matches an ID exactly, returns it. 2. Substring match: If uid is a substring of exactly one ID, returns that timeline. If multiple match, returns the first and warns. 3. Regex match: If uid is a valid regex, matches via re.search(). Same first-match logic with warning.

Parameters

Name Type Description Default
uid str The timeline’s unique identifier, or a partial/regex pattern. required

Returns

Name Type Description
'Timeline' The Timeline object.

Raises

Name Type Description
KeyError If no timeline matches the pattern.

Examples

>>> bundle.get_timeline("clt1")          # Exact match
>>> bundle.get_timeline("score")         # Substring match
>>> bundle.get_timeline(r"^perf:")       # Regex match

get_timelines

alignment.AlignmentBundle.get_timelines(ids)

Get multiple timelines by their IDs.

Convenience method for retrieving several timelines at once. Each ID supports partial string and regex matching (via get_timeline()).

Parameters

Name Type Description Default
ids list[str] List of timeline IDs (or partial/regex patterns). required

Returns

Name Type Description
list['Timeline'] List of Timeline objects in the same order as the input IDs.

Raises

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

Examples

>>> timelines = bundle.get_timelines(["score", "audio", "midi"])
>>> len(timelines)
3

summary

alignment.AlignmentBundle.summary()

Get a summary of the bundle contents.

Returns a deterministic representation suitable for comparison. Keys and timeline lists are sorted for order-independence.

Returns

Name Type Description
dict[str, Any] Dictionary with bundle information.

transfer

alignment.AlignmentBundle.transfer(coord, from_timeline, to_timeline)

Transfer a coordinate from one timeline to another.

Automatically determines the conversion path:

  1. If both timelines are in the same group: direct conversion via TimelineGroup.convert().
  2. If in different groups with MatchClaims: builds a MatchLine and a cached WarpMap and calls it to interpolate the coordinate.
  3. If no path exists: returns None.

Low-level coordinate transfer utility. For user-facing coordinate queries, use get_matchstamp_at() which returns a full cross-section as a MatchStamp.

Parameters

Name Type Description Default
coord CoordinateSpec The coordinate value to transfer. required
from_timeline str Bundle UID of the source timeline. required
to_timeline str Bundle UID of the target timeline. required

Returns

Name Type Description
float | None The transferred coordinate, or None if no path exists.

Raises

Name Type Description
KeyError If either timeline is not in the bundle.

transfer_interval

alignment.AlignmentBundle.transfer_interval(
    start,
    end,
    from_timeline,
    to_timeline,
)

Transfer an interval from one timeline to another.

Parameters

Name Type Description Default
start CoordinateSpec Start coordinate in source timeline. Accepts a raw int/float/Fraction, a Coordinate, or an IdCoordinate. required
end CoordinateSpec End coordinate in source timeline. Accepts a raw int/float/Fraction, a Coordinate, or an IdCoordinate. required
from_timeline str ID of the source timeline. required
to_timeline str ID of the target timeline. required

Returns

Name Type Description
tuple[float, float] | None Tuple of (start, end) in target timeline, or None if no path.