kernpy 1.0.0__py3-none-any.whl → 1.0.1__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
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
=====
|
5
5
|
|
6
6
|
|
7
|
-
Python Humdrum kern and mens utilities package.
|
7
|
+
Python Humdrum **kern and **mens utilities package.
|
8
8
|
|
9
9
|
|
10
10
|
|
@@ -13,191 +13,6 @@ Execute the following command to run **kernpy** as a module:
|
|
13
13
|
python -m kernpy --help
|
14
14
|
python -m kernpy <command> <options>
|
15
15
|
```
|
16
|
-
|
17
|
-
Run `kernpy` from your script:
|
18
|
-
```python
|
19
|
-
import kernpy
|
20
|
-
|
21
|
-
help(kernpy)
|
22
|
-
```
|
23
|
-
|
24
|
-
While the package is not published in `pip`, the `kernpy` module must be in the root directory.
|
25
|
-
|
26
|
-
## 🎯 **kern2ekern**: Convertir un solo archivo .krn a .ekern:
|
27
|
-
|
28
|
-
```bash
|
29
|
-
python -m kernpy --kern2ekern --input_path <input_file> <v | --verbose [0-2]>
|
30
|
-
```
|
31
|
-
|
32
|
-
The command has the following arguments:
|
33
|
-
* **input_path**: Ruta del archivo .krn a convertir.
|
34
|
-
* **output_path**: Ruta del archivo .ekern a generar (opcional). Si no se especifica, se generará en la misma ubicación.
|
35
|
-
* **-r**: Recursivo (opcional).
|
36
|
-
* **--verbose[0-2]**: Nivel de verbosidad (opcional).
|
37
|
-
|
38
|
-
|
39
|
-
📌 Basic usage running **kernpy** as a module:
|
40
|
-
```shell
|
41
|
-
python -m kernpy --input_path /my/path/to/file.krn # New ekern generated in /my/path/to/file.ekern
|
42
|
-
```
|
43
|
-
|
44
|
-
📌 Generate an _ekrn_ file in specific location running **kernpy** as a module:
|
45
|
-
```shell
|
46
|
-
python -m kernpy --input_path /my/path/to/file.krn --output_path /new/output.ekern
|
47
|
-
```
|
48
|
-
|
49
|
-
📌 Converting all the .krn files in a directory to .ekern files running **kernpy** as a module:
|
50
|
-
* Every .krn file in the directory will be converted to .ekern in the same location.
|
51
|
-
* Using, at least, one additional directory level is required.
|
52
|
-
```
|
53
|
-
root
|
54
|
-
├─ kern-folder
|
55
|
-
│ ├── 1.krn
|
56
|
-
│ ├── 2.krn
|
57
|
-
│ └── 3.krn
|
58
|
-
├── more-kerns
|
59
|
-
│ ├── 1.krn
|
60
|
-
│ ├── ...
|
61
|
-
```
|
62
|
-
Run:
|
63
|
-
```shell
|
64
|
-
python -m kernpy --input_path /my/path/to/directory/ -r
|
65
|
-
```
|
66
|
-
|
67
|
-
✏️ This function is also available as a python function:
|
68
|
-
```python
|
69
|
-
# converter.py
|
70
|
-
from kernpy import kern_to_ekern
|
71
|
-
|
72
|
-
kern_to_ekern('/my/path/to/input.krn', '/to/my/output.ekrn')
|
73
|
-
|
74
|
-
# Many files
|
75
|
-
files = ['file1.krn', 'file2.krn', 'file3.krn']
|
76
|
-
[kern_to_ekern(f) for f in files]
|
77
|
-
|
78
|
-
# This function raises an exception if the conversion fails.
|
79
|
-
# Handle the errors using try-except statement if many files are going to be converted in series.
|
80
|
-
```
|
81
|
-
|
82
|
-
****************************************************************************************
|
83
|
-
## 🎯 **ekern2kern**: Convertir un solo archivo .ekern a .krn:
|
84
|
-
|
85
|
-
```bash
|
86
|
-
python -m kernpy --ekern2kern --input_path <input_file> <--verbose [0-2]>
|
87
|
-
```
|
88
|
-
|
89
|
-
The command has the following arguments:
|
90
|
-
* **input_path**: Ruta del archivo .ekern a convertir.
|
91
|
-
* **output_path**: Ruta del archivo .krn a generar (opcional). Si no se especifica, se generará en la misma ubicación.
|
92
|
-
* **-r**: Recursivo (opcional).
|
93
|
-
* **--verbose[0-2]**: Nivel de verbosidad (opcional).
|
94
|
-
|
95
|
-
* Basic usage running **kernpy** as a module:
|
96
|
-
```shell
|
97
|
-
python -m kernpy --input_path /my/path/to/file.ekern # New krn generated in /my/path/to/file.krn
|
98
|
-
```
|
99
|
-
|
100
|
-
📌 Generate a _krn_ file in specific location running **kernpy** as a module:
|
101
|
-
```shell
|
102
|
-
python -m kernpy --input_path /my/path/to/file.ekern --output_path /new/output.krn
|
103
|
-
```
|
104
|
-
|
105
|
-
📌 Converting **all** the .ekern files in a directory to .krn files running **kernpy** as a module:
|
106
|
-
|
107
|
-
* Every .ekrn file in the directory will be converted to .krn in the same location.
|
108
|
-
* Using, at least, one additional directory level is required.
|
109
|
-
```
|
110
|
-
root
|
111
|
-
├─ ekern-folder
|
112
|
-
│ ├── 1.ekrn
|
113
|
-
│ ├── 2.ekrn
|
114
|
-
│ └── 3.ekrn
|
115
|
-
├── more-ekerns
|
116
|
-
│ ├── 1.ekrn
|
117
|
-
│ ├── ...
|
118
|
-
```
|
119
|
-
Run:
|
120
|
-
```shell
|
121
|
-
python -m kernpy --input_path /my/path/to/directory/ -r
|
122
|
-
```
|
123
|
-
|
124
|
-
✏️ This function is also available as a python function:
|
125
|
-
```python
|
126
|
-
# converter.py
|
127
|
-
from kernpy import ekern_to_krn
|
128
|
-
|
129
|
-
# Only one file
|
130
|
-
ekern_to_krn('/my/path/to/input.ekrn', '/to/my/output.krn')
|
131
|
-
|
132
|
-
# Many files
|
133
|
-
files = ['file1.ekrn', 'file2.ekrn', 'file3.ekrn']
|
134
|
-
[ekern_to_krn(f) for f in files]
|
135
|
-
|
136
|
-
# This function raises an exception if the conversion fails.
|
137
|
-
# Handle the errors using try-except statement if many files are going to be converted in series.
|
138
|
-
```
|
139
|
-
|
140
|
-
|
141
|
-
****************************************************************************************
|
142
|
-
## 🎯 **create fragments**
|
143
|
-
Generate new valid _kern_ files from an original _kern_ file. Every new fragment will be a subset of the original file.
|
144
|
-
|
145
|
-
Explore the documentation website for more information about the parameters.
|
146
|
-
|
147
|
-
|
148
|
-
Use:
|
149
|
-
- **create_fragments_from_kern** to generate using always the same measure length.
|
150
|
-
- **create_fragments_from_directory** to generate using a Gaussian distribution for the measure length. Static measure is also available if the standard deviation is set to 0.
|
151
|
-
|
152
|
-
|
153
|
-
📌 Create new scores from one original _kern_ directory running **kernpy** as a module:
|
154
|
-
```shell
|
155
|
-
python -m kernpy --generate_fragments --input_directory /from/my/kerns --output_directory /to/my/fragments --log_file log.csv --verbose 2 --mean 4.2 --std_dev 1.5 --offset 1 --num_processes 12
|
156
|
-
```
|
157
|
-
|
158
|
-
|
159
|
-
✏️ Create new scores from one original _kern_ file:
|
160
|
-
```python
|
161
|
-
# generator.py
|
162
|
-
from kernpy import create_fragments_from_kern
|
163
|
-
|
164
|
-
# View docs:
|
165
|
-
help(create_fragments_from_kern)
|
166
|
-
|
167
|
-
create_fragments_from_kern('/my/path/to/input.krn', '/to/my/output_dir/',
|
168
|
-
measure_length=4, offset=1,
|
169
|
-
log_file='/dev/null')
|
170
|
-
```
|
171
|
-
|
172
|
-
✏️ Create new scores from one original _kern_ directory:
|
173
|
-
- Using, at least, one additional directory level is required.
|
174
|
-
```
|
175
|
-
root
|
176
|
-
├─ kern-folder
|
177
|
-
│ ├── 1.krn
|
178
|
-
│ ├── 2.krn
|
179
|
-
│ └── 3.krn
|
180
|
-
├── more-kerns
|
181
|
-
│ ├── 1.krn
|
182
|
-
│ ├── ...
|
183
|
-
```
|
184
|
-
|
185
|
-
Run:
|
186
|
-
```python
|
187
|
-
# generator.py
|
188
|
-
from kernpy import create_fragments_from_directory
|
189
|
-
|
190
|
-
# View docs:
|
191
|
-
help(create_fragments_from_directory)
|
192
|
-
|
193
|
-
create_fragments_from_directory('/my/path/to/input_dir/', '/to/my/output_dir/',
|
194
|
-
mean=4.1, std_dev=0.2, offset=2,
|
195
|
-
log_file='/logs/fragments.csv',
|
196
|
-
num_processes=12)
|
197
|
-
```
|
198
|
-
|
199
|
-
|
200
|
-
|
201
16
|
"""
|
202
17
|
|
203
18
|
|
kernpy/__main__.py
CHANGED
@@ -1,217 +1,127 @@
|
|
1
1
|
"""
|
2
2
|
This module contains the main function for the kernpy package.
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
python -m kernpy
|
7
|
-
```
|
8
|
-
|
4
|
+
Usage:
|
5
|
+
python -m kernpy
|
9
6
|
"""
|
10
7
|
|
11
8
|
import argparse
|
12
9
|
import sys
|
13
|
-
import
|
10
|
+
from pathlib import Path
|
14
11
|
|
15
|
-
from kernpy import polish_scores, ekern_to_krn, kern_to_ekern
|
12
|
+
from kernpy import polish_scores, ekern_to_krn, kern_to_ekern
|
16
13
|
|
17
14
|
|
18
15
|
def create_parser() -> argparse.ArgumentParser:
|
19
|
-
""
|
20
|
-
Create a parser for the command line arguments.
|
21
|
-
|
22
|
-
Examples:
|
23
|
-
>>> parser = create_parser()
|
24
|
-
>>> args = parser.parse_args()
|
25
|
-
>>> print(args.verbose)
|
26
|
-
|
27
|
-
|
28
|
-
Returns:
|
29
|
-
argparse.ArgumentParser: The parser object
|
30
|
-
"""
|
31
|
-
parser = argparse.ArgumentParser(description="kernpy")
|
32
|
-
|
33
|
-
parser.add_argument('--verbose', default=1, help='Enable verbose mode')
|
34
|
-
|
35
|
-
|
36
|
-
# ekern to kern
|
37
|
-
kern_parser = parser.add_argument_group('Kern Parser options')
|
38
|
-
kern_parser.add_argument('--ekern2kern', action='store_true', help='Convert file from ekern to kern. [-r]')
|
39
|
-
kern_parser.add_argument('--kern2ekern', action='store_true', help='Convert file from kern to ekern. [-r]')
|
40
|
-
|
41
|
-
if '--ekern2kern' in sys.argv:
|
42
|
-
kern_parser.add_argument('--input_path', required=True, type=str,
|
43
|
-
help='Input file or directory path. Employ -r to use recursive mode')
|
44
|
-
kern_parser.add_argument('--output_path', required=False, type=str, help='Output file or directory path')
|
45
|
-
kern_parser.add_argument('-r', '--recursive', required=False, action='store_true', help='Recursive mode')
|
46
|
-
|
47
|
-
if '--kern2ekern' in sys.argv:
|
48
|
-
kern_parser.add_argument('--input_path', required=True, type=str,
|
49
|
-
help='Input file or directory path. Employ -r to use recursive mode')
|
50
|
-
kern_parser.add_argument('--output_path', required=False, type=str, help='Output file or directory path')
|
51
|
-
kern_parser.add_argument('-r', '--recursive', required=False, action='store_true', help='Recursive mode')
|
52
|
-
|
53
|
-
# Polish operations
|
54
|
-
# Create a group for optional arguments
|
55
|
-
polish_args = parser.add_argument_group('Polish Exporter options')
|
56
|
-
polish_args.add_argument('--polish', action='store_true', help='Enable Polish Exporter')
|
57
|
-
# Add the required flags, but only if --polish exists
|
58
|
-
if '--polish' in sys.argv:
|
59
|
-
polish_args.add_argument('--input_directory', required=True, type=str, help='Input directory path')
|
60
|
-
polish_args.add_argument('--output_directory', required=True, type=str, help='Output directory path')
|
61
|
-
polish_args.add_argument('--instrument', required=False, type=str, help='Instrument name')
|
62
|
-
polish_args.add_argument('--kern_type', required=False, type=str, help='Kern type: "krn" or "ekrn"')
|
63
|
-
polish_args.add_argument('--kern_spines_filter', required=False, type=str, help='How many kern spines scores will be exported. A number greater than 0', default=None)
|
64
|
-
polish_args.add_argument('--remove_empty_dirs', required=False, action='store_true', help='Remove empty directories after exporting the scores', default=True)
|
65
|
-
|
66
|
-
# Generate fragments
|
67
|
-
# Create a group for optional arguments
|
68
|
-
generate_fragments = parser.add_argument_group('Generate Fragments options')
|
69
|
-
generate_fragments.add_argument('--generate_fragments', action='store_true', help='Enable Generate Fragments')
|
70
|
-
if '--generate_fragments' in sys.argv:
|
71
|
-
generate_fragments.add_argument('--input_directory', required=True, type=str, help='Input directory path')
|
72
|
-
generate_fragments.add_argument('--output_directory', required=True, type=str, help='Output directory path')
|
73
|
-
generate_fragments.add_argument('--log_file', required=True, type=str, help='Log file path')
|
74
|
-
generate_fragments.add_argument('--check_file_extension', required=False, action='store_true', help='Check file extension', default=True)
|
75
|
-
generate_fragments.add_argument('--offset', required=True, type=int, help='Offset', default=1)
|
76
|
-
generate_fragments.add_argument('--num_processes', required=True, type=int, help='Number of processes')
|
77
|
-
generate_fragments.add_argument('--mean', required=True, type=float, help='Mean')
|
78
|
-
generate_fragments.add_argument('--std_dev', required=True, type=float, help='Standard deviation')
|
16
|
+
parser = argparse.ArgumentParser(description="kernpy CLI tool")
|
79
17
|
|
80
|
-
|
18
|
+
parser.add_argument('--verbose', type=int, default=1, help='Verbosity level')
|
81
19
|
|
20
|
+
group = parser.add_mutually_exclusive_group(required=True)
|
21
|
+
group.add_argument('--ekern2kern', action='store_true', help='Convert files from ekern to kern')
|
22
|
+
group.add_argument('--kern2ekern', action='store_true', help='Convert files from kern to ekern')
|
23
|
+
group.add_argument('--polish', action='store_true', help='Run Polish Exporter')
|
24
|
+
group.add_argument('--generate_fragments', action='store_true', help='Generate Fragments')
|
82
25
|
|
83
|
-
|
84
|
-
|
85
|
-
|
26
|
+
parser.add_argument('--input_path', type=str, help='Input file or directory')
|
27
|
+
parser.add_argument('--output_path', type=str, help='Output file or directory')
|
28
|
+
parser.add_argument('-r', '--recursive', action='store_true', help='Enable recursive directory processing')
|
86
29
|
|
87
|
-
|
88
|
-
|
30
|
+
# Polish Exporter
|
31
|
+
parser.add_argument('--input_directory', type=str, help='Polish: Input directory')
|
32
|
+
parser.add_argument('--output_directory', type=str, help='Polish: Output directory')
|
33
|
+
parser.add_argument('--instrument', type=str, help='Polish: Instrument name')
|
34
|
+
parser.add_argument('--kern_type', type=str, help='Polish: "krn" or "ekrn"')
|
35
|
+
parser.add_argument('--kern_spines_filter', type=str, help='Polish: Filter for number of kern spines')
|
36
|
+
parser.add_argument('--remove_empty_dirs', action='store_true', help='Polish: Remove empty directories')
|
89
37
|
|
90
|
-
Returns:
|
91
|
-
None
|
92
|
-
"""
|
93
|
-
# TODO: Add instrument argument to download_polish_dataset.main
|
94
|
-
if args.instrument:
|
95
|
-
print("Instrument:", args.instrument)
|
96
|
-
else:
|
97
|
-
print("Instrument: Not specified")
|
98
38
|
|
99
|
-
|
100
|
-
input_directory=args.input_directory,
|
101
|
-
output_directory=args.output_directory,
|
102
|
-
kern_spines_filter=args.kern_spines_filter,
|
103
|
-
exporter_kern_type=args.kern_type,
|
104
|
-
remove_empty_directories=args.remove_empty_dirs
|
105
|
-
)
|
39
|
+
return parser
|
106
40
|
|
107
41
|
|
108
|
-
def
|
109
|
-
|
110
|
-
|
42
|
+
def find_files(directory: Path, patterns: list[str], recursive: bool = False) -> list[Path]:
|
43
|
+
files = []
|
44
|
+
for pattern in patterns:
|
45
|
+
if recursive:
|
46
|
+
files.extend(directory.rglob(pattern))
|
47
|
+
else:
|
48
|
+
files.extend(directory.glob(pattern))
|
49
|
+
return files
|
111
50
|
|
112
|
-
Args:
|
113
|
-
args: The parsed arguments
|
114
51
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
if not args.output_path:
|
119
|
-
args.output_path = args.input_path.replace("ekrn", "krn")
|
52
|
+
def handle_ekern2kern(args):
|
53
|
+
input_path = Path(args.input_path)
|
54
|
+
output_path = Path(args.output_path) if args.output_path else None
|
120
55
|
|
121
|
-
if
|
122
|
-
|
123
|
-
|
124
|
-
|
56
|
+
if input_path.is_file():
|
57
|
+
out = output_path or input_path.with_suffix(".krn")
|
58
|
+
ekern_to_krn(str(input_path), str(out))
|
59
|
+
if args.verbose:
|
60
|
+
print(f"Converted: {input_path} → {out}")
|
125
61
|
return
|
126
62
|
|
127
|
-
|
128
|
-
for
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
Args:
|
148
|
-
args: The parsed arguments
|
149
|
-
|
150
|
-
Returns:
|
151
|
-
None
|
152
|
-
"""
|
153
|
-
if not args.output_path:
|
154
|
-
args.output_path = args.input_path.replace("krn", "ekrn")
|
155
|
-
|
156
|
-
if not args.recursive:
|
157
|
-
kern_to_ekern(args.input_path, args.output_path)
|
158
|
-
if int(args.verbose) > 0:
|
159
|
-
print(f"New ekern generated in {args.output_path}")
|
63
|
+
files = find_files(input_path, ["*.ekrn", "*.ekern"], recursive=args.recursive)
|
64
|
+
for file in files:
|
65
|
+
out = file.with_suffix(".krn")
|
66
|
+
try:
|
67
|
+
ekern_to_krn(str(file), str(out))
|
68
|
+
if args.verbose:
|
69
|
+
print(f"Converted: {file} → {out}")
|
70
|
+
except Exception as e:
|
71
|
+
print(f"Error converting {file}: {e}", file=sys.stderr)
|
72
|
+
|
73
|
+
|
74
|
+
def handle_kern2ekern(args):
|
75
|
+
input_path = Path(args.input_path)
|
76
|
+
output_path = Path(args.output_path) if args.output_path else None
|
77
|
+
|
78
|
+
if input_path.is_file():
|
79
|
+
out = output_path or input_path.with_suffix(".ekrn")
|
80
|
+
kern_to_ekern(str(input_path), str(out))
|
81
|
+
if args.verbose:
|
82
|
+
print(f"Converted: {input_path} → {out}")
|
160
83
|
return
|
161
84
|
|
162
|
-
|
163
|
-
for
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
Returns:
|
186
|
-
None
|
187
|
-
"""
|
188
|
-
create_fragments_from_directory(args.input_directory, args.output_directory, args.log_file,
|
189
|
-
check_file_extension=args.check_file_extension, offset=args.offset,
|
190
|
-
verbose=args.verbose, num_processes=args.num_processes, mean=args.mean,
|
191
|
-
std_dev=args.std_dev)
|
85
|
+
files = find_files(input_path, ["*.krn", "*.kern"], recursive=args.recursive)
|
86
|
+
for file in files:
|
87
|
+
out = file.with_suffix(".ekrn")
|
88
|
+
try:
|
89
|
+
kern_to_ekern(str(file), str(out))
|
90
|
+
if args.verbose:
|
91
|
+
print(f"Converted: {file} → {out}")
|
92
|
+
except Exception as e:
|
93
|
+
print(f"Error converting {file}: {e}", file=sys.stderr)
|
94
|
+
|
95
|
+
|
96
|
+
def handle_polish_exporter(args):
|
97
|
+
if args.verbose:
|
98
|
+
print(f"Running Polish Exporter on {args.input_directory} → {args.output_directory}")
|
99
|
+
|
100
|
+
polish_scores.download_polish_dataset.main(
|
101
|
+
input_directory=args.input_directory,
|
102
|
+
output_directory=args.output_directory,
|
103
|
+
kern_spines_filter=args.kern_spines_filter,
|
104
|
+
exporter_kern_type=args.kern_type,
|
105
|
+
remove_empty_directories=args.remove_empty_dirs,
|
106
|
+
)
|
192
107
|
|
193
108
|
|
194
109
|
def main():
|
195
110
|
parser = create_parser()
|
196
111
|
args = parser.parse_args()
|
197
112
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
print(key, value)
|
203
|
-
print(f"{50 * '*'}\n")
|
113
|
+
if args.verbose > 2:
|
114
|
+
print("Arguments:")
|
115
|
+
for key, val in vars(args).items():
|
116
|
+
print(f" {key}: {val}")
|
204
117
|
|
205
|
-
if args.polish:
|
206
|
-
handle_polish_exporter(args)
|
207
118
|
if args.ekern2kern:
|
208
119
|
handle_ekern2kern(args)
|
209
|
-
|
120
|
+
elif args.kern2ekern:
|
210
121
|
handle_kern2ekern(args)
|
211
|
-
|
212
|
-
|
122
|
+
elif args.polish:
|
123
|
+
handle_polish_exporter(args)
|
213
124
|
|
214
125
|
|
215
126
|
if __name__ == "__main__":
|
216
127
|
main()
|
217
|
-
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: kernpy
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.1
|
4
4
|
Summary: Python Humdrum **kern and **mens utilities
|
5
5
|
Project-URL: Homepage, https://github.com/OMR-PRAIG-UA-ES/kernpy
|
6
6
|
Project-URL: Documentation, https://github.com/OMR-PRAIG-UA-ES/kernpy#readme
|
@@ -19,9 +19,18 @@ Description-Content-Type: text/markdown
|
|
19
19
|
|
20
20
|
# Python Humdrum **kern and **mens utilities
|
21
21
|
|
22
|
-
|
22
|
+
[](https://www.gnu.org/licenses/agpl-3.0)
|
23
|
+

|
24
|
+
[](https://pypi.org/project/kernpy/)
|
25
|
+
[](https://kernpy.pages.dev)
|
26
|
+
[](https://github.com/kernpy/kernpy/actions)
|
27
|
+
[](CONTRIBUTING.md)
|
23
28
|
|
24
|
-
|
29
|
+
|
30
|
+
Python package that provides comprehensive tools for working with symbolic modern and mensural notations in Humdrum format. kernpy is a fully open-source project open to contributions.
|
31
|
+
|
32
|
+
## Documentation
|
33
|
+
Visit the online website: <a target="_blank" href="https://kernpy.pages.dev/">https://kernpy.pages.dev/</a>
|
25
34
|
|
26
35
|
## Index:
|
27
36
|
- [Code examples](#code-examples)
|
@@ -71,18 +80,74 @@ Only use the specified spines in `spine_types`.
|
|
71
80
|
```python
|
72
81
|
import kernpy as kp
|
73
82
|
|
83
|
+
# only export the **kern spines
|
74
84
|
kp.dump(document, "newfile_core.krn",
|
75
85
|
spine_types=['**kern'])
|
86
|
+
|
87
|
+
# only export the **text spines
|
76
88
|
kp.dump(document, "newfile_lyrics.krn",
|
77
89
|
spine_types=['**text])
|
90
|
+
|
91
|
+
# only export **kern and **text spines
|
78
92
|
kp.dump(document, "newfile_core_and_lyrics.krn",
|
79
93
|
spine_types=['*+text'])
|
80
94
|
```
|
81
95
|
|
96
|
+
- The categories are hierarchically defined in the `TokenCategory` class.
|
97
|
+
See the hierarchy as a tree
|
98
|
+
```python
|
99
|
+
import kernpy as kp
|
100
|
+
|
101
|
+
|
102
|
+
print(kp.TokenCategory.tree())
|
103
|
+
```
|
104
|
+
Tree:
|
105
|
+
```txt
|
106
|
+
.
|
107
|
+
├── STRUCTURAL
|
108
|
+
│ ├── HEADER
|
109
|
+
│ └── SPINE_OPERATION
|
110
|
+
├── CORE
|
111
|
+
│ ├── NOTE_REST
|
112
|
+
│ │ ├── DURATION
|
113
|
+
│ │ ├── NOTE
|
114
|
+
│ │ │ ├── PITCH
|
115
|
+
│ │ │ ├── DECORATION
|
116
|
+
│ │ │ └── ALTERATION
|
117
|
+
│ │ └── REST
|
118
|
+
│ ├── CHORD
|
119
|
+
│ ├── EMPTY
|
120
|
+
│ └── ERROR
|
121
|
+
├── SIGNATURES
|
122
|
+
│ ├── CLEF
|
123
|
+
│ ├── TIME_SIGNATURE
|
124
|
+
│ ├── METER_SYMBOL
|
125
|
+
│ ├── KEY_SIGNATURE
|
126
|
+
│ └── KEY_TOKEN
|
127
|
+
├── ENGRAVED_SYMBOLS
|
128
|
+
├── OTHER_CONTEXTUAL
|
129
|
+
├── BARLINES
|
130
|
+
├── COMMENTS
|
131
|
+
│ ├── FIELD_COMMENTS
|
132
|
+
│ └── LINE_COMMENTS
|
133
|
+
├── DYNAMICS
|
134
|
+
├── HARMONY
|
135
|
+
├── FINGERING
|
136
|
+
├── LYRICS
|
137
|
+
├── INSTRUMENTS
|
138
|
+
├── IMAGE_ANNOTATIONS
|
139
|
+
│ ├── BOUNDING_BOXES
|
140
|
+
│ └── LINE_BREAK
|
141
|
+
├── OTHER
|
142
|
+
├── MHXM
|
143
|
+
└── ROOT
|
144
|
+
```
|
145
|
+
|
82
146
|
- 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
147
|
```python
|
84
148
|
import kernpy as kp
|
85
149
|
|
150
|
+
|
86
151
|
kp.dump(document, "newfile_only_clefs.krn",
|
87
152
|
include={kp.TokenCategory.CLEF})
|
88
153
|
kp.dump(document, "newfile_only_durations_and_bounding_boxes.krn",
|
@@ -104,6 +169,9 @@ import kernpy as kp
|
|
104
169
|
kp.dump(document, "newfile_custom.krn",
|
105
170
|
include=kp.BEKERN_CATEGORIES, # Preloaded set of simple categories
|
106
171
|
exclude={kp.TokenCategory.PITCH})
|
172
|
+
|
173
|
+
# Inspect the BEKERN preloaded categories
|
174
|
+
print(kp.BEKERN_CATEGORIES)
|
107
175
|
```
|
108
176
|
|
109
177
|
- Use `tokenizer` to select how the categories are split. By default, the `normalizedKern` tokenizer is used.
|
@@ -382,8 +450,10 @@ kp.graph(document, '/tmp/graph.dot')
|
|
382
450
|
### Production version:
|
383
451
|
Just install the last version of **kernpy** using pip:
|
384
452
|
```shell
|
385
|
-
pip3
|
386
|
-
|
453
|
+
pip3 install kernpy
|
454
|
+
|
455
|
+
# ensure you have the latest version
|
456
|
+
pip3 install kernpy --upgrade
|
387
457
|
```
|
388
458
|
|
389
459
|
> [!NOTE]
|
@@ -391,55 +461,6 @@ pip3 install git+https://github.com/OMR-PRAIG-UA-ES/kernpy.git
|
|
391
461
|
|
392
462
|
<hr>
|
393
463
|
|
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
464
|
## Documentation
|
444
465
|
Documentation available at [https://kernpy.pages.dev/](https://kernpy.pages.dev/)
|
445
466
|
|
@@ -461,32 +482,7 @@ cd tests && python -m pytest
|
|
461
482
|
|
462
483
|
We welcome contributions from the community! If you'd like to contribute to the project, please follow these steps:
|
463
484
|
|
464
|
-
|
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
|
-
|
485
|
+
Go to the file [CONTRIBUTING.md](CONTRIBUTING.md) for more information on how to contribute.
|
490
486
|
|
491
487
|
## Citation:
|
492
488
|
```bibtex
|
@@ -1,5 +1,5 @@
|
|
1
|
-
kernpy/__init__.py,sha256=
|
2
|
-
kernpy/__main__.py,sha256=
|
1
|
+
kernpy/__init__.py,sha256=HdHS0T3se8qIU0d2mULhwhgJRfgGmNA4Zhxl4YvjeVA,313
|
2
|
+
kernpy/__main__.py,sha256=ZxsPlyfgzpZjU8TdNBc1SrMyTTr-Osu4j08DXHAgpVQ,4437
|
3
3
|
kernpy/test_grammar.sh,sha256=MP9Hav9nPxTbHeofFEuunwDsLcBoeFRtzPp4bbPnqBU,520
|
4
4
|
kernpy/visualize_analysis.sh,sha256=z68jyZ8zj4w7v5CoC8-J7PGh7dYA_iQbuFL5T63X6qY,526
|
5
5
|
kernpy/core/__init__.py,sha256=gIbOKMWcPcQc4c6QpslWnAw9XkcMJ6OvedHANyDABbs,2581
|
@@ -46,6 +46,6 @@ kernpy/polish_scores/iiif.py,sha256=yITdrQbMsGmm8qag8TSousjCjS2io148Jk9xwEKa3B4,
|
|
46
46
|
kernpy/util/__init__.py,sha256=dfW3nRSMkGQS7p7YebM271_0H8_pVw4IiDKeINs_LI8,152
|
47
47
|
kernpy/util/helpers.py,sha256=Xbj3nWNyErdOpLHYd4uVyfwleXvmC5_FlYEhxaeTtS8,1549
|
48
48
|
kernpy/util/store_cache.py,sha256=AA7SFCGQ6ryy-c02wbLy8gIQ2C-VdM1JSWFoWIK_KLA,1186
|
49
|
-
kernpy-1.0.
|
50
|
-
kernpy-1.0.
|
51
|
-
kernpy-1.0.
|
49
|
+
kernpy-1.0.1.dist-info/METADATA,sha256=1SpNbdsg1KHO4FnR7vSeabwlsueGoA8y-4RDN-v2vZk,15096
|
50
|
+
kernpy-1.0.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
51
|
+
kernpy-1.0.1.dist-info/RECORD,,
|
File without changes
|