Source code for muspy.datasets.haydn

"""Haydn Op.20 Dataset."""
from pathlib import Path
from typing import List, Union

import music21
from music21.roman import RomanNumeral

from ..classes import Annotation
from ..inputs import from_music21_score
from ..music import DEFAULT_RESOLUTION, Music
from .base import DatasetInfo, RemoteFolderDataset

# pylint: disable=line-too-long

_NAME = "Haydn Op.20 Dataset"
_DESCRIPTION = """\
This dataset is a set of functional harmonic analysis annotations \
for the Op.20 string quartets from Joseph Haydn, commonly known as \
the 'Sun' quartets."""
_HOMEPAGE = "https://doi.org/10.5281/zenodo.1095630"
_CITATION = """\
@dataset{nestor_napoles_lopez_2017_1095630,
  author={N\'apoles L\'opez, N\'estor},
  title={{Joseph Haydn - String Quartets Op.20 - Harmonic Analysis Annotations Dataset}},
  month=dec,
  year=2017,
  publisher={Zenodo},
  version={v1.1-alpha},
  doi={10.5281/zenodo.1095630},
  url={https://doi.org/10.5281/zenodo.1095630}
}"""


[docs]class HaydnOp20Dataset(RemoteFolderDataset): """Haydn Op.20 Dataset.""" _info = DatasetInfo(_NAME, _DESCRIPTION, _HOMEPAGE) _citation = _CITATION _sources = { "haydn": { "filename": "haydnop20v1.3_annotated.zip", "url": "https://github.com/napulen/haydn_op20_harm/releases/download/v1.3/haydnop20v1.3_annotated.zip", "archive": True, "size": 130954, "md5": "1c65c8da312e1c9dda681d0496bf527f", "sha256": "96986cccebfd37a36cc97a2fc0ebcfbe22d5136e622b21e04ea125d589f5073b", } } _extension = "hrm"
[docs] def read(self, filename: Union[str, Path]) -> Music: """Read a file into a Music object.""" score = music21.converter.parse(filename, format="humdrum") # Get the annotations roman_numerals = list(score.flat.getElementsByClass("RomanNumeral")) annotations = get_annotations(roman_numerals) # Remove the annotations from the original score # (they mess with the python representation) score.remove(roman_numerals, recurse=True) music = from_music21_score(score) music.annotations = annotations return music
def get_annotations( roman_numerals: List[RomanNumeral], resolution=DEFAULT_RESOLUTION ) -> List[Annotation]: """Return music21 RomanNumeral objects as Annotation objects.""" # Convert the list into a dictionary to remove duplicate items roman_numeral_dict = {rn.offset: rn for rn in roman_numerals if rn} annotations = [] for offset, roman_numeral in roman_numeral_dict.items(): time = int(round(float(offset * resolution))) tonicized_key = roman_numeral.secondaryRomanNumeralKey key = tonicized_key if tonicized_key else roman_numeral.key annotation = { "key": key.tonicPitchNameWithCase, "figure": roman_numeral.figure, "chord": roman_numeral.pitchedCommonName, } annotations.append(Annotation(time=time, annotation=annotation)) return annotations