def evaluate_tabs(all_songs) -> None: """ Evaluate all lab files based on tab parsing and alignment. :param all_songs: All songs in our data set. """ result_csv_path = filehandler.TABLABS_RESULTS_PATH if not path.isfile(result_csv_path): # Results were not calculated yet with open(result_csv_path, 'w') as write_file: for song_key in all_songs: song = all_songs[song_key] for tab_path in song.full_tab_paths: tab_write_path = filehandler.get_full_tab_chord_labs_path( tab_path) if filehandler.file_exists(tab_write_path): likelihood, transposition = filehandler.read_log_likelihood( song_key, tab_write_path) if filehandler.file_exists(tab_write_path): csr, overseg, underseg, seg = evaluate( song.full_ground_truth_chord_labs_path, tab_write_path) write_file.write( '{0};{1};{2};{3};{4};{5};{6};{7};{8}\n'.format( str(song_key), str(song.duration), str( filehandler.get_relative_path( tab_write_path)), str(likelihood), str(transposition), str(csr), str(overseg), str(underseg), str(seg)))
def predict_single_song(song: Song, hmm_parameters: HMMParameters) -> None: """ Estimate chords for each tab matched to the song and export them to a lab file. :param song: Song for which we estimate tab-based chords :param hmm_parameters: Parameters of the trained HMM """ for full_tab_path in song.full_tab_paths: tab_chord_path = filehandler.get_chords_from_tab_filename( full_tab_path) tab_write_path = filehandler.get_full_tab_chord_labs_path( full_tab_path) if not filehandler.file_exists(tab_write_path): log_likelihood, transposition_semitone = \ jump_align(tab_chord_path, song.full_audio_path, tab_write_path, hmm_parameters) if log_likelihood is not None: # We found an alignment, write this to our log-likelihoods file if not tab_write_path.startswith(filehandler.DATA_PATH): print('WRITING ERROR') # Remove start of path tab_write_path = tab_write_path[len(filehandler.DATA_PATH) + 1:] filehandler.write_log_likelihood(song.key, tab_write_path, log_likelihood, transposition_semitone)
def get_expected_best_tab_lab(song: Song) -> str: """ Find the lab file of the expected best tab for this Song (based on log-likelihood returned by Jump Alignment) :param song: Song in our data set """ best_tab_lab, best_tab_quality = '', 0 for tab_path in song.full_tab_paths: tab_write_path = filehandler.get_full_tab_chord_labs_path(tab_path) if filehandler.file_exists(tab_write_path): tab_quality, _ = filehandler.read_log_likelihood( song.key, tab_path) if tab_quality > best_tab_quality: best_tab_lab, best_tab_quality = tab_write_path, tab_quality return best_tab_lab
def export_result_image(song: Song, chords_vocabulary: ChordVocabulary, midi: bool = True, tab: bool = True, audio: str = 'CHF_2017', df: bool = True): """ Export visualisation to a png file. :param song: Song for which we want to export the visualisation :param chords_vocabulary: Chord vocabulary :param midi: Show MIDI files? :param tab: Show Tab files? :param audio: Audio ACE method :param df: Show all DF results? """ if filehandler.file_exists( filehandler.get_lab_visualisation_path(song, audio)): return song.title + " was already visualised for the ACE method " + audio + "." nr_of_samples = int(ceil(song.duration * 100)) alphabet = ChordAlphabet(chords_vocabulary) # Select labs based on parameter setting label_data = [{ 'name': 'Ground truth', 'index': 0, 'lab_path': song.full_ground_truth_chord_labs_path, 'csr': 1.0, 'ovs': 1.0, 'uns': 1.0, 'seg': 1.0 }] i = 1 best_indices = [] # For expected best MIDI and tab if midi: duplicate_midis = filehandler.find_duplicate_midis(song) best_midi_name, best_segmentation = data_fusion.get_expected_best_midi( song) full_midi_paths = song.full_midi_paths full_midi_paths.sort() for full_midi_path in full_midi_paths: midi_name = filehandler.get_file_name_from_full_path( full_midi_path) for segmentation_method in ['bar', 'beat']: full_midi_chords_path = filehandler.get_full_midi_chord_labs_path( midi_name, segmentation_method) if filehandler.file_exists(full_midi_chords_path) \ and midi_name not in duplicate_midis: # Evaluate song csr, ovs, uns, seg = evaluate( song.full_ground_truth_chord_labs_path, full_midi_chords_path) # Save evaluation values to label_data label_data.append({ 'name': 'MIDI ' + midi_name + ' | ' + segmentation_method, 'index': i, 'lab_path': full_midi_chords_path, 'csr': csr, 'ovs': ovs, 'uns': uns, 'seg': seg }) # Check if this is the expected best MIDI & segmentation method for this song if midi_name == best_midi_name and segmentation_method == best_segmentation: best_indices.append(i) i += 1 if tab: best_tab = data_fusion.get_expected_best_tab_lab(song) for tab_counter, full_tab_path in enumerate(song.full_tab_paths, 1): tab_chord_labs_path = filehandler.get_full_tab_chord_labs_path( full_tab_path) if filehandler.file_exists(tab_chord_labs_path): # Evaluate song csr, ovs, uns, seg = evaluate( song.full_ground_truth_chord_labs_path, tab_chord_labs_path) # Save evaluation values to label_data label_data.append({ 'name': 'Tab ' + str(tab_counter), 'index': i, 'lab_path': tab_chord_labs_path, 'csr': csr, 'ovs': ovs, 'uns': uns, 'seg': seg }) if tab_chord_labs_path == best_tab: best_indices.append(i) i += 1 if df: csr, ovs, uns, seg = evaluate( song.full_ground_truth_chord_labs_path, filehandler.get_full_mirex_chord_labs_path(song, audio)) label_data.append({ 'name': audio, 'index': i, 'lab_path': filehandler.get_full_mirex_chord_labs_path(song, audio), 'csr': csr, 'ovs': ovs, 'uns': uns, 'seg': seg }) for selection_name in 'all', 'best': for combination_name in 'rnd', 'mv', 'df': df_lab_path = filehandler.get_data_fusion_path( song.key, combination_name, selection_name, audio) csr, ovs, uns, seg = evaluate( song.full_ground_truth_chord_labs_path, df_lab_path) label_data.append({ 'name': audio + '-' + combination_name.upper() + '-' + selection_name.upper(), 'index': i, 'lab_path': df_lab_path, 'csr': csr, 'ovs': ovs, 'uns': uns, 'seg': seg }) # Fill a numpy array with chord labels for each of the lab files chord_matrix = np.zeros((len(label_data), nr_of_samples), dtype=int) for lab_nr in range(len(label_data)): data_fusion.load_lab_file_into_chord_matrix( label_data[lab_nr]['lab_path'], lab_nr, chord_matrix, alphabet, nr_of_samples) all_chords = [chord_matrix[x] for x in range(len(label_data))] # Find names names = [label_dict['name'] for label_dict in label_data] # Find results results = ['CSR OvS UnS Seg'] for label_dict in label_data[1:]: results.append(' '.join([ str(round(label_dict[measure], 2)).ljust(4, '0') for measure in ['csr', 'ovs', 'uns', 'seg'] ])) # Show result plt1 = _show_chord_sequences(song, all_chords, best_indices, names, results, alphabet) plt1.savefig(filehandler.get_lab_visualisation_path(song, audio), bbox_inches="tight", pad_inches=0) return song.title + " was visualised for the ACE method " + audio + "."
def get_actual_best_tab_lab(song: Song) -> str: best_tab_name, _ = filehandler.get_actual_best_tab_for_song(song.key) return filehandler.get_full_tab_chord_labs_path(best_tab_name)
def data_fuse_song(song: Song, chord_vocabulary: ChordVocabulary): """ Data fuse a song using all combinations of selection and combination methods, write the final labels to .lab files :param song: The song on which we want to apply data fusion :param chord_vocabulary: The chord vocabulary """ # Check if data fusion has already been calculated TODO: make this check more robust if path.isfile( filehandler.get_data_fusion_path(song.key, 'df', 'besttab', 'CHF_2017')): return # Get list of symbolic lab files (all / expected best) # well_aligned_midis = get_well_aligned_midis(song) # all_symbolic_lab_paths = \ # [filehandler.get_full_midi_chord_labs_path(wam, 'bar') for wam in well_aligned_midis] + \ # [filehandler.get_full_midi_chord_labs_path(wam, 'beat') for wam in well_aligned_midis] + \ # [filehandler.get_full_tab_chord_labs_path(t) for t in song.full_tab_paths] # expected_best_symbolic_lab_paths = [] # if well_aligned_midis: # expected_best_symbolic_lab_paths.append( # filehandler.get_full_midi_chord_labs_path(*get_expected_best_midi(song))) # if [filehandler.get_full_tab_chord_labs_path(t) for t in song.full_tab_paths]: # expected_best_symbolic_lab_paths.append( # filehandler.get_full_tab_chord_labs_path(get_expected_best_tab_lab(song))) well_aligned_midis = get_well_aligned_midis(song) all_midi_bar_lab_paths = [ filehandler.get_full_midi_chord_labs_path(wam, 'bar') for wam in well_aligned_midis if filehandler.file_exists( filehandler.get_full_midi_chord_labs_path(wam, 'bar')) ] all_midi_beat_lab_paths = [ filehandler.get_full_midi_chord_labs_path(wam, 'beat') for wam in well_aligned_midis if filehandler.file_exists( filehandler.get_full_midi_chord_labs_path(wam, 'beat')) ] all_midi_lab_paths = all_midi_bar_lab_paths + all_midi_beat_lab_paths all_tab_lab_paths = [ filehandler.get_full_tab_chord_labs_path(t) for t in song.full_tab_paths if filehandler.file_exists(filehandler.get_full_tab_chord_labs_path(t)) ] all_audio_lab_paths = { **song.full_mirex_chord_lab_paths, **{ 'CHF_2017': song.full_chordify_chord_labs_path } } # expected_best_symbolic_lab_paths = [] # if well_aligned_midis: # expected_best_symbolic_lab_paths.append( # filehandler.get_full_midi_chord_labs_path(*get_expected_best_midi(song))) # if [filehandler.get_full_tab_chord_labs_path(t) for t in song.full_tab_paths]: # expected_best_symbolic_lab_paths.append( # filehandler.get_full_tab_chord_labs_path(get_expected_best_tab_lab(song))) expected_best_midi_lab_paths = [] if well_aligned_midis: expected_best_midi_lab_paths.append( filehandler.get_full_midi_chord_labs_path( *get_expected_best_midi(song))) expected_best_tab_lab_paths = [] if [ filehandler.get_full_tab_chord_labs_path(t) for t in song.full_tab_paths ]: expected_best_tab_lab_paths.append( filehandler.get_full_tab_chord_labs_path( get_expected_best_tab_lab(song))) all_symbolic_lab_paths = all_midi_lab_paths + all_tab_lab_paths expected_best_symbolic_lab_paths = expected_best_midi_lab_paths + expected_best_tab_lab_paths # # Remove non-existing files (e.g. tab files in which too little chords were observed) # all_symbolic_lab_paths = [lab for lab in all_symbolic_lab_paths if filehandler.file_exists(lab)] # expected_best_symbolic_lab_paths = [lab for lab in expected_best_symbolic_lab_paths if filehandler.file_exists(lab)] # Get list of audio lab files # audio_labs = song.full_mirex_chord_lab_paths # audio_labs['CHF_2017'] = song.full_chordify_chord_labs_path # Sample every 10ms, so 100 samples per second song_duration = song.duration nr_of_samples = int(ceil(song_duration * 100)) # Turn the chords list (a list of (key, mode-str, chroma-list) tuples) into an chord_vocabulary (a list of strings) alphabet = ChordAlphabet(chord_vocabulary) selection_dict = { 'all': all_symbolic_lab_paths, 'best': expected_best_symbolic_lab_paths, 'allmidi': all_midi_lab_paths, 'bestmidi': expected_best_midi_lab_paths, 'alltab': all_tab_lab_paths, 'besttab': expected_best_tab_lab_paths } # Iterate over the two types of selection (all / best) # for lab_list_i in [0, 1]: # lab_list = [all_symbolic_lab_paths, expected_best_symbolic_lab_paths, # all_midi_lab_paths, expected_best_midi_lab_paths, # all_tab_lab_paths, expected_best_tab_lab_paths][lab_list_i] # lab_list = [i for i in lab_list if i != ''] # selection_name = ['all', 'best', 'allmidi', 'bestmidi', 'alltab', 'besttab'][lab_list_i] for selection_name, lab_list in selection_dict.items(): lab_list = [i for i in lab_list if i != ''] # Fill a numpy array with chord labels for each of the lab files chord_matrix = np.zeros((len(lab_list) + 1, nr_of_samples), dtype=int) for lab_nr in range(len(lab_list)): load_lab_file_into_chord_matrix(lab_list[lab_nr], lab_nr, chord_matrix, alphabet, nr_of_samples) # Iterate over the audio types: for audio_name, audio_lab in all_audio_lab_paths.items(): if filehandler.file_exists(audio_lab): if any([ not filehandler.file_exists( filehandler.get_data_fusion_path( song.key, df_type_str, selection_name, audio_name)) for df_type_str in ['rnd', 'mv', 'df'] ]): # Add the lab file to our chord matrix load_lab_file_into_chord_matrix(audio_lab, len(lab_list), chord_matrix, alphabet, nr_of_samples) # Iterate over the three combination types; calculate labels and write them: if not filehandler.file_exists( filehandler.get_data_fusion_path( song.key, 'rnd', selection_name, audio_name)): final_labels_random = _random_chord_label_combination( chord_matrix, nr_of_samples) _write_final_labels( final_labels_random, filehandler.get_data_fusion_path( song.key, 'rnd', selection_name, audio_name), alphabet) if not filehandler.file_exists( filehandler.get_data_fusion_path( song.key, 'mv', selection_name, audio_name)): final_labels_majority = _majority_vote_chord_label_combination( chord_matrix, nr_of_samples, alphabet) _write_final_labels( final_labels_majority, filehandler.get_data_fusion_path( song.key, 'mv', selection_name, audio_name), alphabet) if not filehandler.file_exists( filehandler.get_data_fusion_path( song.key, 'df', selection_name, audio_name)): final_labels_data_fusion = _data_fusion_chord_label_combination( chord_matrix, nr_of_samples, alphabet) _write_final_labels( final_labels_data_fusion, filehandler.get_data_fusion_path( song.key, 'df', selection_name, audio_name), alphabet)