from pathlib import Path
from timetoalign.loader.score.partitura import PartituraLoaderChildren, 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.
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")
tlContinuousLogicalTimeline[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 | duration_float | mc | mn | ... | specific_pitch | tpc | octave | velocity | tied | gracenote | chord_id | voice | staff | part_id | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | notes:note:000002 | E4 | interval | Note | 1/2 | 1.00 | 1/2 | 0.50 | 2 | 2 | ... | {'gpc_int': 2, 'gpc_str': 'E', 'acc': 0, 'spc_... | 4 | 4 | 64 | 0 | NaN | NaN | 1 | 1 | P1 |
| 1 | notes:note:000003 | G♯3 | interval | Note | 1/2 | 0.75 | 1/4 | 0.25 | 2 | 2 | ... | {'gpc_int': 4, 'gpc_str': 'G', 'acc': 1, 'spc_... | 8 | 3 | 64 | 0 | NaN | NaN | 3 | 1 | P1 |
| 2 | notes:note:000004 | E2 | interval | Note | 1/2 | 0.75 | 1/4 | 0.25 | 2 | 2 | ... | {'gpc_int': 2, 'gpc_str': 'E', 'acc': 0, 'spc_... | 4 | 2 | 64 | 0 | NaN | NaN | 4 | 2 | P1 |
| 3 | notes:note:000005 | E2 | interval | Note | 1/2 | 1.50 | 1 | 1.00 | 2 | 2 | ... | {'gpc_int': 2, 'gpc_str': 'E', 'acc': 0, 'spc_... | 4 | 2 | 64 | 0 | NaN | NaN | 7 | 2 | P1 |
| 4 | notes:note:000006 | B3 | interval | Note | 3/4 | 1.00 | 1/4 | 0.25 | 2 | 2 | ... | {'gpc_int': 6, 'gpc_str': 'B', 'acc': 0, 'spc_... | 5 | 3 | 64 | 0 | NaN | NaN | 3 | 1 | P1 |
5 rows × 23 columns
Timestamps: Cross-Section Queries
At root coordinate X, what is the local coordinate inside each active child timeline?
timestamps_df = tl.get_timestamps()
timestamps_df.head(10)| axis (quarters) | chopin_etude (quarters) | notes (quarters) | measures (quarters) | controls (quarters) | annotations (quarters) | quarters_to_ticks (ticks) | quarters_to_measures (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