0
# Data Query and Access
1
2
This document covers querying element attributes, timing information, MIDI values, page locations, and other data from loaded music notation documents.
3
4
## Capabilities
5
6
### Element Attributes
7
8
Access attributes of specific elements in the loaded document.
9
10
```python { .api }
11
class toolkit:
12
def getElementAttr(self, xmlId: str) -> dict:
13
"""
14
Get all attributes of an element as a dictionary.
15
16
Returns all attributes, including those not directly supported
17
by Verovio.
18
19
Args:
20
xmlId: The @xml:id of the element
21
22
Returns:
23
Dictionary with all element attributes
24
"""
25
26
def getNotatedIdForElement(self, xmlId: str) -> str:
27
"""
28
Get the ID of the notated (original) element.
29
30
When elements are expanded (e.g., due to repeats), this returns
31
the ID of the original notated element.
32
33
Args:
34
xmlId: The @xml:id of an element (notated or expanded)
35
36
Returns:
37
ID string of the notated element
38
"""
39
40
def getExpansionIdsForElement(self, xmlId: str) -> list:
41
"""
42
Get IDs of all elements (notated and expanded) for a given element.
43
44
When notation includes repeats or other expansions, this returns
45
the IDs of both the notated element and all its expanded instances.
46
47
Args:
48
xmlId: The @xml:id of an element
49
50
Returns:
51
List containing all related IDs
52
"""
53
```
54
55
### Page Location
56
57
Find which page contains a specific element.
58
59
```python { .api }
60
class toolkit:
61
def getPageWithElement(self, xmlId: str) -> int:
62
"""
63
Get the page number where an element is rendered.
64
65
Takes into account current layout options.
66
67
Args:
68
xmlId: The @xml:id of the element
69
70
Returns:
71
Page number (1-based) where element appears, or 0 if not found
72
"""
73
```
74
75
### Timing Information
76
77
Query temporal information for elements.
78
79
```python { .api }
80
class toolkit:
81
def getElementsAtTime(self, millisec: int) -> dict:
82
"""
83
Get IDs of elements being played at a specific time.
84
85
Args:
86
millisec: Time in milliseconds
87
88
Returns:
89
Dictionary with page number and list of note IDs being played
90
"""
91
92
def getTimeForElement(self, xmlId: str) -> int:
93
"""
94
Get the playback time for an element.
95
96
renderToMIDI() must be called before using this method.
97
98
Args:
99
xmlId: The @xml:id of the element
100
101
Returns:
102
Time in milliseconds when element is played
103
"""
104
105
def getTimesForElement(self, xmlId: str) -> dict:
106
"""
107
Get detailed timing information for a note element.
108
109
Returns score time and real time values for onset, offset,
110
and tied duration.
111
112
Args:
113
xmlId: The @xml:id of a note element
114
115
Returns:
116
Dictionary with timing information:
117
- scoreTimeOnset: Score time onset
118
- scoreTimeOffset: Score time offset
119
- scoreTimeTiedDuration: Score time tied duration
120
- realTimeOnsetMilliseconds: Real time onset in ms
121
- realTimeOffsetMilliseconds: Real time offset in ms
122
- realTimeTiedDurationMilliseconds: Real time tied duration in ms
123
"""
124
```
125
126
### MIDI Information
127
128
Access MIDI values for musical elements.
129
130
```python { .api }
131
class toolkit:
132
def getMIDIValuesForElement(self, xmlId: str) -> dict:
133
"""
134
Get MIDI values for an element.
135
136
renderToMIDI() must be called before using this method.
137
138
Args:
139
xmlId: The @xml:id of the element
140
141
Returns:
142
Dictionary with MIDI values (pitch, velocity, channel, etc.)
143
"""
144
```
145
146
### Descriptive Features
147
148
Extract features for music information retrieval tasks.
149
150
```python { .api }
151
class toolkit:
152
def getDescriptiveFeatures(self, options: dict | None = None) -> dict:
153
"""
154
Extract descriptive features from the loaded document.
155
156
Features are tailored for implementing incipit search and
157
other music information retrieval tasks.
158
159
Args:
160
options: Dictionary with feature extraction options, optional
161
162
Returns:
163
Dictionary with requested features
164
"""
165
```
166
167
## Usage Examples
168
169
### Finding Elements on a Page
170
171
```python
172
import verovio
173
174
tk = verovio.toolkit()
175
tk.loadFile("score.mei")
176
177
# Find which page contains a specific note
178
note_id = "note-123"
179
page_num = tk.getPageWithElement(note_id)
180
181
if page_num > 0:
182
print(f"Note {note_id} is on page {page_num}")
183
184
# Render that page
185
svg = tk.renderToSVG(pageNo=page_num)
186
else:
187
print(f"Note {note_id} not found")
188
```
189
190
### Element Attribute Inspection
191
192
```python
193
import verovio
194
195
tk = verovio.toolkit()
196
tk.loadFile("score.mei")
197
198
# Get all attributes of an element
199
element_id = "note-456"
200
attributes = tk.getElementAttr(element_id)
201
202
print(f"Attributes of {element_id}:")
203
for attr_name, attr_value in attributes.items():
204
print(f" {attr_name}: {attr_value}")
205
206
# Check specific attributes
207
if 'pname' in attributes:
208
print(f"Pitch name: {attributes['pname']}")
209
if 'oct' in attributes:
210
print(f"Octave: {attributes['oct']}")
211
```
212
213
### Playback Synchronization
214
215
```python
216
import verovio
217
import time
218
219
tk = verovio.toolkit()
220
tk.loadFile("score.mei")
221
222
# Render to MIDI first (required for timing queries)
223
tk.renderToMIDI()
224
225
# Simulate playback - highlight notes at current time
226
playback_time_ms = 0
227
duration_ms = 10000 # 10 seconds
228
229
while playback_time_ms < duration_ms:
230
# Get elements being played at current time
231
elements = tk.getElementsAtTime(playback_time_ms)
232
233
if elements.get('notes'):
234
page = elements.get('page')
235
note_ids = elements.get('notes')
236
print(f"Time {playback_time_ms}ms: Page {page}, Notes: {note_ids}")
237
238
time.sleep(0.1)
239
playback_time_ms += 100
240
```
241
242
### Detailed Timing Analysis
243
244
```python
245
import verovio
246
247
tk = verovio.toolkit()
248
tk.loadFile("score.mei")
249
tk.renderToMIDI()
250
251
# Analyze timing for a note
252
note_id = "note-789"
253
times = tk.getTimesForElement(note_id)
254
255
print(f"Timing for {note_id}:")
256
print(f" Score time onset: {times['scoreTimeOnset']}")
257
print(f" Score time offset: {times['scoreTimeOffset']}")
258
print(f" Real onset: {times['realTimeOnsetMilliseconds']} ms")
259
print(f" Real offset: {times['realTimeOffsetMilliseconds']} ms")
260
print(f" Duration: {times['realTimeTiedDurationMilliseconds']} ms")
261
262
# Calculate duration
263
duration = times['realTimeOffsetMilliseconds'] - times['realTimeOnsetMilliseconds']
264
print(f" Calculated duration: {duration} ms")
265
```
266
267
### MIDI Value Extraction
268
269
```python
270
import verovio
271
272
tk = verovio.toolkit()
273
tk.loadFile("score.mei")
274
tk.renderToMIDI()
275
276
# Get MIDI values for analysis
277
note_id = "note-101"
278
midi_values = tk.getMIDIValuesForElement(note_id)
279
280
print(f"MIDI values for {note_id}:")
281
if 'pitch' in midi_values:
282
print(f" MIDI pitch: {midi_values['pitch']}")
283
if 'velocity' in midi_values:
284
print(f" Velocity: {midi_values['velocity']}")
285
if 'channel' in midi_values:
286
print(f" Channel: {midi_values['channel']}")
287
```
288
289
### Working with Expanded Elements
290
291
```python
292
import verovio
293
294
tk = verovio.toolkit()
295
tk.loadFile("score_with_repeats.mei")
296
297
# Get the notated (original) ID for an expanded element
298
expanded_id = "note-repeat-2-note-123"
299
notated_id = tk.getNotatedIdForElement(expanded_id)
300
print(f"Notated ID: {notated_id}")
301
302
# Get all expansion IDs for a notated element
303
expansion_ids = tk.getExpansionIdsForElement(notated_id)
304
print(f"All expansions: {expansion_ids}")
305
306
# Query attributes of the notated element
307
notated_attrs = tk.getElementAttr(notated_id)
308
print(f"Notated element attributes: {notated_attrs}")
309
```
310
311
### Feature Extraction for Search
312
313
```python
314
import verovio
315
316
tk = verovio.toolkit()
317
tk.loadFile("score.mei")
318
319
# Extract features for incipit search
320
features = tk.getDescriptiveFeatures()
321
322
print("Extracted features:")
323
for feature_name, feature_value in features.items():
324
print(f" {feature_name}: {feature_value}")
325
326
# Use features for music similarity comparison
327
# or incipit-based search
328
```
329
330
### Building an Interactive Score Viewer
331
332
```python
333
import verovio
334
335
class ScoreViewer:
336
def __init__(self, filename):
337
self.tk = verovio.toolkit()
338
self.tk.loadFile(filename)
339
self.tk.renderToMIDI() # Enable timing queries
340
341
def get_element_info(self, element_id):
342
"""Get comprehensive information about an element."""
343
info = {
344
'attributes': self.tk.getElementAttr(element_id),
345
'page': self.tk.getPageWithElement(element_id),
346
'times': self.tk.getTimesForElement(element_id),
347
'midi': self.tk.getMIDIValuesForElement(element_id)
348
}
349
return info
350
351
def highlight_elements_at_time(self, millisec):
352
"""Get elements to highlight during playback."""
353
return self.tk.getElementsAtTime(millisec)
354
355
def find_notated_element(self, expanded_id):
356
"""Find the original notated element for an expanded one."""
357
return self.tk.getNotatedIdForElement(expanded_id)
358
359
# Usage
360
viewer = ScoreViewer("score.mei")
361
note_info = viewer.get_element_info("note-123")
362
print(f"Note is on page {note_info['page']}")
363
print(f"Note attributes: {note_info['attributes']}")
364
```
365
366
### Timing-Based Element Lookup
367
368
```python
369
import verovio
370
371
tk = verovio.toolkit()
372
tk.loadFile("score.mei")
373
tk.renderToMIDI()
374
375
# Find all elements played in a time range
376
start_time = 1000 # 1 second
377
end_time = 3000 # 3 seconds
378
interval = 100 # 100ms steps
379
380
elements_in_range = []
381
for t in range(start_time, end_time, interval):
382
result = tk.getElementsAtTime(t)
383
if result.get('notes'):
384
elements_in_range.extend(result['notes'])
385
386
# Remove duplicates
387
unique_elements = list(set(elements_in_range))
388
print(f"Elements played between {start_time}-{end_time}ms:")
389
print(unique_elements)
390
391
# Get details for each element
392
for elem_id in unique_elements:
393
attrs = tk.getElementAttr(elem_id)
394
print(f" {elem_id}: {attrs}")
395
```
396