def is_black_white_adjacent(one_note, other_note): """ Determine if two fingerings of the input notes are interchangeable because they are adjacent long fingers of the same hand or adjacent fingers on white keys. :param one_note: A fingered middle note of a trigram. :param other_note: Another fingered middle note of the same sequence. :return: True iff they are interchangeable. False otherwise, even if finger used is the same. """ one_pf = PianoFingering.fingering(one_note) other_pf = PianoFingering.fingering(other_note) if one_pf.strike_hand() != other_pf.strike_hand(): return False one_digit = one_pf.strike_digit() other_digit = other_pf.strike_digit() if one_digit == other_digit: return False if (one_digit in (2, 3) and other_digit in (2, 3)) or \ (one_digit in (3, 4) and other_digit in (3, 4)): return True if DEvalFunction.is_white_key(one_note): if (one_digit in (1, 2) and other_digit in (1, 2)) or \ (one_digit in (4, 5) and other_digit in (4, 5)): return True return False
def delta_hamming(one_note, other_note): one_pf = PianoFingering.fingering(one_note) other_pf = PianoFingering.fingering(other_note) if one_pf.strike_digit() != other_pf.strike_digit(): return 1.0 elif one_pf.strike_hand() != other_pf.strike_hand(): return 1.0 return 0.0
def get_best_pseudo_model_scores(d_score, staff="upper"): system_scores = [] for i in range(5): system_scores.append(copy.deepcopy(d_score)) PianoFingering.finger_score(d_score=system_scores[i], staff=staff, id=i + 1) return system_scores
def get_worst_pseudo_model_scores(d_score, staff="upper"): ann_count = d_score.annotation_count() system_scores = [] for i in range(ann_count - 1, ann_count - 6, -1): system_scores.append(copy.deepcopy(d_score)) PianoFingering.finger_score(d_score=system_scores[i], staff=staff, id=i + 1) return system_scores
def get_all_results(self, corpus_name, model, model_name, k=5, staff="upper", full_context=True, version='0000'): if (corpus_name, model_name, version, staff, k, full_context) in self._err_result_cache: cached_err_results = self._err_result_cache[(corpus_name, model_name, version, staff, k, full_context)] cached_pivot_reports = self._pivot_report_cache[(corpus_name, model_name, version, staff, k, full_context)] cached_rank_results = self._rank_result_cache[(corpus_name, model_name, version, staff, k, full_context)] return cached_err_results, cached_pivot_reports, cached_rank_results rank_results = [] err_results = [] pivot_reports = {} da_corpus = self.get_corpus(corpus_name=corpus_name) for da_score in da_corpus.d_score_list(): model.load_score_as_corpus(d_score=da_score) system_scores = self.get_fingered_system_scores(loaded_model=model, model_name=model_name, version=version) title = da_score.title() note_count = da_score.note_count(staff=STAFF) abcdh = da_score.abcd_header() last_annot_id = abcdh.annotation_count() for annot_id in range(1, last_annot_id + 1): annot = abcdh.annotation_by_id(annot_id) comment = annot.comments() mat = re.match(WEIGHT_RE, comment) if mat: weight = int(mat.group(1)) else: weight = 1 human_score = copy.deepcopy(da_score) PianoFingering.finger_score(d_score=human_score, staff=STAFF, id=annot_id) evil = DEvaluation(human_score=human_score, system_scores=system_scores, staff=staff, full_context=full_context) pivot_report_key = (model_name, corpus_name, title) pivot_heading = "{} over {} {} human {}".format(model_name, corpus_name, title, annot_id) pivot_report = evil.pivot_count_report(heading=pivot_heading) if pivot_report_key not in pivot_reports: pivot_reports[pivot_report_key] = [] pivot_reports[pivot_report_key].append(pivot_report) err_result = self._get_err_result_set(evil, corpus_name=corpus_name, model_name=model_name, title=title, note_count=note_count, annot_id=annot_id, weight=weight) err_results.append(err_result) for i in range(k): rank = i + 1 result = self._get_result_set(evil, corpus_name=corpus_name, model_name=model_name, title=title, note_count=note_count, annot_id=annot_id, weight=weight, rank=rank) rank_results.append(result) evil.parameterize() # Reset to defaults. self._err_result_cache[(corpus_name, model_name, version, staff, k, full_context)] = err_results self._pivot_report_cache[(corpus_name, model_name, version, staff, k, full_context)] = pivot_reports self._rank_result_cache[(corpus_name, model_name, version, staff, k, full_context)] = rank_results return err_results, pivot_reports, rank_results
def _get_basic_bigram_info(one_stream, index): if index >= len(one_stream): raise Exception("Stream index is out of range") a_pf = PianoFingering.fingering(one_stream[index]) b_pf = PianoFingering.fingering(one_stream[index + 1]) this_note = one_stream[index] next_note = one_stream[index + 1] this_midi = this_note.pitch.midi next_midi = next_note.pitch.midi direction = next_midi - this_midi return a_pf, b_pf, direction
def delta_adjacent_long(one_note, other_note, epsilon=None): if epsilon is None: epsilon = DEvalFunction.delta_epsilon one_pf = PianoFingering.fingering(one_note) other_pf = PianoFingering.fingering(other_note) if one_pf.strike_hand() != other_pf.strike_hand(): return 1.0 one_digit = one_pf.strike_digit() other_digit = other_pf.strike_digit() if one_digit == other_digit: return 0.0 if (one_digit in (2, 3) and other_digit in (2, 3)) or \ (one_digit in (3, 4) and other_digit in (3, 4)): return 1.0 - epsilon return 1.0
def is_unigram_match(one_note_stream, other_note_stream, index): if len(one_note_stream) != len(other_note_stream): raise Exception("Mismatched note streams") if index < 0: return True if index >= len(one_note_stream): return True one_note = one_note_stream[index] other_note = other_note_stream[index] one_pf = PianoFingering.fingering(one_note) other_pf = PianoFingering.fingering(other_note) if one_pf.strike_hand() != other_pf.strike_hand(): return False if one_pf.strike_digit() == other_pf.strike_digit(): return True return False
def abcdf2pf_list(abcdf): annot = DAnnotation(abcdf=abcdf) sfs = annot.score_fingerings(staff="upper") pfs = [] for sf in sfs: pf = PianoFingering(score_fingering=sf) pfs.append(pf) return pfs
def get_system_scores(self, model_name, d_score, k=5, weights=None): if model_name == 'ideal': return DEvaluation.get_best_pseudo_model_scores(d_score=d_score, staff=STAFF) model = self.get_model(model_name=model_name, weights=weights) advice = model.generate_advice(staff=STAFF, score_index=0, k=k) # print(advice) sys_scores = [] for r in (range(k)): sys_score = copy.deepcopy(d_score) sys_score.remove_annotations() abcdf = advice[0][r] ann = DAnnotation(abcdf=abcdf, authority=model_name) sys_score.annotate(d_annotation=ann) PianoFingering.finger_score(d_score=sys_score, staff=STAFF) sys_scores.append(sys_score) return sys_scores
def get_fingered_system_scores(self, loaded_model: Parncutt, model_name, version=None, score_count=5, weights=None): advice = loaded_model.generate_advice(staff=STAFF, score_index=0, k=score_count) # print(advice) authority = model_name if version: authority = model_name + '_' + version base_score = loaded_model.score_by_index(0) sys_scores = [] for i in range(score_count): sys_score = copy.deepcopy(base_score) sys_score.remove_annotations() abcdf = advice[0][i] ann = DAnnotation(abcdf=abcdf, authority=authority) sys_score.annotate(d_annotation=ann) PianoFingering.finger_score(d_score=sys_score, staff=STAFF) sys_scores.append(sys_score) return sys_scores
def get_err_results(self, corpus_name, model, model_name, staff="upper", full_context=True, version='0000'): if (corpus_name, model_name, version, staff) in self._err_result_cache: cached_err_results = self._err_result_cache[(corpus_name, model_name, version, staff)] return cached_err_results err_results = [] da_corpus = self.get_corpus(corpus_name=corpus_name) for da_score in da_corpus.d_score_list(): model.load_score_as_corpus(d_score=da_score) system_scores = self.get_fingered_system_scores(loaded_model=model, model_name=model_name, version=version) title = da_score.title() note_count = da_score.note_count(staff=STAFF) abcdh = da_score.abcd_header() last_annot_id = abcdh.annotation_count() for annot_id in range(1, last_annot_id + 1): annot = abcdh.annotation_by_id(annot_id) comment = annot.comments() mat = re.match(WEIGHT_RE, comment) if mat: weight = int(mat.group(1)) else: weight = 1 human_score = copy.deepcopy(da_score) PianoFingering.finger_score(d_score=human_score, staff=STAFF, id=annot_id) evil = DEvaluation(human_score=human_score, system_scores=system_scores, staff=staff, full_context=full_context) err_result = self._get_err_result_set(evil, corpus_name=corpus_name, model_name=model_name, title=title, note_count=note_count, annot_id=annot_id, weight=weight) err_results.append(err_result) self._err_result_cache[(corpus_name, model_name, version, staff)] = err_results return err_results
def finger_contour_for_note_stream(stream): contour_string = '' prior_note = None for note in stream: if prior_note: if DEvaluation._is_ascending(one_note=prior_note, next_note=note): contour_string += '/' elif DEvaluation._is_descending(one_note=prior_note, next_note=note): contour_string += "\\" else: contour_string += '-' pf = PianoFingering.fingering(note) contour_string += "{}{}".format(pf.strike_hand(), pf.strike_digit()) prior_note = note return contour_string
def abcdf_for_note_stream(stream): abcdf_str = '' for note in stream: pf = PianoFingering.fingering(note) abcdf_str += "{}{}".format(pf.strike_hand(), pf.strike_digit()) return abcdf_str
annotator_unigrams = corpus_unigrams[corpus_name][score_id][ annotator_id] annotator_trigrams = corpus_trigrams[corpus_name][score_id][ annotator_id] annotator_distance = { 'unigram': 0, 'adjlong': 0, 'trigram': 0, 'nuanced': 0 } is_unigram_match = True is_unigram_proxy_match = True for note_index in range(score_len): czerny_finger = CZERNY_PFS[score_id][note_index] annotated_finger = annotator_unigrams[note_index] annotator_distance['unigram'] += PianoFingering.delta_hamming( czerny_finger, annotated_finger) annotator_distance[ 'adjlong'] += PianoFingering.delta_adjacent_long( czerny_finger, annotated_finger) czerny_trigram = CZERNY_TRIGRAMS[score_id][note_index] annotated_trigram = annotator_trigrams[note_index] annotator_distance['trigram'] += PianoFingering.tau_trigram( czerny_trigram, annotated_trigram) annotator_distance['nuanced'] += PianoFingering.tau_nuanced( czerny_trigram, annotated_trigram) if not PianoFingering.is_unigram_match(annotated_finger, czerny_finger): is_unigram_match = False if not PianoFingering.is_adjacent_long( annotated_finger, czerny_finger): is_unigram_proxy_match = False