Skip to main content

A library for representing and aligning musical timelines

Project description

TimeToAlign!

A Python library for representing and aligning musical timelines.

Installation

cd timetoalign
pip install -e .                # Core only — lightweight

The core install pulls in only PyArrow, pandas, NetworkX, and typing_extensions. This gives you the full timeline / map / alignment framework but no file-format-specific loaders. If you need loaders, plotting, or Jupyter support, install one of the optional extras described below. To run the tutorial notebooks (see below), for example:

pip install -e ".[tutorial]"    # Loaders + plotting + Jupyter

Optional Dependencies

TimeToAlign! organises its optional dependencies into atomic extras (one concern each) and composite extras (convenience bundles that include several atomic ones). You can mix and match freely: pip install -e ".[midi,plot]" is perfectly valid.

Atomic extras

Each atomic extra adds support for a single loader backend or feature.

Extra Packages Purpose
midi mido MIDI file loading (PerformanceMidiLoader)
partitura partitura Score parsing via partitura (PartituraLoader, ScoreMidiLoader)
music21 music21 Score parsing via music21 (Music21Loader)
ms3 ms3 DCML TSV score parsing (TSVLoader)
audio soundfile, mutagen Audio file loading + MP3/M4A metadata
graphical pymupdf, pillow PDF/image loading & drawing
plot matplotlib Visualisation (WP1 plotting)
delta deltalake Delta Lake columnar storage (future)
rdf rdflib RDF / linked-data export (future)

Composite extras

Composite extras are convenience bundles that pull in several atomic extras at once. Each level includes everything below it.

Extra Includes Purpose
scores partitura, music21, ms3 All score-loader backends
loaders midi, scores, audio, graphical Every loader dependency
tutorial loaders, plot, plus jupytext, jupyter Everything needed for the tutorial notebooks
all tutorial, delta, rdf All runtime features
dev all, plus pre-commit, pytest, pytest-cov, pytest-benchmark, hypothesis, ruff All features + development / CI tooling

The inclusion chain is:

dev  ⊃  all  ⊃  tutorial  ⊃  loaders  ⊃  { midi, scores, audio, graphical }
                                        +  plot, jupytext, jupyter
                            +  delta, rdf

Examples

From the repository root:

pip install -e .                         # Core only
pip install -e ".[midi]"                 # Core + MIDI loading
pip install -e ".[partitura]"            # Core + partitura score parsing
pip install -e ".[scores]"               # Core + all score-loader backends
pip install -e ".[loaders]"              # Core + every loader
pip install -e ".[tutorial]"             # Loaders + plotting + Jupyter
pip install -e ".[all]"                  # All runtime features
pip install -e ".[dev]"                  # Editable install + everything + dev tooling

Quick Start

import timetoalign as tta

# Create a 60-second audio timeline
audio = tta.ContinuousPhysicalTimeline(length=60.0, uid="audio", name="Piano Recording")

# Add beats and notes -- IDs and temporal_type are inferred automatically
audio.add_events([
    {"event_type": "Beat", "instant": 0.0},
    {"event_type": "Beat", "instant": 0.5},
    {"event_type": "Beat", "instant": 1.0},
    {"event_type": "Note", "start": 0.0, "end": 0.5},
    {"event_type": "Note", "start": 8.0, "end": 12.0},   # spans Intro -> Verse
])

# Nest children (sections of the same recording)
intro  = audio.create_child(length=10.0, offset=0.0,  uid="intro",  name="Intro")
verse  = audio.create_child(length=20.0, offset=10.0, uid="verse",  name="Verse")
chorus = audio.create_child(length=15.0, offset=30.0, uid="chorus", name="Chorus")

# Attach ConversionMaps (seconds -> milliseconds, seconds -> samples at 48 kHz)
audio.add_conversion_map(tta.ScalarMap(scalar=1000, source_unit="seconds", target_unit="milliseconds"))
audio.add_conversion_map(tta.SecondsToSamples(sample_rate=48000))

# The diagram shows the hierarchy at a glance
print(audio.diagram())
ContinuousPhysicalTimeline[audio] (5 events, 3 children)
                      0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 60 seconds
  ├─ Intro            0 ~~~~~                               10
  ├─ Verse           10      ~~~~~~~~~~~~                   30
  └─ Chorus          30                  ~~~~~~~~~          45
# A TimeStamp is a cross-section through the entire hierarchy at a given coordinate.
# Only children whose span covers the coordinate appear:
ts = audio.get_timestamp(25.0)
print(ts)
TimeStamp @25 seconds
  audio         25 seconds
  verse         15 seconds
  milliseconds  25000
  samples       1200000
# A TimeIntervalStamp gives the cross-section for a [start, end) range.
# The note at [8, 12) straddles Intro [0, 10) and Verse [10, 30):
# its start falls in Intro, its end in Verse.
tis = audio.get_interval_stamp(8.0, 12.0)
print(tis)
TimeIntervalStamp [8, 12) seconds
                 start     end
  audio              8      12 seconds
  intro              8       - seconds
  verse              -       2 seconds
  milliseconds    8000   12000
  samples       384000  576000

Tutorial Notebooks

The docs/notebooks/ directory contains Jupytext percent-script notebooks covering the library from first principles to full alignment workflows. Make sure you have installed the tutorial extra (see Installation), then generate the paired .ipynb files and launch Jupyter:

jupytext --sync docs/*-notebooks/*.py
jupyter notebook docs/tuto-notebooks/

Development

# Run the test suite
pytest

# Run linting / pre-commit hooks
tox -e lint

Glossary

Gemini

Term Definition
AlignmentAnchor A set of TimeStamps corresponding to matched events, representing their temporal equivalence across timelines. From a Match of TimeIntervalEvents, we derive a StartAnchor and EndAnchor.
AlignmentBundle The primary container object in the implementation that manages a collection of timelines, their groupings, and the coordination of transfers between them.
BeatGrid A specialized \textit{ContinuousLogicalTimeline} representing metrical structure (measures and beats) using quarter notes as the underlying coordinate unit.
Break A control event that voids contiguity at its Instant. TimeIntervals cannot span a Break, and Breaks cannot be inserted into existing TimeIntervals.
ChainMap A MultiMap that applies multiple ConversionMaps in sequence, creating a conversion path from source to target unit.
Child A timeline nested within a parent timeline, sharing the same measuring unit. Children are locked upon insertion to prevent side effects from modifications.
CombinationMap A MultiMap yielding outputs from multiple ConversionMaps simultaneously (e.g., $(x, y)$ coordinate pairs).
Commensurable Two timelines are commensurable when connected by a Match path or ConversionMap chain, enabling coordinate translation between them.
ConcatenationMap A MultiMap combining bounded ConversionMaps such that each coordinate region is handled by a specific map. Implemented as \textit{PiecewiseMap}.
Contiguity A TimeInterval is contiguous if it monotonically spans all coordinates between its start and end. An Instant is contiguous with a TimeInterval if it is synchronous with its EndInstant.
Control Event An event affecting flow control: either a Break (voiding contiguity) or a Jump (creating new contiguity).
ConversionMap A function mapping any coordinate to at most one value (another coordinate, specifier, or constant). Also called C-map.
Coordinate A position on a timeline, expressed as the distance from the origin in the timeline's measuring unit.
Discrete/Continuous A timeline is discrete when coordinates exist only at discrete points (e.g., pixels, samples); continuous otherwise (e.g., seconds, quarters).
Domain One of three temporal categories: Graphical (visual/spatial), Logical (symbolic/musical), or Physical (audio/sound).
Event Anything associated with a timeline via Instants. An InstantEvent has zero duration; a TimeIntervalEvent has duration defined by start and end coordinates.
FlowControlType A taxonomy of control events distinguishing between structural markers (e.g., \textit{repeat_start}, \textit{double_barline}) and jump instructions (e.g., \textit{dal_segno}, \textit{to_coda}).
GroupTimestamp A view object representing a synchronized instant across all commensurable timelines within a \textit{TimelineGroup}.
IdCoordinate A coordinate specification that explicitly includes the unique identifier of the timeline to which it belongs, preventing ambiguity in multi-timeline contexts.
Instant Associates a coordinate with a signification such as \enquote{start of event $e$}. Instants sharing a coordinate are synchronous.
InterpolationMap A \textit{ConversionMap} that performs coordinate conversion via linear interpolation between a set of known correspondence points.
InverseMap The reverse transformation of a bijective ConversionMap.
Jump A control event with JumpFrom and JumpTo Instants. When active, makes events at JumpTo contiguous with those ending at JumpFrom (e.g., repeats, \textit{dal segno}).
Length The distance between a timeline's origin and its last Instant. A locked timeline cannot extend its length.
LinearMap A \textit{ConversionMap} implementing an affine transformation ($f(x) = ax + b$). Includes \textit{ScalarMap} ($b=0$) and \textit{ShiftMap} ($a=1$) as special cases.
Match A claim---issued by a human or algorithmic agent---that events from disparate timelines are synchronous or equivalent, with associated metadata (agent, criteria, certainty).
MatchClaim The implementation class for a \textit{Match}, representing a specific claim of equivalence between two events, comprising one (instant) or two (interval) \textit{AlignmentAnchor}s.
MatchLine A linked list of Match objects preserving their order, enabling selection and alignment of temporal correspondences.
MatchMetadata Structured provenance information attached to a \textit{MatchClaim}, recording the agent, decision criteria, and certainty level of the match.
MatchPath A graph traversal connecting matched events across multiple timelines (e.g., $A \rightarrow B \rightarrow C$).
MetricMap A specialized \textit{ConversionMap} that handles complex metrical conversions (e.g., quarter notes to measure count) accounting for time signatures and anacrusis.
MultiMap An umbrella term for composed ConversionMaps (ChainMap, CombinationMap, ConcatenationMap).
Origin The zero coordinate of a timeline, from which all positions are measured.
PiecewiseMap The implementation of a \textit{ConcatenationMap}, applying different sub-maps to disjoint coordinate intervals.
Region A named part of a timeline defined by a TimeInterval (e.g., \enquote{Chorus}, \enquote{Verse}). Regions are not timelines and cannot hold events or maps directly.
RotationMap A \textit{ConversionMap} that implements periodic or cyclic transformations using modular arithmetic.
Segment A Child timeline that is contiguous with its siblings. A SegmentLine is a parent containing only contiguous Segments.
Synchrony Strict synchrony: Instants sharing identical coordinates. Pragmatic synchrony: Instants binned together based on a threshold (e.g., for quantisation).
TimeInterval Defined by a StartInstant and EndInstant; left-inclusive and right-exclusive $[s, e)$. The EndInstant's coordinate must be $\geq$ the StartInstant's.
Timeline A positive coordinate axis minimally defined by its origin and measuring unit. Accommodates events and potentially Children.
TimelineGroup A container for a set of commensurable timelines that are bijectively mapped to each other (e.g., via linear interpolation) and share a common timestamp table.
TimeStamp A cross-section through a timeline hierarchy, comprising the root coordinate, synchronous Child coordinates, and all ConversionMap results.
TraversalMap A sequence of TimeIntervals representing a specific traversal path through a timeline (handling Jumps and repeats). Also called T-map.
WarpMap A derived timeline where coordinates are re-adjusted based on AlignmentAnchors to align with another timeline.

Claude

Term Definition
AlignmentAnchor A set of TimeStamps corresponding to matched events, representing their temporal equivalence across timelines. From a Match of TimeIntervalEvents, we derive a StartAnchor and EndAnchor.
Break A control event that voids contiguity at its Instant. TimeIntervals cannot span a Break, and Breaks cannot be inserted into existing TimeIntervals.
Child A timeline nested within a parent timeline, sharing the same measuring unit. Children are locked upon insertion to prevent side effects from modifications.
ChainMap A MultiMap that applies multiple ConversionMaps in sequence, creating a conversion path from source to target unit.
CombinationMap A MultiMap yielding outputs from multiple ConversionMaps simultaneously (e.g., $(x, y)$ coordinate pairs).
Commensurable Two timelines are commensurable when connected by a Match path or ConversionMap chain, enabling coordinate translation between them.
ConcatenationMap A MultiMap combining bounded ConversionMaps such that each coordinate region is handled by a specific map.
Contiguity A TimeInterval is contiguous if it monotonically spans all coordinates between its start and end. An Instant is contiguous with a TimeInterval if it is synchronous with its EndInstant.
Control Event An event affecting flow control: either a Break (voiding contiguity) or a Jump (creating new contiguity).
ConversionMap A function mapping any coordinate to at most one value (another coordinate, specifier, or constant). Also called C-map.
Coordinate A position on a timeline, expressed as the distance from the origin in the timeline's measuring unit.
Discrete/Continuous A timeline is discrete when coordinates exist only at discrete points (e.g., pixels, samples); continuous otherwise (e.g., seconds, quarters).
Domain One of three temporal categories: Graphical (visual/spatial), Logical (symbolic/musical), or Physical (audio/sound).
Event Anything associated with a timeline via Instants. An InstantEvent has zero duration; a TimeIntervalEvent has duration defined by start and end coordinates.
Instant Associates a coordinate with a signification such as \enquote{start of event $e$}. Instants sharing a coordinate are synchronous.
InverseMap The reverse transformation of a bijective ConversionMap.
Jump A control event with JumpFrom and JumpTo Instants. When active, makes events at JumpTo contiguous with those ending at JumpFrom (e.g., repeats, \textit{dal segno}).
Length The distance between a timeline's origin and its last Instant. A locked timeline cannot extend its length.
Match A claim---issued by a human or algorithmic agent---that events from disparate timelines are synchronous or equivalent, with associated metadata (agent, criteria, certainty).
MatchLine A linked list of Match objects preserving their order, enabling selection and alignment of temporal correspondences.
MatchPath A graph traversal connecting matched events across multiple timelines (e.g., $A \rightarrow B \rightarrow C$).
MultiMap An umbrella term for composed ConversionMaps (ChainMap, CombinationMap, ConcatenationMap).
Origin The zero coordinate of a timeline, from which all positions are measured.
Region A named part of a timeline defined by a TimeInterval (e.g., \enquote{Chorus}, \enquote{Verse}). Regions are not timelines and cannot hold events or maps directly.
Segment A Child timeline that is contiguous with its siblings. A SegmentLine is a parent containing only contiguous Segments.
Synchrony Strict synchrony: Instants sharing identical coordinates. Pragmatic synchrony: Instants binned together based on a threshold (e.g., for quantisation).
TimeInterval Defined by a StartInstant and EndInstant; left-inclusive and right-exclusive $[s, e)$. The EndInstant's coordinate must be $\geq$ the StartInstant's.
Timeline A positive coordinate axis minimally defined by its origin and measuring unit. Accommodates events and potentially Children.
TimeStamp A cross-section through a timeline hierarchy, comprising the root coordinate, synchronous Child coordinates, and all ConversionMap results.
TraversalMap A sequence of TimeIntervals representing a specific traversal path through a timeline (handling Jumps and repeats). Also called T-map.
WarpMap A derived timeline where coordinates are re-adjusted based on AlignmentAnchors to align with another timeline.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

timetoalign-0.2.0.tar.gz (16.0 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

timetoalign-0.2.0-py3-none-any.whl (485.0 kB view details)

Uploaded Python 3

File details

Details for the file timetoalign-0.2.0.tar.gz.

File metadata

  • Download URL: timetoalign-0.2.0.tar.gz
  • Upload date:
  • Size: 16.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for timetoalign-0.2.0.tar.gz
Algorithm Hash digest
SHA256 6e6dbffb09a1d128bcb96b257389abe0c7550464dfda9bf82c69f269b5a70458
MD5 a9e2b36d3d28bbd2732246e8f485d903
BLAKE2b-256 423da72148b3beb124bcacc634aec131da99224182c2123fd47fe40d343318e1

See more details on using hashes here.

File details

Details for the file timetoalign-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: timetoalign-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 485.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for timetoalign-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 36afd5d3cc24e34581d7a434cffa43356047cfd09a761866bbd8e7b2382c2a85
MD5 a1300dc34d5e87fac7b683a70f79eda0
BLAKE2b-256 7f0e056b6c6d1b562b27828e7dfcb80f9745889f8cbebda323e0a0555c632d73

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page