Source code for musif.extract.features.core.handler

from os import path
from typing import List

import pandas as pd
from music21 import *
from music21.stream import Measure

from musif.config import Configuration
from musif.extract.basic_modules.scoring.constants import (
    FAMILY_ABBREVIATION,
    NUMBER_OF_FILTERED_PARTS,
    SOUND_ABBREVIATION,
)
from musif.extract.constants import (
    DATA_FAMILY_ABBREVIATION,
    DATA_FILE,
    DATA_MUSESCORE_SCORE,
    DATA_PART,
    DATA_PART_ABBREVIATION,
    DATA_SCORE,
    DATA_SOUND_ABBREVIATION,
)
from musif.extract.features.prefix import (
    get_family_feature,
    get_part_feature,
    get_score_feature,
    get_sound_feature,
)
from musif.musicxml.common import (
    _get_intervals,
    _get_lyrics_in_notes,
    get_notes_and_measures,
)
from musif.musicxml.key import get_key_and_mode, get_name_from_key

from .constants import *


[docs]def update_part_objects( score_data: dict, part_data: dict, cfg: Configuration, part_features: dict ): part = part_data[DATA_PART] ( notes, measures, sounding_measures, notes_and_rests, ) = get_notes_and_measures(part) lyrics = _get_lyrics_in_notes(notes) intervals = _get_intervals(notes) part_data.update( { DATA_NOTES: notes, DATA_LYRICS: lyrics, DATA_SOUNDING_MEASURES: sounding_measures, DATA_MEASURES: measures, DATA_INTERVALS: intervals, DATA_NOTES_AND_RESTS: notes_and_rests, } ) part_features.update( { NUM_NOTES: len(notes), NUM_MEASURES: len(measures), NUM_SOUNDING_MEASURES: len(sounding_measures), } )
[docs]def update_score_objects( score_data: dict, parts_data: List[dict], cfg: Configuration, parts_features: List[dict], score_features: dict, ): score = score_data[DATA_SCORE] score_key, key_name, mode = get_key_and_mode(score) if ( cfg.is_requested_musescore_file() and (score_data[DATA_MUSESCORE_SCORE] is not None) and (not score_data[DATA_MUSESCORE_SCORE].empty) ): tonality_ms3 = score_data[DATA_MUSESCORE_SCORE].globalkey[0] if key_name != tonality_ms3: score_key = key.Key(tonality_ms3) mode, key_name = get_name_from_key(score_key) score_features[FILE_NAME] = path.basename(score_data[DATA_FILE]) num_measures = len(score.parts[0].getElementsByClass(Measure)) score_data.update( { DATA_KEY: score_key, DATA_KEY_NAME: key_name, DATA_MODE: mode, DATA_MEASURES: num_measures, } ) features = {} for i, part in enumerate(parts_features): part[SOUND_ABBREVIATION] = parts_data[i][DATA_SOUND_ABBREVIATION] part[FAMILY_ABBREVIATION] = parts_data[i][DATA_FAMILY_ABBREVIATION] df_parts = pd.DataFrame(parts_features) df_sound = df_parts.groupby(SOUND_ABBREVIATION).aggregate( {NUM_NOTES: "sum", NUM_SOUNDING_MEASURES: "sum"} ) df_family = df_parts.groupby(FAMILY_ABBREVIATION).aggregate( {NUM_NOTES: "sum", NUM_SOUNDING_MEASURES: "sum"} ) df_score = df_parts.aggregate({NUM_NOTES: "sum", NUM_SOUNDING_MEASURES: "sum"}) for part_data, part_features in zip(parts_data, parts_features): part = part_data[DATA_PART_ABBREVIATION] features[get_part_feature(part, NUM_NOTES)] = part_features[NUM_NOTES] features[get_part_feature(part, NUM_SOUNDING_MEASURES)] = part_features[ NUM_SOUNDING_MEASURES ] part_data[get_part_feature(part, NUM_NOTES)] = part_features[NUM_NOTES] part_data[get_part_feature(part, NUM_SOUNDING_MEASURES)] = part_features[ NUM_SOUNDING_MEASURES ] for sound in df_sound.index: notes = df_sound.loc[sound, NUM_NOTES].tolist() sounding_measures = df_sound.loc[sound, NUM_SOUNDING_MEASURES].tolist() sound_parts = score_data[get_sound_feature(sound, NUMBER_OF_FILTERED_PARTS)] notes_mean = notes / sound_parts if sound_parts > 0 else 0 sounding_measures_mean = ( sounding_measures / sound_parts if sound_parts > 0 else 0 ) features[get_sound_feature(sound, NUM_NOTES)] = notes features[get_sound_feature(sound, NOTES_MEAN)] = notes_mean features[get_sound_feature(sound, NUM_SOUNDING_MEASURES)] = sounding_measures features[ get_sound_feature(sound, SOUNDING_MEASURES_MEAN) ] = sounding_measures_mean for family in df_family.index: notes = df_family.loc[family, NUM_NOTES].tolist() sounding_measures = df_family.loc[family, NUM_SOUNDING_MEASURES].tolist() family_parts = score_data[get_family_feature(family, NUMBER_OF_FILTERED_PARTS)] notes_mean = notes / family_parts if family_parts > 0 else 0 sounding_measures_mean = ( sounding_measures / family_parts if family_parts > 0 else 0 ) features[get_family_feature(family, NUM_NOTES)] = notes features[get_family_feature(family, NOTES_MEAN)] = notes_mean features[get_family_feature(family, NUM_SOUNDING_MEASURES)] = df_family.loc[ family, NUM_SOUNDING_MEASURES ].tolist() features[ get_family_feature(family, SOUNDING_MEASURES_MEAN) ] = sounding_measures_mean notes = df_score[NUM_NOTES].tolist() notes_mean = notes / len(parts_data) sounding_measures = df_score[NUM_SOUNDING_MEASURES].tolist() sounding_measures_mean = sounding_measures / len(parts_data) features[get_score_feature(NUM_NOTES)] = notes features[get_score_feature(NOTES_MEAN)] = notes_mean features[get_score_feature(NUM_SOUNDING_MEASURES)] = sounding_measures features[get_score_feature(SOUNDING_MEASURES_MEAN)] = sounding_measures_mean features[NUM_MEASURES] = num_measures score_features.update(features)