kernpy 0.0.1__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kernpy/__init__.py +215 -0
- kernpy/__main__.py +217 -0
- kernpy/core/__init__.py +119 -0
- kernpy/core/_io.py +48 -0
- kernpy/core/base_antlr_importer.py +61 -0
- kernpy/core/base_antlr_spine_parser_listener.py +196 -0
- kernpy/core/basic_spine_importer.py +43 -0
- kernpy/core/document.py +965 -0
- kernpy/core/dyn_importer.py +30 -0
- kernpy/core/dynam_spine_importer.py +42 -0
- kernpy/core/error_listener.py +51 -0
- kernpy/core/exporter.py +535 -0
- kernpy/core/fing_spine_importer.py +42 -0
- kernpy/core/generated/kernSpineLexer.interp +444 -0
- kernpy/core/generated/kernSpineLexer.py +535 -0
- kernpy/core/generated/kernSpineLexer.tokens +236 -0
- kernpy/core/generated/kernSpineParser.interp +425 -0
- kernpy/core/generated/kernSpineParser.py +9954 -0
- kernpy/core/generated/kernSpineParser.tokens +236 -0
- kernpy/core/generated/kernSpineParserListener.py +1200 -0
- kernpy/core/generated/kernSpineParserVisitor.py +673 -0
- kernpy/core/generic.py +426 -0
- kernpy/core/gkern.py +526 -0
- kernpy/core/graphviz_exporter.py +89 -0
- kernpy/core/harm_spine_importer.py +41 -0
- kernpy/core/import_humdrum_old.py +853 -0
- kernpy/core/importer.py +285 -0
- kernpy/core/importer_factory.py +43 -0
- kernpy/core/kern_spine_importer.py +73 -0
- kernpy/core/mens_spine_importer.py +23 -0
- kernpy/core/mhxm_spine_importer.py +44 -0
- kernpy/core/pitch_models.py +338 -0
- kernpy/core/root_spine_importer.py +58 -0
- kernpy/core/spine_importer.py +45 -0
- kernpy/core/text_spine_importer.py +43 -0
- kernpy/core/tokenizers.py +239 -0
- kernpy/core/tokens.py +2011 -0
- kernpy/core/transposer.py +300 -0
- kernpy/io/__init__.py +14 -0
- kernpy/io/public.py +355 -0
- kernpy/polish_scores/__init__.py +13 -0
- kernpy/polish_scores/download_polish_dataset.py +357 -0
- kernpy/polish_scores/iiif.py +47 -0
- kernpy/test_grammar.sh +22 -0
- kernpy/util/__init__.py +14 -0
- kernpy/util/helpers.py +55 -0
- kernpy/util/store_cache.py +35 -0
- kernpy/visualize_analysis.sh +23 -0
- kernpy-1.0.0.dist-info/METADATA +501 -0
- kernpy-1.0.0.dist-info/RECORD +51 -0
- {kernpy-0.0.1.dist-info → kernpy-1.0.0.dist-info}/WHEEL +1 -2
- kernpy/example.py +0 -0
- kernpy-0.0.1.dist-info/LICENSE +0 -19
- kernpy-0.0.1.dist-info/METADATA +0 -19
- kernpy-0.0.1.dist-info/RECORD +0 -7
- kernpy-0.0.1.dist-info/top_level.txt +0 -1
@@ -0,0 +1,501 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: kernpy
|
3
|
+
Version: 1.0.0
|
4
|
+
Summary: Python Humdrum **kern and **mens utilities
|
5
|
+
Project-URL: Homepage, https://github.com/OMR-PRAIG-UA-ES/kernpy
|
6
|
+
Project-URL: Documentation, https://github.com/OMR-PRAIG-UA-ES/kernpy#readme
|
7
|
+
Project-URL: Issues, https://github.com/OMR-PRAIG-UA-ES/kernpy/issues
|
8
|
+
Author-email: David Rizo Valero <drizo@ua.es>, Joan Cerveto Serrano <joan.cerveto@ua.es>
|
9
|
+
License: AGPL-3.0-only
|
10
|
+
Classifier: License :: OSI Approved :: GNU Affero General Public License v3
|
11
|
+
Classifier: Operating System :: OS Independent
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
13
|
+
Requires-Python: >=3.9
|
14
|
+
Requires-Dist: antlr4-python3-runtime
|
15
|
+
Requires-Dist: pillow
|
16
|
+
Requires-Dist: requests
|
17
|
+
Requires-Dist: urllib3>=1.26.6
|
18
|
+
Description-Content-Type: text/markdown
|
19
|
+
|
20
|
+
# Python Humdrum **kern and **mens utilities
|
21
|
+
|
22
|
+
## Documentation: <a target="_blank" href="https://kernpy.pages.dev/">https://kernpy.pages.dev/</a>
|
23
|
+
|
24
|
+

|
25
|
+
|
26
|
+
## Index:
|
27
|
+
- [Code examples](#code-examples)
|
28
|
+
- [Installation](#installation)
|
29
|
+
- [Documentation](#documentation)
|
30
|
+
- [Run tests](#run-tests)
|
31
|
+
- [Contributing](#contributing)
|
32
|
+
- [Citation](#citation)
|
33
|
+
|
34
|
+
|
35
|
+
## Code examples
|
36
|
+
|
37
|
+
### Basic Usage
|
38
|
+
|
39
|
+
Load a `**kern`/`**mens` file into a `kp.Document`.
|
40
|
+
```python
|
41
|
+
import kernpy as kp
|
42
|
+
|
43
|
+
# Read a **kern file
|
44
|
+
document, errors = kp.load("path/to/file.krn")
|
45
|
+
```
|
46
|
+
|
47
|
+
Load a `**kern`/`**mens` from a string into a `kp.Document`.
|
48
|
+
```python
|
49
|
+
import kernpy as kp
|
50
|
+
|
51
|
+
document, errors = kp.loads("**kern\n*clefC3\n*k[b-e-a-]\n*M3/4\n4e-\n4g\n4c\n=1\n4r\n2cc;\n==\n*-")
|
52
|
+
```
|
53
|
+
|
54
|
+
Create a new standardized file from a `kp.Document`.
|
55
|
+
```python
|
56
|
+
import kernpy as kp
|
57
|
+
|
58
|
+
kp.dump(document, "newfile.krn")
|
59
|
+
```
|
60
|
+
|
61
|
+
Save the document in a string from a `kp.Document`.
|
62
|
+
```python
|
63
|
+
import kernpy as kp
|
64
|
+
|
65
|
+
content = kp.dumps(document)
|
66
|
+
````
|
67
|
+
|
68
|
+
### Exploring different options when creating new files
|
69
|
+
|
70
|
+
Only use the specified spines in `spine_types`.
|
71
|
+
```python
|
72
|
+
import kernpy as kp
|
73
|
+
|
74
|
+
kp.dump(document, "newfile_core.krn",
|
75
|
+
spine_types=['**kern'])
|
76
|
+
kp.dump(document, "newfile_lyrics.krn",
|
77
|
+
spine_types=['**text])
|
78
|
+
kp.dump(document, "newfile_core_and_lyrics.krn",
|
79
|
+
spine_types=['*+text'])
|
80
|
+
```
|
81
|
+
|
82
|
+
- Use `include` for selecting the **kern semantic categories **to use**. The output only contains what is passed. By default, all the categories are included.
|
83
|
+
```python
|
84
|
+
import kernpy as kp
|
85
|
+
|
86
|
+
kp.dump(document, "newfile_only_clefs.krn",
|
87
|
+
include={kp.TokenCategory.CLEF})
|
88
|
+
kp.dump(document, "newfile_only_durations_and_bounding_boxes.krn",
|
89
|
+
include={kp.TokenCategory.DURATION, kp.TokenCategory.BOUNDING_BOXES})
|
90
|
+
```
|
91
|
+
- Use `exclude` for selecting the **kern semantic categories **to not use**. The output contains everything except what is passed. By default, any category is excluded.
|
92
|
+
```python
|
93
|
+
import kernpy as kp
|
94
|
+
|
95
|
+
kp.dump(document, "newfile_without_pitches.krn",
|
96
|
+
exclude={kp.TokenCategory.PITCH})
|
97
|
+
kp.dump(document, "newfile_without_durations_or_rests.krn",
|
98
|
+
exclude={kp.TokenCategory.BARLINES, kp.TokenCategory.REST})
|
99
|
+
```
|
100
|
+
- Use `include` and `exclude` together to select the **kern semantic categories **to use**. The output combines both.
|
101
|
+
```python
|
102
|
+
import kernpy as kp
|
103
|
+
|
104
|
+
kp.dump(document, "newfile_custom.krn",
|
105
|
+
include=kp.BEKERN_CATEGORIES, # Preloaded set of simple categories
|
106
|
+
exclude={kp.TokenCategory.PITCH})
|
107
|
+
```
|
108
|
+
|
109
|
+
- Use `tokenizer` to select how the categories are split. By default, the `normalizedKern` tokenizer is used.
|
110
|
+
|
111
|
+
```python
|
112
|
+
import kernpy as kp
|
113
|
+
|
114
|
+
kp.dump(document, "newfile_normalized.krn",
|
115
|
+
tokenizer=kp.Encoding.normalizedKern) # Default tokenizer
|
116
|
+
```
|
117
|
+
Select the proper Humdrum **kern tokenizer:
|
118
|
+
|
119
|
+
`kernpy` provides different tokenizers to export the content each symbol in different formats.
|
120
|
+
|
121
|
+
| Encoding | Tokenized | Description |
|
122
|
+
|----------|--------------|----------------------------------------|
|
123
|
+
| kern | 2.bb-_L | Traditional Humdrum **kern encoding |
|
124
|
+
| ekern | 2@.@bb@-·_·L | Extended Humdrum **kern encoding |
|
125
|
+
|
126
|
+
Use the `Encoding` enum class to select the tokenizer:
|
127
|
+
|
128
|
+
```python
|
129
|
+
import kernpy as kp
|
130
|
+
|
131
|
+
doc, _ = kp.load('resource_dir/legacy/chor048.krn')
|
132
|
+
|
133
|
+
kern_content = kp.dumps(doc, tokenizer=kp.Encoding.normalizedKern)
|
134
|
+
ekern_content = kp.dumps(doc, tokenizer=kp.Encoding.eKern)
|
135
|
+
```
|
136
|
+
|
137
|
+
- Use `from_measure` and `to_measure` to select the measures to export. By default, all the measures are exported.
|
138
|
+
```python
|
139
|
+
import kernpy as kp
|
140
|
+
|
141
|
+
kp.dump(document, "newfile_1_to_10.krn",
|
142
|
+
from_measure=1, # First from measure 1
|
143
|
+
to_measure=10) # Last measure exported
|
144
|
+
```
|
145
|
+
|
146
|
+
- Use `spine_ids` to select the spines to export. By default, all the spines are exported.
|
147
|
+
```python
|
148
|
+
import kernpy as kp
|
149
|
+
|
150
|
+
kp.dump(document, "newfile_1_and_2.krn",
|
151
|
+
spine_ids=[0, 1]) # Export only the first and the second spine
|
152
|
+
```
|
153
|
+
|
154
|
+
- Use `show_measure_numbers` to select if the measure numbers are shown. By default, the measure numbers are shown.
|
155
|
+
```python
|
156
|
+
import kernpy as kp
|
157
|
+
|
158
|
+
kp.dump(document, "newfile_no_measure_numbers.krn",
|
159
|
+
show_measure_numbers=False) # Do not show measure numbers
|
160
|
+
```
|
161
|
+
|
162
|
+
- Use all the options at the same time.
|
163
|
+
|
164
|
+
```python
|
165
|
+
import kernpy as kp
|
166
|
+
|
167
|
+
kp.dump(document, "newfile.krn",
|
168
|
+
spine_types=['**kern'], # Export only the **kern spines
|
169
|
+
include=kp.BEKERN_CATEGORIES, # Token categories to include
|
170
|
+
exclude={kp.TokenCategory.PITCH}, # Token categories to exclude
|
171
|
+
tokenizer=kp.Encoding.eKern, # Kern encoding
|
172
|
+
from_measure=1, # First from measure 1
|
173
|
+
to_measure=10, # Last measure exported
|
174
|
+
spine_ids=[0, 1], # Export only the first and the second spine
|
175
|
+
show_measure_numbers=False, # Do not show measure numbers
|
176
|
+
)
|
177
|
+
```
|
178
|
+
|
179
|
+
## Exploring `kernpy` utilities.
|
180
|
+
|
181
|
+
|
182
|
+
- Spines analysis
|
183
|
+
Retrieve all the spine types of the document.
|
184
|
+
```python
|
185
|
+
import kernpy as kp
|
186
|
+
|
187
|
+
kp.spine_types(document)
|
188
|
+
# ['**kern', '**kern', '**kern', '**kern', '**root', '**harm']
|
189
|
+
|
190
|
+
kp.spine_types(document, spine_types=None)
|
191
|
+
# ['**kern', '**kern', '**kern', '**kern', '**root', '**harm']
|
192
|
+
|
193
|
+
kp.spine_types(document, spine_types=['**kern'])
|
194
|
+
# ['**kern', '**kern', '**kern', '**kern']
|
195
|
+
```
|
196
|
+
|
197
|
+
- Get specific **kern spines.
|
198
|
+
```python
|
199
|
+
import kernpy as kp
|
200
|
+
|
201
|
+
def how_many_instrumental_spines(document):
|
202
|
+
print(kp.spine_types(document, ['**kern']))
|
203
|
+
return len(kp.spine_types(document, ['**kern']))
|
204
|
+
# ['**kern', '**kern', '**kern', '**kern']
|
205
|
+
# 4
|
206
|
+
|
207
|
+
def has_voice(document):
|
208
|
+
return len(kp.spine_types(document, ['**text'])) > 0
|
209
|
+
# True
|
210
|
+
```
|
211
|
+
|
212
|
+
|
213
|
+
|
214
|
+
### How many measures are there in the document? Which measures do you want to export?
|
215
|
+
|
216
|
+
After reading the score into the `Document` object. You can get some useful data:
|
217
|
+
```python
|
218
|
+
first_measure: int = document.get_first_measure()
|
219
|
+
last_measure: int = document.measures_count()
|
220
|
+
```
|
221
|
+
|
222
|
+
Iterate over all the measures of the document.
|
223
|
+
```python
|
224
|
+
import kernpy as kp
|
225
|
+
|
226
|
+
doc, _ = kp.load('resource_dir/legacy/chor048.krn') # 10 measures score
|
227
|
+
for i in range(doc.get_first_measure(), doc.measures_count(), 1): # from 1 to 11, step 1
|
228
|
+
# Export only the i-th measure (1 long measure scores)
|
229
|
+
content_ith_measure = kp.dumps(doc, from_measure=i, to_measure=i)
|
230
|
+
|
231
|
+
# Export the i-th measure and the next 4 measures (5 long measure scores)
|
232
|
+
if i + 4 <= doc.measures_count():
|
233
|
+
content_longer = kp.dumps(doc, from_measure=i, to_measure=i + 4)
|
234
|
+
...
|
235
|
+
```
|
236
|
+
|
237
|
+
It is easier to iterate over all the measures using the `for measure in doc`: loop
|
238
|
+
(using the `__ iter__` method):
|
239
|
+
```python
|
240
|
+
import kernpy as kp
|
241
|
+
|
242
|
+
for measure in doc:
|
243
|
+
content = kp.dumps(doc, from_measure=measure, to_measure=measure)
|
244
|
+
...
|
245
|
+
```
|
246
|
+
|
247
|
+
Exploring the page bounding boxes.
|
248
|
+
|
249
|
+
```python
|
250
|
+
import kernpy as kp
|
251
|
+
|
252
|
+
# Iterate over the pages using the bounding boxes
|
253
|
+
doc, _ = kp.load('kern_having_bounding_boxes.krn')
|
254
|
+
|
255
|
+
# Inspect the bounding boxes
|
256
|
+
print(doc.page_bounding_boxes)
|
257
|
+
|
258
|
+
|
259
|
+
def are_there_bounding_boxes(doc):
|
260
|
+
return len(doc.get_all_tokens(filter_by_categories=[kp.TokenCategory.BOUNDING_BOXES])) > 0
|
261
|
+
|
262
|
+
|
263
|
+
# True
|
264
|
+
|
265
|
+
# Iterate over the pages
|
266
|
+
for page_label, bounding_box_measure in doc.page_bounding_boxes.items():
|
267
|
+
print(f"Page: {page_label}"
|
268
|
+
f"Bounding box: {bounding_box_measure}"
|
269
|
+
f"from_measure: {bounding_box_measure.from_measure}"
|
270
|
+
f"to_measure+1: {bounding_box_measure.to_measure}") # TODO: Check bounds
|
271
|
+
kp.dump(doc, f"foo_{page_label}.ekrn",
|
272
|
+
spine_types=['**kern'],
|
273
|
+
token_categories=kp.BEKERN_CATEGORIES,
|
274
|
+
tokenizer=kp.Encoding.eKern,
|
275
|
+
from_measure=bounding_box_measure.from_measure,
|
276
|
+
to_measure=bounding_box_measure.to_measure - 1 # TODO: Check bounds
|
277
|
+
)
|
278
|
+
```
|
279
|
+
|
280
|
+
### Merge different full kern scores
|
281
|
+
```python
|
282
|
+
import kernpy as kp
|
283
|
+
# NOT AVAILABLE YET!!!
|
284
|
+
# Pay attention to `kp.merge` too.
|
285
|
+
|
286
|
+
# Concat two valid documents
|
287
|
+
score_a = '**kern\n*clefG2\n=1\n4c\n4d\n4e\n4f\n*-\n'
|
288
|
+
score_b = '**kern\n*clefG2\n=1\n4a\n4c\n4d\n4c\n*-\n'
|
289
|
+
concatenated = kp.merge([score_a, score_b])
|
290
|
+
```
|
291
|
+
|
292
|
+
# Concatenate sorted fragments of the same score
|
293
|
+
```python
|
294
|
+
import kernpy as kp
|
295
|
+
|
296
|
+
fragment_a = '**kern\n*clefG2\n=1\n4c\n4d\n4e\n4f\n*-\n'
|
297
|
+
fragment_b = '=2\n4a\n4c\n4d\n4c\n*-\n=3\n4a\n4c\n4d\n4c\n*-\n'
|
298
|
+
fragment_c = '=4\n4a\n4c\n4d\n4c\n*-\n=5\n4a\n4c\n4d\n4c\n*-\n'
|
299
|
+
fragment_d = '=6\n4a\n4c\n4d\n4c\n*-\n=7\n4a\n4c\n4d\n4c\n*-\n==*-'
|
300
|
+
fragments = [fragment_a, fragment_b, fragment_c, fragment_d]
|
301
|
+
|
302
|
+
doc_merged, indexes = kp.concat(fragments)
|
303
|
+
for index_pair in indexes:
|
304
|
+
from_measure, to_measure = index_pair
|
305
|
+
print(f'From measure: {from_measure}, To measure: {to_measure}')
|
306
|
+
print(kp.dumps(doc_merged, from_measure=from_measure, to_measure=to_measure))
|
307
|
+
|
308
|
+
# Sometimes is useful having a different separator between the fragments rather than the default one (newline)...
|
309
|
+
doc_merged, indexes = kp.concat(fragments, separator='')
|
310
|
+
```
|
311
|
+
|
312
|
+
### Inspect the `Document` class functions
|
313
|
+
```python
|
314
|
+
import kernpy as kp
|
315
|
+
doc, _ = kp.load('resource_dir/legacy/chor048.krn') # 10 measures score
|
316
|
+
|
317
|
+
frequencies = doc.frequencies() # All the token categories
|
318
|
+
filtered_frequencies = doc.frequencies(filter_by_categories=[kp.TokenCategory.SIGNATURES])
|
319
|
+
frequencies['*k[f#c#]']
|
320
|
+
# {
|
321
|
+
# 'occurrences': 4,
|
322
|
+
# 'category': SIGNATURES,
|
323
|
+
# }
|
324
|
+
|
325
|
+
# Get all the tokens in the document
|
326
|
+
all_tokens: [kp.Token] = doc.get_all_tokens()
|
327
|
+
all_tokens_encodings: [str] = doc.get_all_tokens_encodings()
|
328
|
+
|
329
|
+
# Get the unique tokens in the document (vocabulary)
|
330
|
+
unique_tokens: [kp.Token] = doc.get_unique_tokens()
|
331
|
+
unique_token_encodings: [str] = doc.get_unique_token_encodings()
|
332
|
+
|
333
|
+
# Get the line comments in the document
|
334
|
+
document.get_metacomments()
|
335
|
+
# ['!!!COM: Coltrane', '!!!voices: 1', '!!!OPR: Blue Train']
|
336
|
+
document.get_metacomments(KeyComment='COM')
|
337
|
+
# ['!!!COM: Coltrane']
|
338
|
+
document.get_metacomments(KeyComment='COM', clear=True)
|
339
|
+
# ['Coltrane']
|
340
|
+
document.get_metacomments(KeyComment='non_existing_key')
|
341
|
+
# []
|
342
|
+
```
|
343
|
+
|
344
|
+
## Transpose
|
345
|
+
- Inspect what intervals are available for transposing.
|
346
|
+
```python
|
347
|
+
import kernpy as kp
|
348
|
+
|
349
|
+
print(kp.AVAILABLE_INTERVALS)
|
350
|
+
```
|
351
|
+
|
352
|
+
- Transpose the document to a specific interval.
|
353
|
+
```python
|
354
|
+
import kernpy as kp
|
355
|
+
|
356
|
+
doc, err = kp.load('resource_dir/legacy/chor048.krn') # 10 measures score
|
357
|
+
higher_octave_doc = doc.to_transposed('octave', 'up')
|
358
|
+
|
359
|
+
kp.dump(higher_octave_doc, 'higher_octave.krn')
|
360
|
+
```
|
361
|
+
|
362
|
+
### On your own
|
363
|
+
|
364
|
+
- Handle the document if needed.
|
365
|
+
```python
|
366
|
+
import kernpy as kp
|
367
|
+
|
368
|
+
# Access the document tree
|
369
|
+
print(document.tree)
|
370
|
+
# <kernpy.core.document.DocumentTree object at 0x7f8b3b3b3d30>
|
371
|
+
|
372
|
+
# View the tree-based Document structure for debugging.
|
373
|
+
kp.graph(document, '/tmp/graph.dot')
|
374
|
+
# Render the graph
|
375
|
+
# - using Graphviz extension in your IDE
|
376
|
+
# - in the browser here: https://dreampuf.github.io/GraphvizOnline/
|
377
|
+
```
|
378
|
+
|
379
|
+
|
380
|
+
## Installation
|
381
|
+
|
382
|
+
### Production version:
|
383
|
+
Just install the last version of **kernpy** using pip:
|
384
|
+
```shell
|
385
|
+
pip3 uninstall kernpy # Uninstall the previous version before installing the new one
|
386
|
+
pip3 install git+https://github.com/OMR-PRAIG-UA-ES/kernpy.git
|
387
|
+
```
|
388
|
+
|
389
|
+
> [!NOTE]
|
390
|
+
> This module is downloaded by default in the _/tmp_ directory in Linux. So it is removed when shutdown the machine.
|
391
|
+
|
392
|
+
<hr>
|
393
|
+
|
394
|
+
### Development version:
|
395
|
+
|
396
|
+
> [!IMPORTANT]
|
397
|
+
> - Add the development dependencies to the `requirements.txt` file.
|
398
|
+
> - Add the production dependencies to the `pyproject.toml` file.
|
399
|
+
> - After every change in the grammar, the next steps are mandatory:
|
400
|
+
> - - Run the `antlr4.sh` script (JAVA required).
|
401
|
+
> - - Commit & push the changes to the repository.
|
402
|
+
|
403
|
+
|
404
|
+
- Generate antrl4 grammar:
|
405
|
+
- For generating the Python code required for parsing the **kern files, the shell script `antlr4.sh` inside the `kernpy` package must be run.
|
406
|
+
|
407
|
+
```shell
|
408
|
+
./antlr4.sh
|
409
|
+
```
|
410
|
+
|
411
|
+
Install all the dependencies using the `requirements.txt` file:
|
412
|
+
```shell
|
413
|
+
pip install -r requirements.txt
|
414
|
+
```
|
415
|
+
|
416
|
+
Otherwise, install the required packages manually:
|
417
|
+
|
418
|
+
|
419
|
+
- It requires the `antlr4` package to be installed using:
|
420
|
+
```shell
|
421
|
+
pip install antlr4-python3-runtime
|
422
|
+
```
|
423
|
+
|
424
|
+
|
425
|
+
- For visualizing the bounding boxes, the library, the `Pillow` library is required:
|
426
|
+
```shell
|
427
|
+
pip install Pillow
|
428
|
+
```
|
429
|
+
|
430
|
+
- To parse a IIIF (International Image Interoperability Framework) manifest in Python, we use the `requests` library to fetch the manifest file:
|
431
|
+
```shell
|
432
|
+
pip install requests
|
433
|
+
```
|
434
|
+
|
435
|
+
- If fetching data from `https` fails, install the following version of `urllib`:
|
436
|
+
```shell
|
437
|
+
pip install urllib3==1.26.6
|
438
|
+
```
|
439
|
+
|
440
|
+
It has been tested with version 4.13.1 of the package.
|
441
|
+
|
442
|
+
|
443
|
+
## Documentation
|
444
|
+
Documentation available at [https://kernpy.pages.dev/](https://kernpy.pages.dev/)
|
445
|
+
|
446
|
+
|
447
|
+
**kernpy** also supports been executed as a module. Find out the available commands:
|
448
|
+
```shell
|
449
|
+
python -m kernpy --help
|
450
|
+
python -m kernpy <command> <options>
|
451
|
+
```
|
452
|
+
|
453
|
+
|
454
|
+
## Run tests:
|
455
|
+
```shell
|
456
|
+
cd tests && python -m pytest
|
457
|
+
```
|
458
|
+
|
459
|
+
|
460
|
+
## Contributing
|
461
|
+
|
462
|
+
We welcome contributions from the community! If you'd like to contribute to the project, please follow these steps:
|
463
|
+
|
464
|
+
1. Fork the Repository from GitHub.
|
465
|
+
2. Clone your own fork repository.
|
466
|
+
```bash
|
467
|
+
git clone ...
|
468
|
+
cd ...
|
469
|
+
```
|
470
|
+
3. Create a Branch:
|
471
|
+
4. Create a new branch for your feature or bug fix:
|
472
|
+
```bash
|
473
|
+
git checkout -b feature/your-feature-name
|
474
|
+
```
|
475
|
+
5. Commit Your Changes:
|
476
|
+
Commit your changes with a descriptive message:
|
477
|
+
```bash
|
478
|
+
git commit -m "feat: add your feature or fix"
|
479
|
+
```
|
480
|
+
|
481
|
+
6. Push to Your Branch:
|
482
|
+
Push your changes to your forked repository:
|
483
|
+
```bash
|
484
|
+
git push origin feature/your-feature-name
|
485
|
+
```
|
486
|
+
|
487
|
+
7. Create a Pull Request:
|
488
|
+
Open a pull request to the main repository, describing your changes.
|
489
|
+
|
490
|
+
|
491
|
+
## Citation:
|
492
|
+
```bibtex
|
493
|
+
@inproceedings{kernpy_mec_2025,
|
494
|
+
title={{kernpy: a Humdrum **Kern Oriented Python Package for Optical Music Recognition Tasks}},
|
495
|
+
author={Cerveto-Serrano, Joan and Rizo, David and Calvo-Zaragoza, Jorge},
|
496
|
+
booktitle={{Proceedings of the Music Encoding Conference (MEC2025)}},
|
497
|
+
address={London, United Kingdom},
|
498
|
+
year={2025}
|
499
|
+
}
|
500
|
+
```
|
501
|
+
|
@@ -0,0 +1,51 @@
|
|
1
|
+
kernpy/__init__.py,sha256=h1o3Z_Xk7nZdE4fBu7uLx6V6nR4M3LySi36ONj73sOo,5998
|
2
|
+
kernpy/__main__.py,sha256=ayuovsnyTaTrhcyOM1kFBoSXGjT1QALwIMcJ_NOqVkM,8495
|
3
|
+
kernpy/test_grammar.sh,sha256=MP9Hav9nPxTbHeofFEuunwDsLcBoeFRtzPp4bbPnqBU,520
|
4
|
+
kernpy/visualize_analysis.sh,sha256=z68jyZ8zj4w7v5CoC8-J7PGh7dYA_iQbuFL5T63X6qY,526
|
5
|
+
kernpy/core/__init__.py,sha256=gIbOKMWcPcQc4c6QpslWnAw9XkcMJ6OvedHANyDABbs,2581
|
6
|
+
kernpy/core/_io.py,sha256=WqH30iDjfzGRCIzlqrAE9Oi_nfyleUpp8xGK8xZPh_w,1208
|
7
|
+
kernpy/core/base_antlr_importer.py,sha256=2pPJ7sdWWCBU9Vw2ZAx-j-674DlSp82ajapeex-pF2I,1475
|
8
|
+
kernpy/core/base_antlr_spine_parser_listener.py,sha256=HqKYACgzdiIc1fAoSaiLzfogkv7pAuiqUHlIRF8c--c,9837
|
9
|
+
kernpy/core/basic_spine_importer.py,sha256=aYceG5wxlm7qTrd0KTR6-P4v4VVlYYPEe8omd3vmC0I,1523
|
10
|
+
kernpy/core/document.py,sha256=Y_Wpwc-t1GkaGr2QVU0hqLRFJv9wJ_Nm6UitgwAlT8w,34892
|
11
|
+
kernpy/core/dyn_importer.py,sha256=dKgZqVIdEELUu8HY63ClLJAMQXXItjHmaYxxOwFZRiY,1025
|
12
|
+
kernpy/core/dynam_spine_importer.py,sha256=crg4LwsWr56VZ6GLYAO1CDnLuum9f1tlX_pXCqKemEc,1450
|
13
|
+
kernpy/core/error_listener.py,sha256=bTlAZvVIQx_6BLZ3oRut_pn24JnV8_7GnNONiwoMMPU,1516
|
14
|
+
kernpy/core/exporter.py,sha256=5MWOk1JmPtpXfjN_VBv5jxUhYu8hhAZwt9eB5u9f1eM,21371
|
15
|
+
kernpy/core/fing_spine_importer.py,sha256=5GLPPakmZVRcNbbaoCn1p1cQdat5QttflbpKu3AytQU,1382
|
16
|
+
kernpy/core/generic.py,sha256=9OTDE2t49laVk6fgtydK5yZh7SCfZwViP_dZUJlskA8,10967
|
17
|
+
kernpy/core/gkern.py,sha256=nRYFLFJ0uOLJwio0DKxQ0YIqLixy6-qCM-eY8DNdxfM,16332
|
18
|
+
kernpy/core/graphviz_exporter.py,sha256=lzeJ0sJoKCDYam1oLJ4pjnlf_NHBJFH0V9w0Pjic5SI,3447
|
19
|
+
kernpy/core/harm_spine_importer.py,sha256=L2eVxW4-tMG3JCtCwLVx6En-ulSn9S90wdUoffj_U5s,1379
|
20
|
+
kernpy/core/import_humdrum_old.py,sha256=NZTQgANQc2BCYJRbGG6AyxcGHxjyy8XXa9dz88zrnMk,35304
|
21
|
+
kernpy/core/importer.py,sha256=Rg4vIvEl2yhMwYrN5NenhdQG4_2dNByCRvHCEBJgWI8,13684
|
22
|
+
kernpy/core/importer_factory.py,sha256=mXYWaAMyd8q1o2hJg5m0gxpBHX-nX6KGPyWl-zjrX7o,1570
|
23
|
+
kernpy/core/kern_spine_importer.py,sha256=9jKDTDDcH81U4Vws4x5msUDq89QzwbdEGYb6uHt-cDI,2581
|
24
|
+
kernpy/core/mens_spine_importer.py,sha256=GGutGL3qeatIkdHZxiOJNcT5mc70acJ728xu-VVLkOU,692
|
25
|
+
kernpy/core/mhxm_spine_importer.py,sha256=45QhuqIgXKkLMFkZYk17sdgOH8dfzK08mWE24fGZ-n4,1410
|
26
|
+
kernpy/core/pitch_models.py,sha256=TpSt1uxGYhbhXs0viB1dNo4jiGxyCOHWseyRHTpfH-0,9730
|
27
|
+
kernpy/core/root_spine_importer.py,sha256=w7oFbMeXakHF9OAlgKWm_HaGJoNq6u7BE_JUnvLiLnU,1893
|
28
|
+
kernpy/core/spine_importer.py,sha256=_VoWcVGfDMhxDn-hCu18g_29Aw2c2bjLnaXuvW2Fbsc,1430
|
29
|
+
kernpy/core/text_spine_importer.py,sha256=mz1qX2nviJs0VsGsN87jk6BVWCIE7mmB9IxEx4RdhT8,1522
|
30
|
+
kernpy/core/tokenizers.py,sha256=dJsaCdPStruzToaYA-RyM9beJ9tQyZRjM4qKLK0d0k4,7899
|
31
|
+
kernpy/core/tokens.py,sha256=0XhbYm6F9NDfYpP5gbrgzZL3qB_xWs74faTwAZghpyM,66515
|
32
|
+
kernpy/core/transposer.py,sha256=EqsEy7Z3bWIXdxUTruBrg8z9sWdJ3Cd_KIzo_6ZuNNA,9352
|
33
|
+
kernpy/core/generated/kernSpineLexer.interp,sha256=Y3_seqmHQu3czO9fHE8XtRwTrk8g4Txf0IKiMaHBqeg,28801
|
34
|
+
kernpy/core/generated/kernSpineLexer.py,sha256=is10dvLvtJw4bA4rHRb_PA4JKTDKCKhAj9ASTNxVuFo,30170
|
35
|
+
kernpy/core/generated/kernSpineLexer.tokens,sha256=ciGB91o4t7VM-tgSLtGB-BUFzHNocVJSUlkjNzK2lcc,2634
|
36
|
+
kernpy/core/generated/kernSpineParser.interp,sha256=mnomJbjTpqMgQdAmYbqBUxk6s7D6OGYh2ya5r6qy8uc,41570
|
37
|
+
kernpy/core/generated/kernSpineParser.py,sha256=j8jnx4gEiTVDJ-juys8YS8-4zHUNfBDuFC3sIBSsK90,338634
|
38
|
+
kernpy/core/generated/kernSpineParser.tokens,sha256=ciGB91o4t7VM-tgSLtGB-BUFzHNocVJSUlkjNzK2lcc,2634
|
39
|
+
kernpy/core/generated/kernSpineParserListener.py,sha256=fcOPxYkGbNbIw8Qk9aqYXnuTB48WWJCn_ZYxTdoFtpY,40015
|
40
|
+
kernpy/core/generated/kernSpineParserVisitor.py,sha256=YSEdcb4kuIi-E4rAFhDKsCVu0lyPdlqrCMtQAeVDhZY,23821
|
41
|
+
kernpy/io/__init__.py,sha256=9103cE_Ao1tu2mi4EaFni-YmnCnwtJqQqFqgeFuT7rA,147
|
42
|
+
kernpy/io/public.py,sha256=p5f22Vse54vU3QYDBn5Z5iJXhRLrF9OTG1MYD8QhdGc,13782
|
43
|
+
kernpy/polish_scores/__init__.py,sha256=EjILt5N5T9cKKdhWwflS_MU4TXuLhdHOYhW8txaicrI,217
|
44
|
+
kernpy/polish_scores/download_polish_dataset.py,sha256=VqACpxDiM1yQYDs4QHHlZ87ZW2gkjl6R_bxYh5E67K4,14633
|
45
|
+
kernpy/polish_scores/iiif.py,sha256=yITdrQbMsGmm8qag8TSousjCjS2io148Jk9xwEKa3B4,1526
|
46
|
+
kernpy/util/__init__.py,sha256=dfW3nRSMkGQS7p7YebM271_0H8_pVw4IiDKeINs_LI8,152
|
47
|
+
kernpy/util/helpers.py,sha256=Xbj3nWNyErdOpLHYd4uVyfwleXvmC5_FlYEhxaeTtS8,1549
|
48
|
+
kernpy/util/store_cache.py,sha256=AA7SFCGQ6ryy-c02wbLy8gIQ2C-VdM1JSWFoWIK_KLA,1186
|
49
|
+
kernpy-1.0.0.dist-info/METADATA,sha256=D2maG9kcRvqxzIO02G6gjx4IecAZtUlfZDoT58rQJOo,14888
|
50
|
+
kernpy-1.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
51
|
+
kernpy-1.0.0.dist-info/RECORD,,
|
kernpy/example.py
DELETED
File without changes
|
kernpy-0.0.1.dist-info/LICENSE
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
Copyright (c) 2018 The Python Packaging Authority
|
2
|
-
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
-
of this software and associated documentation files (the "Software"), to deal
|
5
|
-
in the Software without restriction, including without limitation the rights
|
6
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
-
copies of the Software, and to permit persons to whom the Software is
|
8
|
-
furnished to do so, subject to the following conditions:
|
9
|
-
|
10
|
-
The above copyright notice and this permission notice shall be included in all
|
11
|
-
copies or substantial portions of the Software.
|
12
|
-
|
13
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
-
SOFTWARE.
|
kernpy-0.0.1.dist-info/METADATA
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.2
|
2
|
-
Name: kernpy
|
3
|
-
Version: 0.0.1
|
4
|
-
Summary: A small example package
|
5
|
-
Author-email: Example Author <author@example.com>
|
6
|
-
License: MIT
|
7
|
-
Project-URL: Homepage, https://github.com/pypa/sampleproject
|
8
|
-
Project-URL: Issues, https://github.com/pypa/sampleproject/issues
|
9
|
-
Classifier: Programming Language :: Python :: 3
|
10
|
-
Classifier: Operating System :: OS Independent
|
11
|
-
Requires-Python: >=3.8
|
12
|
-
Description-Content-Type: text/markdown
|
13
|
-
License-File: LICENSE
|
14
|
-
|
15
|
-
# Example Package
|
16
|
-
|
17
|
-
This is a simple example package. You can use
|
18
|
-
[GitHub-flavored Markdown](https://guides.github.com/features/mastering-markdown/)
|
19
|
-
to write your content.
|
kernpy-0.0.1.dist-info/RECORD
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
kernpy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
kernpy/example.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
-
kernpy-0.0.1.dist-info/LICENSE,sha256=2bm9uFabQZ3Ykb_SaSU_uUbAj2-htc6WJQmS_65qD00,1073
|
4
|
-
kernpy-0.0.1.dist-info/METADATA,sha256=Bys8k-Q55dtmy3LkQgue_6khrYe411cPUNNENw7ZAL0,625
|
5
|
-
kernpy-0.0.1.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
|
6
|
-
kernpy-0.0.1.dist-info/top_level.txt,sha256=mioh6PCXgxwhchgmJSffHmPGltPeMR0vava0faosCxA,7
|
7
|
-
kernpy-0.0.1.dist-info/RECORD,,
|
@@ -1 +0,0 @@
|
|
1
|
-
kernpy
|