kernpy 0.0.2__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.2.dist-info → kernpy-1.0.0.dist-info}/WHEEL +1 -2
- kernpy/example.py +0 -1
- kernpy-0.0.2.dist-info/LICENSE +0 -19
- kernpy-0.0.2.dist-info/METADATA +0 -19
- kernpy-0.0.2.dist-info/RECORD +0 -7
- kernpy-0.0.2.dist-info/top_level.txt +0 -1
@@ -0,0 +1,196 @@
|
|
1
|
+
from .generated.kernSpineParserListener import kernSpineParserListener
|
2
|
+
from .generated.kernSpineParser import kernSpineParser
|
3
|
+
from .tokens import BarToken, SimpleToken, TokenCategory, Subtoken, ChordToken, BoundingBox, \
|
4
|
+
BoundingBoxToken, ClefToken, KeySignatureToken, TimeSignatureToken, MeterSymbolToken, BarToken, NoteRestToken, \
|
5
|
+
KeyToken, InstrumentToken
|
6
|
+
|
7
|
+
from typing import List
|
8
|
+
|
9
|
+
|
10
|
+
class BaseANTLRSpineParserListener(kernSpineParserListener):
|
11
|
+
def __init__(self):
|
12
|
+
self.token = None
|
13
|
+
|
14
|
+
self.first_chord_element = None
|
15
|
+
self.chord_tokens = None
|
16
|
+
self.duration_subtokens = []
|
17
|
+
self.diatonic_pitch_and_octave_subtoken = None
|
18
|
+
self.accidental_subtoken = None
|
19
|
+
# self.decorations = {} # in order to standardize the order of decorators, we map the different properties to their class names
|
20
|
+
# We cannot order it using the class name because there are rules with subrules, such as ties, or articulations. We order it using the encoding itself
|
21
|
+
self.decorations: List[Subtoken] = []
|
22
|
+
self.in_chord = False
|
23
|
+
# self.page_start_rows = [] # TODO
|
24
|
+
self.measure_start_rows = []
|
25
|
+
self.last_bounding_box = None
|
26
|
+
|
27
|
+
def enterStart(self, ctx: kernSpineParser.StartContext):
|
28
|
+
self.token = None
|
29
|
+
self.duration_subtokens = []
|
30
|
+
self.diatonic_pitch_and_octave_subtoken = None
|
31
|
+
self.accidental_subtoken = None
|
32
|
+
# self.decorations = {}
|
33
|
+
self.decorations = []
|
34
|
+
|
35
|
+
# def process_decorations(self, ctx: ParserRuleContext):
|
36
|
+
# # in order to standardize the order of note decorators, we map the different properties to their class names
|
37
|
+
# decorations = {}
|
38
|
+
#
|
39
|
+
# for child in ctx.getChildren():
|
40
|
+
# # all decorations have just a child
|
41
|
+
# if child.getChildCount() != 1:
|
42
|
+
# raise Exception('Only 1 decoration child expected, and found ' + child.getChildCount() + ', check '
|
43
|
+
# 'the '
|
44
|
+
# 'grammar')
|
45
|
+
# clazz = type(child.getChild(0))
|
46
|
+
# decoration_type = clazz.__name__
|
47
|
+
# if decoration_type in decorations:
|
48
|
+
# logging.warning(
|
49
|
+
# f'The decoration {decoration_type} is duplicated') # TODO Dar información de línea, columna - ¿lanzamos excepción? - hay algunas que sí pueden estar duplicadas? Barrados?
|
50
|
+
# decorations[decoration_type] = child.getText()
|
51
|
+
# for key in sorted(decorations.keys()):
|
52
|
+
# subtoken = Subtoken(decorations[key], TokenCategory.DECORATION)
|
53
|
+
# self.duration_subtoken.append(subtoken)
|
54
|
+
|
55
|
+
def exitDuration(self, ctx: kernSpineParser.DurationContext):
|
56
|
+
self.duration_subtokens = [Subtoken(ctx.modernDuration().getText(), TokenCategory.DURATION)]
|
57
|
+
for i in range(len(ctx.augmentationDot())):
|
58
|
+
self.duration_subtokens.append(Subtoken(".", TokenCategory.DURATION))
|
59
|
+
|
60
|
+
if ctx.graceNote():
|
61
|
+
self.duration_subtokens.append(Subtoken(ctx.graceNote().getText(), TokenCategory.DURATION))
|
62
|
+
|
63
|
+
if ctx.appoggiatura():
|
64
|
+
self.duration_subtokens.append(Subtoken(ctx.appoggiatura().getText(), TokenCategory.DURATION))
|
65
|
+
|
66
|
+
def exitDiatonicPitchAndOctave(self, ctx: kernSpineParser.DiatonicPitchAndOctaveContext):
|
67
|
+
self.diatonic_pitch_and_octave_subtoken = Subtoken(ctx.getText(), TokenCategory.PITCH)
|
68
|
+
|
69
|
+
def exitNoteDecoration(self, ctx: kernSpineParser.NoteDecorationContext):
|
70
|
+
# clazz = type(ctx.getChild(0))
|
71
|
+
# decoration_type = clazz.__name__
|
72
|
+
# if decoration_type in self.decorations:
|
73
|
+
# logging.warning(
|
74
|
+
# f'The decoration {decoration_type} is duplicated after reading {ctx.getText()}') # TODO Dar información de línea, columna - ¿lanzamos excepción? - hay algunas que sí pueden estar duplicadas? Barrados?
|
75
|
+
|
76
|
+
# self.decorations[decoration_type] = ctx.getText()
|
77
|
+
# We cannot order it using the class name because there are rules with subrules, such as ties, or articulations. We order it using the encoding itself. NOT YET!
|
78
|
+
decoration_encoding = ctx.getText()
|
79
|
+
decoration_subtoken = Subtoken(decoration_encoding, TokenCategory.DECORATION)
|
80
|
+
self.decorations.append(decoration_subtoken)
|
81
|
+
|
82
|
+
def exitRestDecoration(self, ctx: kernSpineParser.NoteDecorationContext):
|
83
|
+
# clazz = type(ctx.getChild(0))
|
84
|
+
# decoration_type = clazz.__name__
|
85
|
+
# if decoration_type in self.decorations:
|
86
|
+
# logging.warning(
|
87
|
+
# f'The decoration {decoration_type} is duplicated after reading {ctx.getText()}') # TODO Dar información de línea, columna - ¿lanzamos excepción? - hay algunas que sí pueden estar duplicadas? Barrados?
|
88
|
+
|
89
|
+
# self.decorations[decoration_type] = ctx.getText()
|
90
|
+
# We cannot order it using the class name because there are rules with subrules, such as ties, or articulations. We order it using the encoding itself
|
91
|
+
decoration = ctx.getText();
|
92
|
+
if decoration != '/' and decoration != '\\':
|
93
|
+
decoration_encoding = ctx.getText()
|
94
|
+
decoration_subtoken = Subtoken(decoration_encoding, TokenCategory.DECORATION)
|
95
|
+
self.decorations.append(decoration_subtoken)
|
96
|
+
|
97
|
+
def addNoteRest(self, ctx, pitchduration_subtokens):
|
98
|
+
# subtoken = Subtoken(self.decorations[key], TokenCategory.DECORATION)
|
99
|
+
token = NoteRestToken(ctx.getText(), pitchduration_subtokens, self.decorations)
|
100
|
+
if self.in_chord:
|
101
|
+
self.chord_tokens.append(token)
|
102
|
+
else:
|
103
|
+
self.token = token
|
104
|
+
|
105
|
+
def exitNote(self, ctx: kernSpineParser.NoteContext):
|
106
|
+
pitch_duration_tokens = []
|
107
|
+
for duration_subtoken in self.duration_subtokens:
|
108
|
+
pitch_duration_tokens.append(duration_subtoken)
|
109
|
+
pitch_duration_tokens.append(self.diatonic_pitch_and_octave_subtoken)
|
110
|
+
if ctx.alteration():
|
111
|
+
pitch_duration_tokens.append(Subtoken(ctx.alteration().getText(), TokenCategory.ALTERATION))
|
112
|
+
|
113
|
+
self.addNoteRest(ctx, pitch_duration_tokens)
|
114
|
+
|
115
|
+
def exitRest(self, ctx: kernSpineParser.RestContext):
|
116
|
+
pitch_duration_tokens = []
|
117
|
+
for duration_subtoken in self.duration_subtokens:
|
118
|
+
pitch_duration_tokens.append(duration_subtoken)
|
119
|
+
pitch_duration_tokens.append(Subtoken('r', TokenCategory.PITCH))
|
120
|
+
self.addNoteRest(ctx, pitch_duration_tokens)
|
121
|
+
|
122
|
+
def enterChord(self, ctx: kernSpineParser.ChordContext):
|
123
|
+
self.in_chord = True
|
124
|
+
self.chord_tokens = []
|
125
|
+
|
126
|
+
def exitChord(self, ctx: kernSpineParser.ChordContext):
|
127
|
+
self.in_chord = False
|
128
|
+
self.token = ChordToken(ctx.getText(), TokenCategory.CHORD, self.chord_tokens)
|
129
|
+
|
130
|
+
def exitEmpty(self, ctx: kernSpineParser.EmptyContext):
|
131
|
+
self.token = SimpleToken(ctx.getText(), TokenCategory.EMPTY)
|
132
|
+
|
133
|
+
def exitNonVisualTandemInterpretation(self, ctx: kernSpineParser.NonVisualTandemInterpretationContext):
|
134
|
+
self.token = SimpleToken(ctx.getText(), TokenCategory.OTHER)
|
135
|
+
|
136
|
+
def exitVisualTandemInterpretation(self, ctx: kernSpineParser.VisualTandemInterpretationContext):
|
137
|
+
self.token = SimpleToken(ctx.getText(), TokenCategory.ENGRAVED_SYMBOLS)
|
138
|
+
|
139
|
+
def exitOtherContextual(self, ctx: kernSpineParser.ContextualContext):
|
140
|
+
self.token = SimpleToken(ctx.getText(), TokenCategory.OTHER_CONTEXTUAL)
|
141
|
+
|
142
|
+
def exitClef(self, ctx: kernSpineParser.ClefContext):
|
143
|
+
self.token = ClefToken(ctx.getText())
|
144
|
+
|
145
|
+
def exitKeySignature(self, ctx: kernSpineParser.KeySignatureContext):
|
146
|
+
self.token = KeySignatureToken(ctx.getText())
|
147
|
+
|
148
|
+
def exitKeyCancel(self, ctx: kernSpineParser.KeyCancelContext):
|
149
|
+
self.token = KeySignatureToken(ctx.getText())
|
150
|
+
|
151
|
+
def exitKey(self, ctx: kernSpineParser.KeyContext):
|
152
|
+
self.token = KeyToken(ctx.getText())
|
153
|
+
|
154
|
+
def exitTimeSignature(self, ctx: kernSpineParser.TimeSignatureContext):
|
155
|
+
self.token = TimeSignatureToken(ctx.getText())
|
156
|
+
|
157
|
+
def exitMeterSymbol(self, ctx: kernSpineParser.MeterSymbolContext):
|
158
|
+
self.token = MeterSymbolToken(ctx.getText())
|
159
|
+
|
160
|
+
def exitStructural(self, ctx: kernSpineParser.StructuralContext):
|
161
|
+
self.token = SimpleToken(ctx.getText(), TokenCategory.STRUCTURAL)
|
162
|
+
|
163
|
+
def exitXywh(self, ctx: kernSpineParser.XywhContext):
|
164
|
+
self.last_bounding_box = BoundingBox(int(ctx.x().getText()), int(ctx.y().getText()), int(ctx.w().getText()),
|
165
|
+
int(ctx.h().getText()))
|
166
|
+
|
167
|
+
def exitBoundingBox(self, ctx: kernSpineParser.BoundingBoxContext):
|
168
|
+
page = ctx.pageNumber().getText()
|
169
|
+
bbox = BoundingBox(int(ctx.xywh().x().getText()), int(ctx.xywh().y().getText()), int(ctx.xywh().w().getText()),
|
170
|
+
int(ctx.xywh().h().getText()))
|
171
|
+
self.token = BoundingBoxToken(ctx.getText(), page, bbox)
|
172
|
+
|
173
|
+
def exitInstrument(self, ctx: kernSpineParser.InstrumentContext):
|
174
|
+
self.token = InstrumentToken(ctx.getText())
|
175
|
+
|
176
|
+
|
177
|
+
def exitBarline(self, ctx: kernSpineParser.BarlineContext):
|
178
|
+
txt_without_number = ''
|
179
|
+
if ctx.EQUAL(0) and ctx.EQUAL(1):
|
180
|
+
txt_without_number = '=='
|
181
|
+
elif ctx.EQUAL(0):
|
182
|
+
txt_without_number = '='
|
183
|
+
if ctx.barLineType():
|
184
|
+
txt_without_number += ctx.barLineType().getText()
|
185
|
+
if ctx.fermata():
|
186
|
+
txt_without_number += ctx.fermata().getText()
|
187
|
+
|
188
|
+
# correct wrong encodings
|
189
|
+
if txt_without_number == ':!:':
|
190
|
+
txt_without_number = ':|!|:'
|
191
|
+
elif txt_without_number == ':|!|:':
|
192
|
+
txt_without_number = ':|!|:'
|
193
|
+
|
194
|
+
self.token = BarToken(txt_without_number)
|
195
|
+
self.token.hidden = "-" in ctx.getText() # hidden
|
196
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import Optional
|
3
|
+
|
4
|
+
from .base_antlr_spine_parser_listener import BaseANTLRSpineParserListener
|
5
|
+
from .spine_importer import SpineImporter
|
6
|
+
from .spine_importer import SpineImporter
|
7
|
+
from .kern_spine_importer import KernSpineImporter, KernSpineListener
|
8
|
+
from .tokens import SimpleToken, TokenCategory, Token
|
9
|
+
|
10
|
+
|
11
|
+
class BasicSpineImporter(SpineImporter):
|
12
|
+
def __init__(self, verbose: Optional[bool] = False):
|
13
|
+
"""
|
14
|
+
KernSpineImporter constructor.
|
15
|
+
|
16
|
+
Args:
|
17
|
+
verbose (Optional[bool]): Level of verbosity for error messages.
|
18
|
+
"""
|
19
|
+
super().__init__(verbose=verbose)
|
20
|
+
|
21
|
+
def import_listener(self) -> BaseANTLRSpineParserListener:
|
22
|
+
return KernSpineListener() # TODO: Create a custom functional listener for BasicSpineImporter
|
23
|
+
|
24
|
+
def import_token(self, encoding: str) -> Token:
|
25
|
+
self._raise_error_if_wrong_input(encoding)
|
26
|
+
|
27
|
+
kern_spine_importer = KernSpineImporter()
|
28
|
+
token = kern_spine_importer.import_token(encoding)
|
29
|
+
|
30
|
+
ACCEPTED_CATEGORIES = {
|
31
|
+
TokenCategory.STRUCTURAL,
|
32
|
+
TokenCategory.SIGNATURES,
|
33
|
+
TokenCategory.EMPTY,
|
34
|
+
TokenCategory.BARLINES,
|
35
|
+
TokenCategory.IMAGE_ANNOTATIONS,
|
36
|
+
TokenCategory.BARLINES,
|
37
|
+
TokenCategory.COMMENTS,
|
38
|
+
}
|
39
|
+
|
40
|
+
if not any(TokenCategory.is_child(child=token.category, parent=cat) for cat in ACCEPTED_CATEGORIES):
|
41
|
+
return SimpleToken(encoding, TokenCategory.OTHER)
|
42
|
+
|
43
|
+
return token
|