partitura 1.3.0__py3-none-any.whl → 1.4.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.
Files changed (41) hide show
  1. partitura/directions.py +3 -0
  2. partitura/display.py +0 -1
  3. partitura/io/__init__.py +41 -35
  4. partitura/io/exportmatch.py +52 -10
  5. partitura/io/exportmidi.py +37 -19
  6. partitura/io/exportmusicxml.py +6 -92
  7. partitura/io/exportparangonada.py +18 -19
  8. partitura/io/importkern.py +2 -4
  9. partitura/io/importmatch.py +121 -39
  10. partitura/io/importmei.py +161 -34
  11. partitura/io/importmidi.py +23 -14
  12. partitura/io/importmusic21.py +0 -1
  13. partitura/io/importmusicxml.py +48 -63
  14. partitura/io/importparangonada.py +0 -1
  15. partitura/io/matchfile_base.py +0 -21
  16. partitura/io/matchfile_utils.py +29 -17
  17. partitura/io/matchlines_v0.py +0 -22
  18. partitura/io/matchlines_v1.py +8 -42
  19. partitura/io/musescore.py +68 -41
  20. partitura/musicanalysis/__init__.py +1 -1
  21. partitura/musicanalysis/note_array_to_score.py +147 -92
  22. partitura/musicanalysis/note_features.py +66 -51
  23. partitura/musicanalysis/performance_codec.py +140 -96
  24. partitura/musicanalysis/performance_features.py +190 -129
  25. partitura/musicanalysis/pitch_spelling.py +0 -2
  26. partitura/musicanalysis/tonal_tension.py +0 -6
  27. partitura/musicanalysis/voice_separation.py +1 -22
  28. partitura/performance.py +178 -5
  29. partitura/score.py +154 -74
  30. partitura/utils/__init__.py +1 -1
  31. partitura/utils/generic.py +3 -7
  32. partitura/utils/misc.py +0 -1
  33. partitura/utils/music.py +108 -66
  34. partitura/utils/normalize.py +75 -35
  35. partitura/utils/synth.py +1 -7
  36. {partitura-1.3.0.dist-info → partitura-1.4.0.dist-info}/METADATA +2 -2
  37. partitura-1.4.0.dist-info/RECORD +51 -0
  38. {partitura-1.3.0.dist-info → partitura-1.4.0.dist-info}/WHEEL +1 -1
  39. partitura-1.3.0.dist-info/RECORD +0 -51
  40. {partitura-1.3.0.dist-info → partitura-1.4.0.dist-info}/LICENSE +0 -0
  41. {partitura-1.3.0.dist-info → partitura-1.4.0.dist-info}/top_level.txt +0 -0
@@ -595,11 +595,9 @@ class BaseSnoteLine(MatchLine):
595
595
  matchline: str,
596
596
  pos: int = 0,
597
597
  ) -> Dict:
598
-
599
598
  match_pattern = cls.pattern.search(matchline, pos)
600
599
 
601
600
  if match_pattern is not None:
602
-
603
601
  (
604
602
  anchor_str,
605
603
  note_name_str,
@@ -640,7 +638,6 @@ class BaseSnoteLine(MatchLine):
640
638
 
641
639
 
642
640
  class BaseNoteLine(MatchLine):
643
-
644
641
  # All derived classes should include at least
645
642
  # these field names
646
643
  field_names = (
@@ -683,7 +680,6 @@ class BaseNoteLine(MatchLine):
683
680
 
684
681
 
685
682
  class BaseSnoteNoteLine(MatchLine):
686
-
687
683
  out_pattern = "{SnoteLine}-{NoteLine}"
688
684
 
689
685
  def __init__(
@@ -692,7 +688,6 @@ class BaseSnoteNoteLine(MatchLine):
692
688
  snote: BaseSnoteLine,
693
689
  note: BaseNoteLine,
694
690
  ) -> None:
695
-
696
691
  super().__init__(version)
697
692
 
698
693
  self.snote = snote
@@ -714,7 +709,6 @@ class BaseSnoteNoteLine(MatchLine):
714
709
  )
715
710
 
716
711
  def __str__(self) -> str:
717
-
718
712
  """
719
713
  Prints the printing the match line
720
714
  """
@@ -775,11 +769,9 @@ class BaseSnoteNoteLine(MatchLine):
775
769
 
776
770
 
777
771
  class BaseDeletionLine(MatchLine):
778
-
779
772
  out_pattern = "{SnoteLine}-deletion."
780
773
 
781
774
  def __init__(self, version: Version, snote: BaseSnoteLine) -> None:
782
-
783
775
  super().__init__(version)
784
776
 
785
777
  self.snote = snote
@@ -808,7 +800,6 @@ class BaseDeletionLine(MatchLine):
808
800
  snote_class: BaseSnoteLine,
809
801
  version: Version,
810
802
  ) -> Dict:
811
-
812
803
  snote = snote_class.from_matchline(matchline, version=version)
813
804
 
814
805
  kwargs = dict(
@@ -820,11 +811,9 @@ class BaseDeletionLine(MatchLine):
820
811
 
821
812
 
822
813
  class BaseInsertionLine(MatchLine):
823
-
824
814
  out_pattern = "insertion-{NoteLine}"
825
815
 
826
816
  def __init__(self, version: Version, note: BaseNoteLine) -> None:
827
-
828
817
  super().__init__(version)
829
818
 
830
819
  self.note = note
@@ -853,7 +842,6 @@ class BaseInsertionLine(MatchLine):
853
842
  note_class: BaseNoteLine,
854
843
  version: Version,
855
844
  ) -> Dict:
856
-
857
845
  note = note_class.from_matchline(matchline, version=version)
858
846
 
859
847
  kwargs = dict(
@@ -865,7 +853,6 @@ class BaseInsertionLine(MatchLine):
865
853
 
866
854
 
867
855
  class BaseOrnamentLine(MatchLine):
868
-
869
856
  # These field names and types need to be expanded
870
857
  # with the attributes of the note
871
858
  field_names = ("Anchor",)
@@ -875,7 +862,6 @@ class BaseOrnamentLine(MatchLine):
875
862
  ornament_pattern: re.Pattern = re.compile(r"ornament\((?P<Anchor>[^\)]*)\)-")
876
863
 
877
864
  def __init__(self, version: Version, anchor: str, note: BaseNoteLine) -> None:
878
-
879
865
  super().__init__(version)
880
866
 
881
867
  self.note = note
@@ -907,7 +893,6 @@ class BaseOrnamentLine(MatchLine):
907
893
  note_class: BaseNoteLine,
908
894
  version: Version,
909
895
  ) -> Dict:
910
-
911
896
  anchor_pattern = cls.ornament_pattern.search(matchline)
912
897
 
913
898
  if anchor_pattern is None:
@@ -957,14 +942,12 @@ class BasePedalLine(MatchLine):
957
942
  version: Version,
958
943
  pos: int = 0,
959
944
  ) -> Dict:
960
-
961
945
  kwargs = None
962
946
  # pattern = re.compile(cls.base_pattern.format(pedal_type=pedal_type))
963
947
 
964
948
  match_pattern = cls.pattern.search(matchline, pos=pos)
965
949
 
966
950
  if match_pattern is not None:
967
-
968
951
  time_str, value_str = match_pattern.groups()
969
952
 
970
953
  kwargs = dict(
@@ -977,7 +960,6 @@ class BasePedalLine(MatchLine):
977
960
 
978
961
 
979
962
  class BaseSustainPedalLine(BasePedalLine):
980
-
981
963
  pattern = re.compile(r"sustain\((?P<Time>[^,]+),(?P<Value>[^,]+)\)\.")
982
964
  out_pattern: str = "sustain({Time},{Value})."
983
965
 
@@ -991,7 +973,6 @@ class BaseSustainPedalLine(BasePedalLine):
991
973
 
992
974
 
993
975
  class BaseSoftPedalLine(BasePedalLine):
994
-
995
976
  pattern = re.compile(r"soft\((?P<Time>[^,]+),(?P<Value>[^,]+)\)\.")
996
977
  out_pattern: str = "soft({Time},{Value})."
997
978
 
@@ -1022,7 +1003,6 @@ class MatchFile(object):
1022
1003
  lines: np.ndarray
1023
1004
 
1024
1005
  def __init__(self, lines: Iterable[MatchLine]) -> None:
1025
-
1026
1006
  # check that all lines have the same version
1027
1007
  same_version = all([line.version == lines[0].version for line in lines])
1028
1008
 
@@ -1187,7 +1167,6 @@ class MatchFile(object):
1187
1167
 
1188
1168
  @property
1189
1169
  def key_sig_lines(self):
1190
-
1191
1170
  ml = [
1192
1171
  line
1193
1172
  for line in self.lines
@@ -214,7 +214,6 @@ old_string_pat = re.compile(r"'(?P<value>.+)'")
214
214
 
215
215
 
216
216
  def interpret_as_string_old(value: str) -> str:
217
-
218
217
  val = old_string_pat.match(value)
219
218
  if val is not None:
220
219
  return val.group("value").strip()
@@ -272,7 +271,6 @@ class FractionalSymbolicDuration(object):
272
271
  tuple_div: Optional[int] = None,
273
272
  add_components: Optional[List[Tuple[int, int, Optional[int]]]] = None,
274
273
  ) -> None:
275
-
276
274
  self.numerator = numerator
277
275
  self.denominator = denominator
278
276
  self.tuple_div = tuple_div
@@ -459,7 +457,6 @@ class FractionalSymbolicDuration(object):
459
457
 
460
458
  @classmethod
461
459
  def from_string(cls, string: str, allow_additions: bool = True):
462
-
463
460
  m = rational_pattern.match(string)
464
461
  m2 = double_rational_pattern.match(string)
465
462
  m3 = integer_pattern.match(string)
@@ -537,7 +534,6 @@ def format_fractional_rational(value: FractionalSymbolicDuration) -> str:
537
534
  """
538
535
 
539
536
  if value.denominator == 1 and value.tuple_div is None:
540
-
541
537
  out = f"{value.numerator}/1"
542
538
 
543
539
  else:
@@ -588,14 +584,12 @@ def format_list(value: List[Any]) -> str:
588
584
 
589
585
 
590
586
  def format_accidental(value: Optional[int]) -> str:
591
-
592
587
  alter = "n" if value == 0 else ALTER_SIGNS[value]
593
588
 
594
589
  return alter
595
590
 
596
591
 
597
592
  def format_accidental_old(value: Optional[int]) -> str:
598
-
599
593
  if value is None:
600
594
  return "-"
601
595
  else:
@@ -603,7 +597,6 @@ def format_accidental_old(value: Optional[int]) -> str:
603
597
 
604
598
 
605
599
  def format_pnote_id(value: Any) -> str:
606
-
607
600
  pnote_id = f"n{str(value)}" if not str(value).startswith("n") else str(value)
608
601
 
609
602
  return pnote_id
@@ -684,7 +677,6 @@ class MatchKeySignature(MatchParameter):
684
677
  return ks
685
678
 
686
679
  def __str__(self):
687
-
688
680
  if self.fmt == "v1.0.0":
689
681
  ks = fifths_mode_to_key_name(self.fifths, self.mode)
690
682
 
@@ -705,7 +697,6 @@ class MatchKeySignature(MatchParameter):
705
697
  return ks
706
698
 
707
699
  def __eq__(self, ks: MatchKeySignature) -> bool:
708
-
709
700
  crit = (
710
701
  self.fifths == ks.fifths
711
702
  and self.mode == ks.mode
@@ -718,7 +709,6 @@ class MatchKeySignature(MatchParameter):
718
709
 
719
710
  @classmethod
720
711
  def _parse_key_signature(cls, kstr: str) -> MatchKeySignature:
721
-
722
712
  # import pdb
723
713
  # pdb.set_trace()
724
714
  ksinfo = key_signature_pattern.search(kstr)
@@ -731,7 +721,6 @@ class MatchKeySignature(MatchParameter):
731
721
  if len(ksinfo) == 2:
732
722
  fifths2, mode2 = key_name_to_fifths_mode(ksinfo[1].upper())
733
723
  else:
734
-
735
724
  fmt = "v0.3.0"
736
725
  step1, alter1, mode1, step2, alter2, mode2 = ksinfo.groups()
737
726
  mode1_str = "m" if mode1.lower() in ("minor", "min") else ""
@@ -779,7 +768,6 @@ class MatchKeySignature(MatchParameter):
779
768
  return cls(fifths=fifths, mode=mode, fmt="v0.1.0")
780
769
 
781
770
  if len(content) > 0:
782
-
783
771
  ksigs = [cls._parse_key_signature(ksig) for ksig in content]
784
772
 
785
773
  ks = ksigs[0]
@@ -838,7 +826,6 @@ class MatchTimeSignature(MatchParameter):
838
826
  self.is_list = is_list
839
827
 
840
828
  def __str__(self):
841
-
842
829
  ts = f"{self.numerator}/{self.denominator}"
843
830
  if self.is_list:
844
831
  return format_list([ts] + self.other_components)
@@ -846,7 +833,6 @@ class MatchTimeSignature(MatchParameter):
846
833
  return ts
847
834
 
848
835
  def __eq__(self, ts: MatchKeySignature) -> bool:
849
-
850
836
  crit = (
851
837
  (self.numerator == ts.numerator)
852
838
  and (self.denominator == ts.denominator)
@@ -871,7 +857,6 @@ class MatchTimeSignature(MatchParameter):
871
857
 
872
858
 
873
859
  def interpret_as_time_signature(value: str) -> MatchTimeSignature:
874
-
875
860
  ts = MatchTimeSignature.from_string(value)
876
861
  return ts
877
862
 
@@ -886,6 +871,35 @@ def format_time_signature_list(value: MatchTimeSignature) -> str:
886
871
  return str(value)
887
872
 
888
873
 
874
+ class MatchTempoIndication(MatchParameter):
875
+ def __init__(
876
+ self,
877
+ value: str,
878
+ is_list: bool = False,
879
+ ):
880
+ super().__init__()
881
+ self.value = self.from_string(value)[0]
882
+ self.is_list = is_list
883
+
884
+ def __str__(self):
885
+ return self.value
886
+
887
+ @classmethod
888
+ def from_string(cls, string: str) -> MatchTempoIndication:
889
+ content = interpret_as_list(string)
890
+ return content
891
+
892
+
893
+ def interpret_as_tempo_indication(value: str) -> MatchTempoIndication:
894
+ tempo_indication = MatchTempoIndication.from_string(value)
895
+ return tempo_indication
896
+
897
+
898
+ def format_tempo_indication(value: MatchTempoIndication) -> str:
899
+ value.is_list = False
900
+ return str(value)
901
+
902
+
889
903
  ## Miscellaneous utils
890
904
 
891
905
 
@@ -912,7 +926,6 @@ def to_camel_case(field_name: str) -> str:
912
926
  camel_case = f"{parts[0].lower()}"
913
927
 
914
928
  if len(parts) > 1:
915
-
916
929
  camel_case += "".join([p.title() for p in parts[1:]])
917
930
 
918
931
  return camel_case
@@ -943,7 +956,6 @@ def get_kwargs_from_matchline(
943
956
  match_pattern = pattern.search(matchline, pos=pos)
944
957
 
945
958
  if match_pattern is not None:
946
-
947
959
  kwargs = dict(
948
960
  [
949
961
  (to_snake_case(fn), class_dict[fn][0](match_pattern.group(fn)))
@@ -208,7 +208,6 @@ class MatchInfo(BaseInfoLine):
208
208
  value_type: type,
209
209
  format_fun: Callable[Any, str],
210
210
  ) -> None:
211
-
212
211
  if version >= Version(1, 0, 0):
213
212
  raise ValueError("The version must be < 1.0.0")
214
213
 
@@ -294,7 +293,6 @@ META_LINE = {
294
293
 
295
294
 
296
295
  class MatchMeta(MatchLine):
297
-
298
296
  field_names = (
299
297
  "Attribute",
300
298
  "Value",
@@ -322,7 +320,6 @@ class MatchMeta(MatchLine):
322
320
  measure: int,
323
321
  time_in_beats: float,
324
322
  ) -> None:
325
-
326
323
  if version >= Version(1, 0, 0):
327
324
  raise ValueError("The version must be < 1.0.0")
328
325
 
@@ -382,7 +379,6 @@ class MatchMeta(MatchLine):
382
379
  class_dict = META_LINE[version]
383
380
 
384
381
  if match_pattern is not None:
385
-
386
382
  (
387
383
  attribute,
388
384
  value_str,
@@ -681,7 +677,6 @@ class MatchNote(BaseNoteLine):
681
677
  velocity: int,
682
678
  **kwargs,
683
679
  ) -> None:
684
-
685
680
  if version not in NOTE_LINE:
686
681
  raise ValueError(
687
682
  f"Unknown version {version}!. "
@@ -720,7 +715,6 @@ class MatchNote(BaseNoteLine):
720
715
  self.AdjOffset = offset
721
716
 
722
717
  if "adj_offset" in kwargs:
723
-
724
718
  self.AdjOffset = kwargs["adj_offset"]
725
719
 
726
720
  @property
@@ -734,7 +728,6 @@ class MatchNote(BaseNoteLine):
734
728
  pos: int = 0,
735
729
  version: Version = LAST_VERSION,
736
730
  ) -> MatchNote:
737
-
738
731
  if version >= Version(1, 0, 0):
739
732
  raise ValueError(f"{version} >= Version(1, 0, 0)")
740
733
 
@@ -760,7 +753,6 @@ class MatchSnoteNote(BaseSnoteNoteLine):
760
753
  snote: MatchSnote,
761
754
  note: MatchNote,
762
755
  ) -> None:
763
-
764
756
  super().__init__(
765
757
  version=version,
766
758
  snote=snote,
@@ -773,7 +765,6 @@ class MatchSnoteNote(BaseSnoteNoteLine):
773
765
  matchline: str,
774
766
  version: Version = LAST_VERSION,
775
767
  ) -> MatchSnoteNote:
776
-
777
768
  if version >= Version(1, 0, 0):
778
769
  raise ValueError(f"{version} >= Version(1, 0, 0)")
779
770
 
@@ -789,7 +780,6 @@ class MatchSnoteNote(BaseSnoteNoteLine):
789
780
 
790
781
  class MatchSnoteDeletion(BaseDeletionLine):
791
782
  def __init__(self, version: Version, snote: MatchSnote) -> None:
792
-
793
783
  super().__init__(
794
784
  version=version,
795
785
  snote=snote,
@@ -801,7 +791,6 @@ class MatchSnoteDeletion(BaseDeletionLine):
801
791
  matchline: str,
802
792
  version: Version = LAST_VERSION,
803
793
  ) -> MatchSnoteDeletion:
804
-
805
794
  if version >= Version(1, 0, 0):
806
795
  raise ValueError(f"{version} >= Version(1, 0, 0)")
807
796
 
@@ -834,7 +823,6 @@ class MatchSnoteNoPlayedNote(MatchSnoteDeletion):
834
823
 
835
824
  class MatchInsertionNote(BaseInsertionLine):
836
825
  def __init__(self, version: Version, note: MatchNote) -> None:
837
-
838
826
  super().__init__(
839
827
  version=version,
840
828
  note=note,
@@ -846,7 +834,6 @@ class MatchInsertionNote(BaseInsertionLine):
846
834
  matchline: str,
847
835
  version: Version = LAST_VERSION,
848
836
  ) -> MatchInsertionNote:
849
-
850
837
  if version >= Version(1, 0, 0):
851
838
  raise ValueError(f"{version} >= Version(1, 0, 0)")
852
839
 
@@ -860,7 +847,6 @@ class MatchInsertionNote(BaseInsertionLine):
860
847
 
861
848
 
862
849
  class MatchHammerBounceNote(MatchInsertionNote):
863
-
864
850
  out_pattern = "hammer_bounce-{NoteLine}"
865
851
 
866
852
  def __init__(self, version: Version, note: MatchNote) -> None:
@@ -869,7 +855,6 @@ class MatchHammerBounceNote(MatchInsertionNote):
869
855
 
870
856
 
871
857
  class MatchTrailingPlayedNote(MatchInsertionNote):
872
-
873
858
  out_pattern = "trailing_played_note-{NoteLine}"
874
859
 
875
860
  def __init__(self, version: Version, note: MatchNote) -> None:
@@ -878,7 +863,6 @@ class MatchTrailingPlayedNote(MatchInsertionNote):
878
863
 
879
864
 
880
865
  class MatchTrillNote(BaseOrnamentLine):
881
-
882
866
  out_pattern = "trill({Anchor})-{NoteLine}"
883
867
  ornament_pattern: re.Pattern = re.compile(r"trill\((?P<Anchor>[^\)]*)\)-")
884
868
 
@@ -900,7 +884,6 @@ class MatchTrillNote(BaseOrnamentLine):
900
884
  matchline: str,
901
885
  version: Version = LAST_VERSION,
902
886
  ) -> MatchTrillNote:
903
-
904
887
  if version >= Version(1, 0, 0):
905
888
  raise ValueError(f"{version} >= Version(1, 0, 0)")
906
889
 
@@ -924,7 +907,6 @@ class MatchSustainPedal(BaseSustainPedalLine):
924
907
  time: int,
925
908
  value: int,
926
909
  ) -> None:
927
-
928
910
  super().__init__(
929
911
  version=version,
930
912
  time=time,
@@ -938,7 +920,6 @@ class MatchSustainPedal(BaseSustainPedalLine):
938
920
  version: Version = LAST_VERSION,
939
921
  pos: int = 0,
940
922
  ) -> MatchSustainPedal:
941
-
942
923
  if version >= Version(1, 0, 0):
943
924
  raise ValueError(f"{version} less than 1.0.0")
944
925
 
@@ -961,7 +942,6 @@ class MatchSoftPedal(BaseSoftPedalLine):
961
942
  time: int,
962
943
  value: int,
963
944
  ) -> None:
964
-
965
945
  super().__init__(
966
946
  version=version,
967
947
  time=time,
@@ -975,7 +955,6 @@ class MatchSoftPedal(BaseSoftPedalLine):
975
955
  version: Version = LAST_VERSION,
976
956
  pos: int = 0,
977
957
  ) -> MatchSoftPedal:
978
-
979
958
  if version >= Version(1, 0, 0):
980
959
  raise ValueError(f"{version} should be less than 1.0.0")
981
960
 
@@ -1025,7 +1004,6 @@ def parse_matchline(line: str, version: Version) -> Optional[MatchLine]:
1025
1004
  return parse(MatchMeta)
1026
1005
 
1027
1006
  if line.startswith("snote"):
1028
-
1029
1007
  for mlt in [
1030
1008
  MatchSnoteNote,
1031
1009
  MatchSnoteDeletion,