Children, Regions, and Timestamps

Hierarchy, cross-section queries

Children, Regions, and Timestamps

Timelines nest inside one another. A timestamp is a cross-section that shows where you are in every active child at a given root coordinate.

from pathlib import Path

from timetoalign.loader.score.partitura import PartituraLoader
/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 a Structured Score

DATA_DIR = Path(".").resolve().parents[1] / "tests" / "data" / "vienna_1x22"

loader = PartituraLoader()
loader.load(DATA_DIR / "Chopin_op10_no3.musicxml")
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)

Measures as Regions

The loader’s EventStore contains measure intervals. We can filter notes by coordinate bounds.

measures = loader.store.measures.to_dataframe()
m2 = measures.iloc[1]
{
    "measure": 2,
    "start": float(m2.start),
    "end": float(m2.end),
}
{'measure': 2, 'start': 0.5, 'end': 2.5}
tl.get_child("notes").get_events(
    event_type="Note", min_coord=float(m2.start), max_coord=float(m2.end)
).to_dataframe().head()
id name temporal_type event_type start end duration mc mn mc_onset ... specific_pitch midi tpc octave tied gracenote chord_id voice staff part_id
0 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
1 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
2 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
3 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
4 notes:note:000006 B3 interval Note 3/4 1.00 1/4 2 2 1/4 ... {'step': 'B', 'alter': 0, 'octave': 3, 'cents'... 59 5 3 0 NaN NaN 3 1 P1

5 rows × 21 columns

Timestamps: Cross-Section Queries

At root coordinate X, what is the local coordinate inside each active child timeline?

timestamps_df = tl.to_dataframe()
timestamps_df.head(10)
axis (quarters) chopin_etude (quarters) notes (quarters) measures (quarters) controls (quarters) annotations (quarters) quarters_to_ticks (ticks) quarters_to_measures (floating_measures) raw_quarters (quarters)
id
notes:note:000001 0 0 0 0 0 0 0 1 -1/2
notes:note:000002 1/2 1/2 1/2 1/2 1/2 1/2 240 2 0
notes:note:000006 3/4 3/4 3/4 3/4 3/4 3/4 360 17/8 1/4
notes:note:000008 1 1 1 1 1 1 480 9/4 1/2
notes:note:000010 5/4 5/4 5/4 5/4 5/4 5/4 600 19/8 3/4
notes:note:000013 3/2 3/2 3/2 3/2 3/2 3/2 720 5/2 1
notes:note:000018 7/4 7/4 7/4 7/4 7/4 7/4 840 21/8 5/4
notes:note:000020 2 2 2 2 2 2 960 11/4 3/2
notes:note:000021 9/4 9/4 9/4 9/4 9/4 9/4 1080 23/8 7/4
notes:note:000023 5/2 5/2 5/2 5/2 5/2 5/2 1200 3 2

NaN means the coordinate falls outside that child’s extent.

Next: Timeline Groups