Timelines, Events, and Maps
Load real musical data, explore it as an EventStore, create a Timeline, and attach a ConversionMap to translate between units.
from pathlib import Path
from timetoalign.loader.score.partitura import PartituraLoader
from timetoalign.maps import TicksToQuarters
/home/laser/miniconda3/envs/timetoalign/lib/python3.11/site-packages/partitura/__init__.py:9: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81.
import pkg_resources
Load Events from a Score
DATA_DIR = Path("." ).resolve().parents[1 ] / "tests" / "data" / "vienna_1x22"
loader = PartituraLoader()
loader.load(DATA_DIR / "Chopin_op10_no3.musicxml" )
loader.store
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
File ~/miniconda3/envs/timetoalign/lib/python3.11/site-packages/IPython/core/formatters.py:406 , in BaseFormatter.__call__ (self, obj)
404 method = get_real_method(obj, self .print_method)
405 if method is not None :
--> 406 return method ( )
407 return None
408 else :
File ~/git/tta/timetoalign/timetoalign/storage/store.py:249 , in EventStore._repr_html_ (self)
247 rows = []
248 for name, info in summary.items():
--> 249 unit = info . get (" unit " , " unknown " )
250 count = info.get(" count " , 0 )
251 coord_range = info.get(" range " , (0.0 , 0.0 ))
AttributeError : 'int' object has no attribute 'get'
ScoreStore(notes=498, measures=22, controls=22, annotations=5)
Create a Timeline
tl = loader.create_timeline(uid= "chopin_etude" )
tl
ContinuousLogicalTimeline[chopin_etude] (547 events, 4 children, 3 cmaps)
0 ________________________________ 41.5 quarters
├─ notes 0 ________________________________ 41.5 (498 events)
├─ measures 0 ________________________________ 41.5 (22 events)
├─ controls 0 ______________________________ 40 (22 events)
└─ annotations 0 _________________________ 32.5 (5 events)
Access Events
The loader creates child timelines for each event category (notes, measures, controls). Access them via get_child().
tl.get_child("notes" ).get_events(event_type= "Note" ).to_dataframe().head()
0
notes:note:000001
B3
interval
Note
0
0.50
1/2
1
1
0
...
{'step': 'B', 'alter': 0, 'octave': 3, 'cents'...
59
5
3
0
NaN
NaN
1
1
P1
1
notes:note:000002
E4
interval
Note
1/2
1.00
1/2
2
2
0
...
{'step': 'E', 'alter': 0, 'octave': 4, 'cents'...
64
4
4
0
NaN
NaN
1
1
P1
2
notes:note:000003
G♯3
interval
Note
1/2
0.75
1/4
2
2
0
...
{'step': 'G', 'alter': 1, 'octave': 3, 'cents'...
56
8
3
0
NaN
NaN
3
1
P1
3
notes:note:000004
E2
interval
Note
1/2
0.75
1/4
2
2
0
...
{'step': 'E', 'alter': 0, 'octave': 2, 'cents'...
40
4
2
0
NaN
NaN
4
2
P1
4
notes:note:000005
E2
interval
Note
1/2
1.50
1
2
2
0
...
{'step': 'E', 'alter': 0, 'octave': 2, 'cents'...
40
4
2
0
NaN
NaN
7
2
P1
5 rows × 21 columns
Coordinates
A Coordinate binds a number to a unit, ensuring type-safe arithmetic.
coord = tl.make_coordinate(8 )
coord
Conversion Maps (C-Maps)
Attach a map to translate the timeline’s native quarters into MIDI ticks (at 480 pulses per quarter).
q2t = TicksToQuarters(ppq= 480 ).inverse()
tl.add_conversion_map(q2t)
ticks_coord = tl.convert_to(coord, target_unit= "ticks" )
{
"input" : f" { coord. value} { coord. unit. name} " ,
"output" : f" { ticks_coord} " ,
}
{'input': '8 quarters', 'output': '3840 ticks'}
Next: Children, Regions & Timestamps