Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR for Release 1.4.1 #335

Merged
merged 26 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
66f2188
remove unnecessary escape character
sildater Oct 6, 2023
0ea767a
Merge pull request #325 from CPJKU/bug_nakamura_match
CarlosCancino-Chacon Oct 6, 2023
956812d
Format code with black (bot)
Oct 6, 2023
36848ac
handle none type doc order
sildater Oct 11, 2023
fae5d1c
voice parsing from matchfile fix
huispaty Oct 20, 2023
8f8fd7c
voice parsing for multiple mf versions
huispaty Oct 23, 2023
3b26ee7
check patterns
sildater Oct 23, 2023
0e9d6c3
Merge pull request #328 from CPJKU/bug_fix_326
CarlosCancino-Chacon Oct 23, 2023
9526dbd
Format code with black (bot)
Oct 23, 2023
e117f7a
correction for mistakenly deleted line
huispaty Oct 23, 2023
39d9741
voice info addendum on part directly
huispaty Oct 23, 2023
9ba3813
add one to voice
sildater Oct 23, 2023
60b04af
Merge pull request #331 from CPJKU/match_voice_parsing_fix
sildater Oct 23, 2023
465f28f
Format code with black (bot)
sildater Oct 23, 2023
848e8fa
Merge pull request #332 from CPJKU/parse_specified_dels_and_ins
CarlosCancino-Chacon Oct 24, 2023
54d0a6a
Format code with black (bot)
Oct 24, 2023
a6220b5
solution without dummies
sildater Oct 24, 2023
5d81106
Merge pull request #334 from CPJKU/non_dummy_refactor
CarlosCancino-Chacon Oct 24, 2023
ded12a6
Format code with black (bot)
Oct 24, 2023
487a048
Update CHANGES.md
fosfrancesco Oct 24, 2023
45b5c79
Update setup.py
fosfrancesco Oct 24, 2023
826c55c
Update conf.py
fosfrancesco Oct 24, 2023
d6786e8
vectorization of None mask
sildater Oct 25, 2023
a22b20d
Format code with black (bot)
sildater Oct 25, 2023
0f50a21
all MatchErrors formatted the same
sildater Oct 25, 2023
8ee8ba9
Merge branch 'develop' of https://github.com/CPJKU/partitura into dev…
sildater Oct 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
Release Notes
=============

Version 1.4.1 (Released on 2023-10-25)
--------------------------------------

## Bug Fixes
- remove unnecessary escape characters for correct parsing of sharp accidentals in Nakamura match files.
- don't consider the propriety `doc_order` for sorting notes in the `matchfile_from_alignment` function if it is not present. This propriety is only present in parts from musicxml scores and previously resulted in an exception for other score formats. This solves https://github.com/CPJKU/partitura/issues/326
- during matchfile parsing, voice info is now parsed as follows: If there is no voice info, all notes get assigned voice number 1. If there is only voice info for the solo voice, the non-solo voiced notes get voice 2. If multiple notes have different voices, but not every note has a voice annotated, those with voice annotation get the annotated voice number and those without voice annotation get assigned the max voice+1 voice number. Previously all notes were assigned to voice 1 if there were any None voiced note
- during matchfile parsing, all note classes are now matched correctly. Previously classes `MatchSnoteTrailingScore` and `MatchSnoteNoPlayedNote` were always marked as `MatchSnoteDeletion` and `MatchHammerBounceNote`, `MatchTrailingPlayedNote`, `MatchTrillNote` always ended up as `MatchInsertionNote`. This solves https://github.com/CPJKU/partitura/issues/286
- during matchfile parsing, lines which can't be parsed are removed. Before they ended up as `None` in the output.

Version 1.4.0 (Released on 2023-09-22)
--------------------------------------

Expand Down
4 changes: 2 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@
# built documents.
#
# The short X.Y version.
version = "1.4.0" # pkg_resources.get_distribution("partitura").version
version = "1.4.1" # pkg_resources.get_distribution("partitura").version
# The full version, including alpha/beta/rc tags.
release = "1.4.0"
release = "1.4.1"

# # The full version, including alpha/beta/rc tags
# release = pkg_resources.get_distribution("partitura").version
Expand Down
5 changes: 4 additions & 1 deletion partitura/io/exportmatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,10 @@ def matchfile_from_alignment(
offset_in_beats=offset_beats,
score_attributes_list=score_attributes_list,
)
snote_sort_info[snote.id] = (onset_beats, snote.doc_order)
snote_sort_info[snote.id] = (
onset_beats,
snote.doc_order if snote.doc_order is not None else 0,
)

# # NOTE time position is hardcoded, not pretty... Assumes there is only one tempo indication at the beginning of the score
if tempo_indication is not None:
Expand Down
27 changes: 20 additions & 7 deletions partitura/io/importmatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
from partitura.io.matchfile_utils import (
Version,
number_pattern,
vnumber_pattern,
MatchTimeSignature,
MatchKeySignature,
format_pnote_id,
Expand Down Expand Up @@ -209,7 +210,9 @@ def load_matchfile(
parse_matchline, version=version, from_matchline_methods=from_matchline_methods
)
f_vec = np.vectorize(f)
parsed_lines = f_vec(np_lines).tolist()
parsed_lines_raw = f_vec(np_lines).tolist()
# do not return unparseable lines
parsed_lines = [line for line in parsed_lines_raw if line is not None]
fosfrancesco marked this conversation as resolved.
Show resolved Hide resolved
# Create MatchFile instance
mf = MatchFile(lines=parsed_lines)
# Validate match for duplicate snote_ids or pnote_ids
Expand Down Expand Up @@ -629,9 +632,17 @@ def part_from_matchfile(
except (TypeError, ValueError):
# no staff attribute, or staff attribute does not end with a number
note_attributes["staff"] = None

fosfrancesco marked this conversation as resolved.
Show resolved Hide resolved
if "s" in note.ScoreAttributesList:
note_attributes["voice"] = 1
elif any(a.startswith("v") for a in note.ScoreAttributesList):
fosfrancesco marked this conversation as resolved.
Show resolved Hide resolved
note_attributes["voice"] = next(
(
int(a[1:])
for a in note.ScoreAttributesList
if vnumber_pattern.match(a)
),
None,
)
else:
note_attributes["voice"] = next(
(int(a) for a in note.ScoreAttributesList if number_pattern.match(a)),
Expand Down Expand Up @@ -692,9 +703,7 @@ def part_from_matchfile(

else:
part_note = score.Note(**note_attributes)

part.add(part_note, onset_divs, offset_divs)

# Check if the note is tied and if so, add the tie information
if is_tied:
found = False
Expand All @@ -717,7 +726,6 @@ def part_from_matchfile(
part_note.id
)
)

# add time signatures
for ts_beat_time, ts_bar, tsg in ts:
ts_beats = tsg.numerator
Expand All @@ -729,7 +737,6 @@ def part_from_matchfile(
else:
bar_start_divs = 0
part.add(score.TimeSignature(ts_beats, ts_beat_type), bar_start_divs)

# add key signatures
for ks_beat_time, ks_bar, keys in mf.key_signatures:
if ks_bar in bar_times.keys():
Expand All @@ -755,10 +762,16 @@ def part_from_matchfile(
score.tie_notes(part)
score.find_tuplets(part)

if not all([n.voice for n in part.notes_tied]):
n_voices = set([n.voice for n in part.notes])
fosfrancesco marked this conversation as resolved.
Show resolved Hide resolved
if len(n_voices) == 1 and None in n_voices:
for note in part.notes_tied:
if note.voice is None:
note.voice = 1
elif len(n_voices) > 1 and None in n_voices:
n_voices.remove(None)
for note in part.notes_tied:
if note.voice is None:
note.voice = max(n_voices) + 1

return part

Expand Down
4 changes: 1 addition & 3 deletions partitura/io/importnakamura.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,7 @@ def load_nakamuramatch(filename: PathLike) -> Tuple[Union[np.ndarray, list]]:
# load missing notes
missing = np.fromregex(filename, pattern, dtype=dtype_missing)

midi_pitch = np.array(
[note_name_to_midi_pitch(n.replace("#", r"\#")) for n in result["alignSitch"]]
)
midi_pitch = np.array([note_name_to_midi_pitch(n) for n in result["alignSitch"]])

align_valid = result["alignID"] != "*"
n_align = sum(align_valid)
Expand Down
13 changes: 13 additions & 0 deletions partitura/io/matchfile_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,7 @@ def prepare_kwargs_from_matchline(

class BaseDeletionLine(MatchLine):
out_pattern = "{SnoteLine}-deletion."
identifier_pattern = re.compile(r"-deletion\.")

def __init__(self, version: Version, snote: BaseSnoteLine) -> None:
super().__init__(version)
Expand Down Expand Up @@ -799,7 +800,12 @@ def prepare_kwargs_from_matchline(
matchline: str,
snote_class: BaseSnoteLine,
version: Version,
pos: int = 0,
) -> Dict:
match_pattern = cls.identifier_pattern.search(matchline, pos=pos)

if match_pattern is None:
raise MatchError("")
fosfrancesco marked this conversation as resolved.
Show resolved Hide resolved
snote = snote_class.from_matchline(matchline, version=version)

kwargs = dict(
Expand All @@ -812,6 +818,7 @@ def prepare_kwargs_from_matchline(

class BaseInsertionLine(MatchLine):
out_pattern = "insertion-{NoteLine}"
identifier_pattern = re.compile(r"insertion-")

def __init__(self, version: Version, note: BaseNoteLine) -> None:
super().__init__(version)
Expand Down Expand Up @@ -841,7 +848,13 @@ def prepare_kwargs_from_matchline(
matchline: str,
note_class: BaseNoteLine,
version: Version,
pos: int = 0,
) -> Dict:
match_pattern = cls.identifier_pattern.search(matchline, pos=pos)

if match_pattern is None:
raise MatchError("")
fosfrancesco marked this conversation as resolved.
Show resolved Hide resolved

note = note_class.from_matchline(matchline, version=version)

kwargs = dict(
Expand Down
1 change: 1 addition & 0 deletions partitura/io/matchfile_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
pitch_class_pattern = re.compile("(?P<step>[A-Ga-g])(?P<alter>[#bn]*)")

number_pattern = re.compile(r"\d+")
vnumber_pattern = re.compile(r"v\d+")

# For matchfiles before 1.0.0.
old_version_pattern = re.compile(r"^(?P<minor>[0-9]+)\.(?P<patch>[0-9]+)")
Expand Down
4 changes: 4 additions & 0 deletions partitura/io/matchlines_v0.py
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,7 @@ def from_matchline(

class MatchSnoteTrailingScore(MatchSnoteDeletion):
out_pattern = "{SnoteLine}-trailing_score_note."
identifier_pattern = re.compile(r"-trailing_score_note\.")

def __init__(self, version: Version, snote: MatchSnote) -> None:
super().__init__(version=version, snote=snote)
Expand All @@ -815,6 +816,7 @@ def __init__(self, version: Version, snote: MatchSnote) -> None:

class MatchSnoteNoPlayedNote(MatchSnoteDeletion):
out_pattern = "{SnoteLine}-no_played_note."
identifier_pattern = re.compile(r"-no_played_note\.")

def __init__(self, version: Version, snote: MatchSnote) -> None:
super().__init__(version=version, snote=snote)
Expand Down Expand Up @@ -848,6 +850,7 @@ def from_matchline(

class MatchHammerBounceNote(MatchInsertionNote):
out_pattern = "hammer_bounce-{NoteLine}"
identifier_pattern = re.compile(r"hammer_bounce-")

def __init__(self, version: Version, note: MatchNote) -> None:
super().__init__(version=version, note=note)
Expand All @@ -856,6 +859,7 @@ def __init__(self, version: Version, note: MatchNote) -> None:

class MatchTrailingPlayedNote(MatchInsertionNote):
out_pattern = "trailing_played_note-{NoteLine}"
identifier_pattern = re.compile(r"trailing_played_note-")

def __init__(self, version: Version, note: MatchNote) -> None:
super().__init__(version=version, note=note)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
EMAIL = "[email protected]"
AUTHOR = "Maarten Grachten, Carlos Cancino-Chacón, Silvan Peter, Emmanouil Karystinaios, Francesco Foscarin, Thassilo Gadermaier, Patricia Hu"
REQUIRES_PYTHON = ">=3.7"
VERSION = "1.4.0"
VERSION = "1.4.1"

# What packages are required for this module to be executed?
REQUIRED = ["numpy", "scipy", "lxml", "lark-parser", "xmlschema", "mido"]
Expand Down
6 changes: 5 additions & 1 deletion tests/test_match_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ def test_load_match(self):
)

sna_musicxml = score_musicxml.note_array()
assert np.all(sna_match['voice'] == sna_musicxml['voice'])

for note in alignment:

Expand Down Expand Up @@ -564,7 +565,7 @@ def test_stimeptime_lines(self):
self.assertTrue(True)

def test_snote_lines(self):

snote_lines = [
"snote(n1,[B,n],3,0:2,1/8,1/8,-0.5000,0.0000,[v1])",
"snote(n3,[G,#],3,1:1,0,1/16,0.0000,0.2500,[v3])",
Expand Down Expand Up @@ -1992,3 +1993,6 @@ def test_match_key_signature(self):
for component in ks.other_components:
key_name = fifths_mode_to_key_name(component.fifths, component.mode)
self.assertTrue(str(component).startswith(key_name))

if __name__ == "__main__":
unittest.main()