def test_abc_2part_mono(): d_corpus = DCorpus(corpus_path=BERINGER2_SCALE_CORPUS, as_xml=False) lo, hi = d_corpus.pitch_range() assert lo < hi, "Bad dcorpus pitch range" score_count = d_corpus.score_count() assert score_count == 38, "Bad score count" d_score = d_corpus.d_score_by_title("scales_g_minor_melodic") assert d_score is not None, "Bad score_by_title retrieval" lo, hi = d_score.pitch_range() assert lo < hi, "Bad DScore pitch range" part_count = d_score.part_count() assert part_count == 2, "Bad part count" d_part = d_score.combined_d_part() part_lo, part_hi = d_part.pitch_range() assert part_lo < part_hi, "Bad DPart pitch range" assert part_lo == lo, "Bad low pitch found" assert part_hi == hi, "Bad high pitch found" assert d_part is not None, "Bad DPart retrieval" assert d_part.is_monophonic() is False, "Polyphony not detected" d_upper = d_score.upper_d_part() assert d_upper, "Bad upper DPart" assert d_upper.is_monophonic() is True, "Monophonic upper part not detected" d_lower = d_score.lower_d_part() assert d_lower, "Bad lower DPart" # lower_stream = d_lower.stream() # lower_stream.show('text') assert d_lower.is_monophonic() is True, "Monophonic lower part not detected"
def test_distance_metrics(): hart = Hart() d_corpus = DCorpus(corpus_str=TestConstant.A_MAJ_SCALE) hart.load_corpus(d_corpus=d_corpus) complete_rh_advice = hart.advise(staff="upper") complete_rh_advice_len = len(complete_rh_advice) right_re = re.compile('^>\d+$') assert right_re.match( complete_rh_advice), "Bad right-hand, upper-staff advice" rh_advice = hart.advise(staff="upper", offset=3, first_digit=4) short_advice_len = len(rh_advice) assert complete_rh_advice_len - 3 == short_advice_len, "Bad offset for advise() call" ff_re = re.compile('^>4\d+$') assert ff_re.match(rh_advice), "Bad first finger constraint" rh_advice = hart.advise(staff="upper", offset=10, first_digit=5, last_digit=5) short_advice_len = len(rh_advice) assert complete_rh_advice_len - 10 == short_advice_len, "Bad offset for advise() call" ff_re = re.compile('^>5\d+5$') assert ff_re.match(rh_advice), "Bad first and last finger constraints" lh_advice = hart.advise(staff="lower") left_re = re.compile('^<\d+$') assert left_re.match(lh_advice), "Bad left-hand, lower-staff advice" combo_advice = hart.advise(staff="both") clean_combo_advice = re.sub('[><&]', '', combo_advice) d_score = d_corpus.d_score_by_index(index=0) gold_fingering = d_score.abcdf(index=0) clean_gold_fingering = re.sub('[><&]', '', gold_fingering) combo_re = re.compile('^>\d+@<\d+$') assert combo_re.match(combo_advice), "Bad combined advice" hamming_evaluations = hart.evaluate_strike_distance(method="hamming", staff="both") # for he in hamming_evaluations: # print(he) assert hamming_evaluations[0] > 0, "Undetected Hamming costs" assert hamming_evaluations[1] == 0, "Bad fish in Hamming barrel" natural_evaluations = hart.evaluate_strike_distance(method="natural", staff="both") # for he in natural_evaluations: # print(he) assert natural_evaluations[0] > 0, "Undetected natural costs" assert natural_evaluations[1] == 0, "Bad fish in natural barrel" pivot_evaluations = hart.evaluate_strike_distance(method="pivot", staff="both") # for he in pivot_evaluations: # print(he) assert pivot_evaluations[0] > 0, "Undetected pivot costs" assert pivot_evaluations[1] == 0, "Bad fish in pivot barrel"
def test_cycles(): parncutt = Parncutt() parncutt.segment_combiner(method="cost") d_corpus = DCorpus(corpus_str=TestConstant.FOUR_NOTES) parncutt.load_corpus(d_corpus=d_corpus) suggestions, costs, details = parncutt.generate_advice(staff="upper", cycle=4, k=2) assert len(suggestions) == 2, "No loops in that dog in top ten" # parncutt.report_on_advice(suggestions, costs, details) d_corpus = DCorpus(corpus_str=TestConstant.PARNCUTT_HUMAN_FRAGMENT['B']) parncutt.load_corpus(d_corpus=d_corpus) suggestions, costs, details = parncutt.generate_advice(staff="upper", cycle=4, k=16) assert len(suggestions) == 16, "There should be 16 cyclic fingerings!"
def test_abc2xml_2part_mono(): xml_str = DCorpus.abc2xml(abc_content=TestConstant.B_MINOR_ARPEGGIO) assert xml_str, "Failed abc2xml transform." abc_str = DCorpus.xml2abc(xml_content=xml_str) assert abc_str, "Failed xml2abc transform." print(abc_str) xml_strings = DCorpus.abc2xmlScores(BERINGER2_SCALE_CORPUS) assert len(xml_strings) == 38, "Bad parse of multi-tune file to xml" xml_strings = DCorpus.abc2xmlScores(BERINGER2_SCALE_CORPUS, skip=12, max=4) assert len(xml_strings) == 4, "Bad subset parse of multi-tune file to xml" d_corpus = DCorpus(corpus_str=TestConstant.B_MINOR_ARPEGGIO, as_xml=True) d_score = d_corpus.d_score_by_title("arpeggios_common_b_minor") part_count = d_score.part_count() assert part_count == 2, "Bad part count" lo, hi = d_corpus.pitch_range() assert lo < hi, "Bad dcorpus pitch range" d_part = d_score.combined_d_part() part_lo, part_hi = d_part.pitch_range() assert part_lo < part_hi, "Bad DPart pitch range" assert part_lo == lo, "Bad low pitch found" assert part_hi == hi, "Bad high pitch found" assert d_part is not None, "Bad DPart retrieval" assert d_part.is_monophonic() is False, "Polyphony not detected" d_upper = d_score.upper_d_part() assert d_upper, "Bad upper DPart" assert d_upper.is_monophonic() is True, "Monophonic upper part not detected" d_lower = d_score.lower_d_part() assert d_lower, "Bad lower DPart" # lower_stream = d_lower.stream() # lower_stream.show('text') assert d_lower.is_monophonic() is True, "Monophonic lower part not detected"
def test_four_note_example(self): parncutt = Parncutt(segmenter=ManualDSegmenter(), segment_combiner="cost") # parncutt.segment_combiner(method="cost") d_corpus = DCorpus(corpus_str=TestConstant.FOUR_NOTES) parncutt.load_corpus(d_corpus=d_corpus) suggestions, costs, details = parncutt.generate_advice(staff="upper", k=2) self.assertEqual(len(suggestions), 2, "No loops in that dog in top ten")
def test_fingering_counts(): parncutt = Parncutt(pruning_method="none") parncutt.segment_combiner(method="cost") d_corpus = DCorpus(corpus_str=TestConstant.FOUR_NOTES) parncutt.load_corpus(d_corpus=d_corpus) suggestions, costs, details = parncutt.generate_advice(staff="upper", k=2) assert parncutt.last_segment_pruned_count() == 320, "Bad none pruning on open-ended problem"
def test_hartk(): hart = Hart() d_corpus = DCorpus(corpus_str=TestConstant.A_MAJ_SCALE_SHORT) hart.load_corpus(d_corpus=d_corpus) hart_rh_advice = hart.advise(staff="upper") print(hart_rh_advice) hart_lh_advice = hart.advise(staff="lower") print(hart_lh_advice) hart_k = HartK() hart_k.load_corpus(d_corpus=d_corpus) hart_k.segment_combination_method("cost") suggestions, costs, hds_for_gold_index = hart_k.evaluate_strike_distances( method="hamming", staff="upper", k=20) min_cost = None for i in range(len(suggestions)): print("{0}:::{1}".format(costs[i], suggestions[i])) if suggestions[i] == hart_rh_advice: print("GOT IT!") break for gi in hds_for_gold_index: print("***" + str(gi) + "***") hd_count = len(hds_for_gold_index[gi]) print("HD count for GI {0} = {1}".format(gi, hd_count)) for hdi in range(hd_count): if hds_for_gold_index[gi][hdi] == 0: print("GOT A ZERO HAMMING DISTANCE")
def test_good_rules(): jake = Jacobs() jake.segment_combiner(method="cost") for id in subcosts: d_corpus = DCorpus( corpus_str=TestConstant.PARNCUTT_HUMAN_FRAGMENT[id]) jake.load_corpus(d_corpus=d_corpus) if id == 'B': suggestions, costs, details = jake.generate_advice( staff="upper", cycle=4, k=20) else: suggestions, costs, details = jake.generate_advice( staff="upper", last_digit=last_digit[id], k=30) details_for_sugg = dict() for i in range(len(details)): details_for_sugg[suggestions[i]] = details[i][ 0] # 0 index because we only have one segment jake.report_on_advice(suggestions, costs, details) for gold_sugg in subcosts[id]: assert gold_sugg in details_for_sugg, \ "Missing suggestion {0} in {1}".format(gold_sugg, id) for rule in subcosts[id][gold_sugg]: if rule == '345': continue gold_cost = subcosts[id][gold_sugg][rule] cost = details_for_sugg[gold_sugg][rule] assert cost == gold_cost, \ "Bad {0} cost for {1} in {2}: {3} should be {4}".format(rule, gold_sugg, id, cost, gold_cost)
def test_sayegh_edges(): sayegh = Sayegh() sayegh.recall(pickle_path=SayeghTest.PICKLE_PATH) d_corpus = DCorpus(corpus_str=TestConstant.ONE_NOTE) sayegh.load_corpus(d_corpus=d_corpus) upper_rh_advice = sayegh.advise(staff="upper") right_re = re.compile('^>\d$') assert right_re.match( upper_rh_advice), "Bad one-note, right-hand, upper-staff advice" # both_advice = sayegh.advise(staff="both") # both_re = re.compile('^>\d@$') # assert both_re.match(both_advice), "Bad one-note, segregated, both-staff advice" sayegh = Sayegh() sayegh.recall(pickle_path=SayeghTest.PICKLE_PATH) d_corpus = DCorpus(corpus_str=TestConstant.ONE_BLACK_NOTE_PER_STAFF) sayegh.load_corpus(d_corpus=d_corpus) upper_advice = sayegh.advise(staff="upper") right_re = re.compile('^>2$') assert right_re.match( upper_advice), "Bad black-note, upper-staff advice" lower_advice = sayegh.advise(staff="lower") left_re = re.compile('^<2$') assert left_re.match( lower_advice), "Bad black-note, upper-staff advice" both_advice = sayegh.advise(staff="both") both_re = re.compile('^>2@<2$') assert both_re.match(both_advice), "Bad black-note, both-staff advice" lower_advice = sayegh.advise(staff="lower", first_digit=3) lower_re = re.compile('^<3$') assert lower_re.match( lower_advice), "Bad preset black-note, lower-staff advice" sayegh = Sayegh() sayegh.recall(pickle_path=SayeghTest.PICKLE_PATH) d_corpus = DCorpus(corpus_str=TestConstant.TWO_WHITE_NOTES_PER_STAFF) sayegh.load_corpus(d_corpus=d_corpus) upper_advice = sayegh.advise(staff="upper") right_re = re.compile('^>\d\d$') assert right_re.match( upper_advice), "Bad two white-note, upper-staff advice" upper_advice = sayegh.advise(staff="upper", first_digit=3, last_digit=2) right_re = re.compile('^>32$') assert right_re.match( upper_advice), "Bad preset two white-note, upper-staff advice"
def test_append_dir(): d_corpus = DCorpus() d_corpus.append_dir(corpus_dir=TestConstant.BERINGER2_ANNOTATED_ARPEGGIO_DIR) # d_corpus.append_dir(corpus_dir=TestConstant.BERINGER2_ANNOTATED_SCALE_DIR) d_corpus.append_dir(corpus_dir=TestConstant.BERINGER2_ANNOTATED_BROKEN_CHORD_DIR) score_count = d_corpus.score_count() assert score_count > 48, "Bad score count" for i in range(score_count): d_score = d_corpus.d_score_by_index(i) assert d_score.title() is not None, "Missing title at {0}".format(i) assert d_score.is_fully_annotated(indices=[0]), "Missing annotation in {}".format(d_score.title())
def test_pivot_alignment(): hart = Hart() d_corpus = DCorpus(corpus_str=TestConstant.A_MAJ_SCALE_SHORT) hart.load_corpus(d_corpus=d_corpus) evaluations = hart.evaluate_pivot_alignment(staff="both") # for ev in evaluations: # print(ev) assert evaluations[0] > 0, "Undetected pivot alignment costs" assert evaluations[1] == 0, "Bad fish in pivot alignment barrel"
def test_malody(self): model = Parncutt(segmenter=ManualDSegmenter(), segment_combiner="cost") d_corpus = DCorpus(paths=["/Users/dave/malody.abcd"]) model.load_corpus(d_corpus=d_corpus) advice = model.advise() print(advice) # Gold-standard embedded in input file. hamming_dists = model.evaluate_strike_distance() print(hamming_dists)
def test_jake(): jake = Jacobs() d_corpus = DCorpus(corpus_str=TestConstant.ONE_NOTE) jake.load_corpus(d_corpus=d_corpus) upper_rh_advice = jake.advise(staff="upper") right_re = re.compile('^>\d$') assert right_re.match( upper_rh_advice), "Bad one-note, right-hand, upper-staff advice" # both_advice = jake.advise(staff="both") # both_re = re.compile('^>\d@$') # assert both_re.match(both_advice), "Bad one-note, segregated, both-staff advice" jake = Jacobs() d_corpus = DCorpus(corpus_str=TestConstant.ONE_BLACK_NOTE_PER_STAFF) jake.load_corpus(d_corpus=d_corpus) upper_advice = jake.advise(staff="upper") right_re = re.compile('^>2$') assert right_re.match( upper_advice), "Bad black-note, upper-staff advice" lower_advice = jake.advise(staff="lower") left_re = re.compile('^<2$') assert left_re.match( lower_advice), "Bad black-note, upper-staff advice" both_advice = jake.advise(staff="both") both_re = re.compile('^>2@<2$') assert both_re.match(both_advice), "Bad black-note, both-staff advice" lower_advice = jake.advise(staff="lower", first_digit=3) lower_re = re.compile('^<3$') assert lower_re.match( lower_advice), "Bad preset black-note, both-staff advice" jake = Jacobs() d_corpus = DCorpus(corpus_str=TestConstant.TWO_WHITE_NOTES_PER_STAFF) jake.load_corpus(d_corpus=d_corpus) upper_advice = jake.advise(staff="upper") right_re = re.compile('^>\d\d$') assert right_re.match( upper_advice), "Bad two white-note, upper-staff advice" upper_advice = jake.advise(staff="upper", first_digit=2, last_digit=4) right_re = re.compile('^>24$') assert right_re.match( upper_advice), "Bad preset two white-note, upper-staff advice"
def test_pivot_alignment(): jake = Jacobs() d_corpus = DCorpus(corpus_str=TestConstant.A_MAJ_SCALE_SHORT) jake.load_corpus(d_corpus=d_corpus) evaluations = jake.evaluate_pivot_alignment(staff="both") # for he in hamming_evaluations: # print(he) assert evaluations[0] > 0, "Undetected pivot alignment costs" assert evaluations[4] == 0, "Bad fish in pivot alignment barrel"
def __init__(self, *args, **kwargs): super(SayeghTest, self).__init__(*args, **kwargs) if not os.path.isfile(SayeghTest.PICKLE_PATH): sayegh = Sayegh() d_corpus = DCorpus() d_corpus.append_dir( corpus_dir=TestConstant.BERINGER2_ANNOTATED_ARPEGGIO_DIR) d_corpus.append_dir( corpus_dir=TestConstant.BERINGER2_ANNOTATED_SCALE_DIR) d_corpus.append_dir( corpus_dir=TestConstant.BERINGER2_ANNOTATED_BROKEN_CHORD_DIR) sayegh.train(d_corpus, annotation_indices=[0]) sayegh.retain(pickle_path=SayeghTest.PICKLE_PATH)
def test_a_segment_cost(): parncutt = Parncutt(segment_combiner="cost") d_corpus = DCorpus(corpus_str=TestConstant.PARNCUTT_HUMAN_FRAGMENT['A']) parncutt.load_corpus(d_corpus=d_corpus) abcdf = ">24342313" cost, details = parncutt.segment_advice_cost(abcdf) # print("") # print(abcdf) # print("Cost: {0}".format(cost)) # for det in details: # print(det) assert cost == 6, "Bad segment cost calculation"
def test_annotated_corpus(): da_corpus = DCorpus() da_corpus.append_from_db(client_id='695311d7e88d5f79b4945bf45d00cc77', selection_id='21') da_score = da_corpus.d_score_by_index(0) da_title = da_score.title() assert da_title == 'Prelude 2 (BWV 847)', "Bad fetch by index" da_score = da_corpus.d_score_by_title(da_title) assert da_title == da_score.title(), "Bad fetch by title" annotation = da_score.abcd_header() abcdf = annotation.abcdf() finger_re = re.compile('[12345]+') at_re = re.compile('@') assert finger_re.search(abcdf), "Bad abcdf" assert at_re.search(abcdf), "Bad abcdf" upper_abcdf = annotation.upper_abcdf() assert finger_re.search(upper_abcdf), "Bad upper abcdf" assert not at_re.search(upper_abcdf), "Bad upper abcdf" lower_abcdf = annotation.lower_abcdf() assert finger_re.search(lower_abcdf), "Bad upper abcdf" assert not at_re.search(lower_abcdf), "Bad upper abcdf" assert lower_abcdf != upper_abcdf, "Bad split of abcdf" abcdf_by_index = da_score.abcdf(index=0) abcdf_by_id = da_score.abcdf(identifier=1) assert abcdf_by_index == abcdf_by_id, "Bad DSCore::abcdf" upper_abcdf_by_index = da_score.upper_abcdf(index=0) upper_abcdf_by_id = da_score.upper_abcdf(identifier=1) assert upper_abcdf_by_index == upper_abcdf_by_id, "Bad DSCore::upper_abcdf" lower_abcdf_by_index = da_score.lower_abcdf(index=0) lower_abcdf_by_id = da_score.lower_abcdf(identifier=1) assert lower_abcdf_by_index == lower_abcdf_by_id, "Bad DSCore::lower_abcdf"
def test_reentry(): jake = Jacobs() # We cannot use the longer example A_MAJ_SCALE because the gold standard fingering # requires hand repositionings not allowed by the Parncutt model. This reinforces the need # for segmentation and also (maybe) the need for a more inclusive option for Parncutt where # all paths are possible but some are just very expensive, as we have in Sayegh. d_corpus = DCorpus(corpus_str=TestConstant.A_MAJ_SCALE_SHORT) jake.load_corpus(d_corpus=d_corpus) reentry_hamming_evals = jake.evaluate_strike_reentry( method="hamming", staff="upper", gold_indices=[2, 3]) # Note we are not picking Beringer for the real gold standard because Beringer and Parncutt agree # on the fingering for this scale. # for rhe in reentry_hamming_evals: # print("RHE:{0}".format(rhe)) assert reentry_hamming_evals[ 0] > 0, "Undetected upper Hamming reentry costs" assert reentry_hamming_evals[ 1] == 0, "Bad fish in upper-staff Hamming reentry barrel" reentry_hamming_evals = jake.evaluate_strike_reentry( method="hamming", staff="both", gold_indices=[2, 3]) # for rhe in reentry_hamming_evals: # print("RHE:{0}".format(rhe)) assert reentry_hamming_evals[ 0] > 0, "Undetected both-staff Hamming reentry costs" assert reentry_hamming_evals[ 1] == 0, "Bad fish in both-staff Hamming reentry barrel" hamming_score = reentry_hamming_evals[0] reentry_natural_evals = jake.evaluate_strike_reentry( method="natural", staff="both", gold_indices=[2, 3]) # for rne in reentry_natural_evals: # print("RNE:{0}".format(rne)) assert reentry_natural_evals[0] > 0, "Undetected natural reentry costs" assert reentry_natural_evals[ 1] == 0, "Bad fish in natural reentry barrel" natural_score = reentry_natural_evals[0] assert natural_score > hamming_score, "Reentry: Natural <= Hamming" reentry_pivot_evals = jake.evaluate_strike_reentry(method="pivot", staff="both", gold_indices=[2, 3]) # for rpe in reentry_pivot_evals: # print("RPE:{0}".format(rpe)) assert reentry_pivot_evals[0] > 0, "Undetected pivot reentry costs" assert reentry_pivot_evals[1] == 0, "Bad fish in pivot reentry barrel" pivot_score = reentry_pivot_evals[0] assert natural_score < pivot_score, "Reentry: Natural >= Pivot"
def test_training(): sayegh = Sayegh() sayegh.recall(pickle_path=SayeghTest.PICKLE_PATH) # sayegh.demonstrate() d_corpus = DCorpus(corpus_str=TestConstant.A_MAJ_SCALE) sayegh.load_corpus(d_corpus=d_corpus) upper_advice = sayegh.advise(staff="upper") upper_re = re.compile('^>\d+$') assert upper_re.match(upper_advice), "Bad upper advice" lower_advice = sayegh.advise(staff="lower") lower_re = re.compile('^<\d+$') assert lower_re.match(lower_advice), "Bad lower advice" both_advice = sayegh.advise(staff="both") both_re = re.compile('^>\d+@<\d+$') assert both_re.match(both_advice), "Bad complete advice"
def test_solutions(): for id in last_digit: print("") print("Piece {0}".format(id)) print("=======") justin = Badgerow(segment_combiner="cost") d_corpus = DCorpus( corpus_str=TestConstant.PARNCUTT_HUMAN_FRAGMENT[id]) justin.load_corpus(d_corpus=d_corpus) if id == 'B': suggestions, costs, details = justin.generate_advice( staff="upper", cycle=4, k=20) else: suggestions, costs, details = justin.generate_advice( staff="upper", last_digit=last_digit[id], k=20) justin.report_on_advice(suggestions, costs, details)
def test_abc2xml_2part_chords(): p01_path = TestConstant.WTC_CORPUS_DIR + '/prelude01.abc' p09_path = TestConstant.WTC_CORPUS_DIR + '/prelude09.abc' d_corpus = DCorpus(corpus_path=p01_path, as_xml=True) score_count = d_corpus.score_count() assert score_count == 1, "Bad score count" d_corpus.append(corpus_path=p09_path, as_xml=True) assert d_corpus.score_count() == 2, "Bad append" titles = d_corpus.titles() assert len(titles) == 2, "Bad title count" d_score = d_corpus.d_score_by_index(0) assert d_score.title() == 'Prelude 1 (BWV 846)', "Bad title retrieval" part_count = d_score.part_count() assert part_count == 2, "Bad part count" d_part = d_score.combined_d_part() assert d_part is not None, "Bad DPart retrieval" assert d_part.is_monophonic() is False, "Polyphony not detected" d_upper = d_score.upper_d_part() assert d_upper, "Bad upper DPart" assert d_upper.is_monophonic() is False, "Polyphonic upper part not detected" d_lower = d_score.lower_d_part() assert d_lower, "Bad lower DPart" assert d_lower.is_monophonic() is False, "Polyphonic lower part in Prelude 1 not detected" assert d_lower.is_orderly() is False, "Lower part in Prelude 1 is not orderly" orderly_stream = d_lower.orderly_note_stream() # orderly_stream.show('text') orderly_d_part = DPart(music21_stream=orderly_stream) assert orderly_d_part.is_orderly() is True, "orderly_note_stream() or is_orderly() is broken" # Need to check what happens to tied notes d_score = d_corpus.d_score_by_index(1) d_upper = d_score.upper_d_part() disorderly_stream = d_upper.stream() disorderly_d_part = DPart(music21_stream=disorderly_stream) assert disorderly_d_part.is_orderly() is False, "orderly_note_stream() or is_orderly() is broken" disorderly_stream.show('text') orderly_stream = d_upper.orderly_note_stream() orderly_d_part = DPart(music21_stream=orderly_stream) assert orderly_d_part.is_orderly() is True, "orderly_note_stream() or is_orderly() is broken"
def test_reentry(): sayegh = Sayegh() sayegh.recall(pickle_path=SayeghTest.PICKLE_PATH) d_corpus = DCorpus(corpus_str=TestConstant.A_MAJ_SCALE_SHORT) sayegh.load_corpus(d_corpus=d_corpus) reentry_hamming_evals = sayegh.evaluate_strike_reentry( method="hamming", staff="upper", gold_indices=[0, 2]) # for rhe in reentry_hamming_evals: # print("RHE:{0}".format(rhe)) assert reentry_hamming_evals[0] > 0, "Undetected Hamming reentry costs" assert reentry_hamming_evals[ 1] == 0, "Bad fish in Hamming reentry barrel" reentry_hamming_evals = sayegh.evaluate_strike_reentry( method="hamming", staff="both") # for rhe in reentry_hamming_evals: # print("RHE:{0}".format(rhe)) assert reentry_hamming_evals[ 0] > 0, "Undetected Hamming reentry costs (both staves)" assert reentry_hamming_evals[ 2] == 0, "Bad fish in Hamming reentry barrel (both staves)" hamming_score = reentry_hamming_evals[0] reentry_natural_evals = sayegh.evaluate_strike_reentry( method="natural", staff="both") # for rne in reentry_natural_evals: # print("RNE:{0}".format(rne)) assert reentry_natural_evals[ 0] > 0, "Undetected natural reentry costs (both staves)" assert reentry_natural_evals[ 2] == 0, "Bad fish in natural reentry barrel (both staves)" natural_score = reentry_natural_evals[0] assert natural_score > hamming_score, "Reentry: Natural <= Hamming" reentry_pivot_evals = sayegh.evaluate_strike_reentry(method="pivot", staff="both") # for rpe in reentry_pivot_evals: # print("RPE:{0}".format(rpe)) assert reentry_pivot_evals[ 0] > 0, "Undetected pivot reentry costs (both staves)" assert reentry_pivot_evals[ 2] == 0, "Bad fish in pivot reentry barrel (both staves)" pivot_score = reentry_pivot_evals[0] assert natural_score < pivot_score, "Reentry: Natural >= Pivot"
def test_reentry(): hart = Hart() d_corpus = DCorpus(corpus_str=TestConstant.A_MAJ_SCALE_SHORT) hart.load_corpus(d_corpus=d_corpus) reentry_hamming_evals = hart.evaluate_strike_reentry( method="hamming", staff="upper", gold_indices=[0, 1]) for rhe in reentry_hamming_evals: print("RHE:{0}".format(rhe)) assert reentry_hamming_evals[0] > 0, "Undetected Hamming reentry costs" assert reentry_hamming_evals[ 1] == 0, "Bad fish in Hamming reentry barrel" reentry_hamming_evals = hart.evaluate_strike_reentry(method="hamming", staff="both") for rhe in reentry_hamming_evals: print("RHE:{0}".format(rhe)) assert reentry_hamming_evals[0] > 0, "Undetected Hamming reentry costs" assert reentry_hamming_evals[ 1] == 0, "Bad fish in Hamming reentry barrel" hamming_score = reentry_hamming_evals[0] reentry_natural_evals = hart.evaluate_strike_reentry(method="natural", staff="both") for rne in reentry_natural_evals: print("RNE:{0}".format(rne)) assert reentry_natural_evals[0] > 0, "Undetected natural reentry costs" assert reentry_natural_evals[ 1] == 0, "Bad fish in natural reentry barrel" natural_score = reentry_natural_evals[0] assert natural_score > hamming_score, "Reentry: Natural <= Hamming" reentry_pivot_evals = hart.evaluate_strike_reentry(method="pivot", staff="both") for rpe in reentry_pivot_evals: print("RPE:{0}".format(rpe)) assert reentry_pivot_evals[0] > 0, "Undetected pivot reentry costs" assert reentry_pivot_evals[1] == 0, "Bad fish in pivot reentry barrel" pivot_score = reentry_pivot_evals[0] assert natural_score < pivot_score, "Reentry: Natural >= Pivot"
def test_sma_lar(): parncutt = Parncutt() parncutt.segment_combiner(method="cost") for id in sma_lar_sums: d_corpus = DCorpus(corpus_str=TestConstant.PARNCUTT_HUMAN_FRAGMENT[id]) parncutt.load_corpus(d_corpus=d_corpus) if id == 'B': suggestions, costs, details = parncutt.generate_advice(staff="upper", cycle=4, k=20) else: suggestions, costs, details = parncutt.generate_advice(staff="upper", last_digit=last_digit[id], k=20) details_for_sugg = dict() for i in range(len(details)): details_for_sugg[suggestions[i]] = details[i][0] # 0 index because we only have one segment # parncutt.report_on_advice(suggestions, costs, details) for gold_sugg in sma_lar_sums[id]: assert gold_sugg in details_for_sugg,\ "Missing suggestion {0} in {1}".format(gold_sugg, id) sma = details_for_sugg[gold_sugg]['sma'] lar = details_for_sugg[gold_sugg]['lar'] assert sma + lar == sma_lar_sums[id][gold_sugg],\ "Bad sma + lar total for {0} in {1}".format(gold_sugg, id)
#!/usr/bin/env python3 import pprint from pydactyl.dactyler.Parncutt import Parncutt from pydactyl.dcorpus.DCorpus import DCorpus from pydactyl.dcorpus.ManualDSegmenter import ManualDSegmenter model = Parncutt(segmenter=ManualDSegmenter(), segment_combiner="cost") # d_corpus = DCorpus(paths=["/Users/dave/malody.abcd"]) d_corpus = DCorpus(paths=["/tmp/malody.abcd"]) model.load_corpus(d_corpus=d_corpus) advice = model.advise() print("Best advice: {0}".format(advice)) # Gold-standard embedded in input file. hamming_dists = model.evaluate_strike_distance() print("Hamming distance from gold standard: {0}".format(hamming_dists[0])) suggestions, costs, details = model.generate_advice(staff="upper", k=9) print("Ranked advice:\n\t{0}".format("\n\t".join(suggestions))) print("Ranked costs :\n\t{0}".format("\n\t".join(str(x) for x in costs))) # pp = pprint.PrettyPrinter(width=120) # pp.pprint(details)
rows.append(last_row) last_row.append(pairs[key]) grand_total += pairs[key] if not header_done: header.append(other) last_one = one # if pairs[key] > 0 and one != other: # pair_str = " {}:{}".format(key, pairs[key]) # output_str += pair_str print("{} Note total: {}".format(label, grand_total)) print("\n".join( [''.join(['{:>4}'.format(item) for item in row]) for row in rows])) print() d_corpus = DCorpus(paths=interp_paths) d_scores = d_corpus.d_score_list() editor = 2 for staff in ['upper', 'lower', 'both']: plural = '' if staff == 'both': plural = 's' score_index = 0 interpolation_pairs = {} interpolation2_pairs = {} annotation_pairs = {} for d_score in d_scores: d_score.assert_consistent_abcd(staff=staff) all_annot_ids = range(1, 14) alpha = d_score.nltk_alpha(ids=all_annot_ids, staff=staff) print("Annotate ALL ANNOTS {} staff{} Section {}.1 Alpha: {}".format(
def __init__(self): self._dactyler = None self._d_corpus = DCorpus() self._gold = dict() self._gold['upper'] = list() self._gold['lower'] = list()
class DEvalSimple(ABC): def __init__(self): self._dactyler = None self._d_corpus = DCorpus() self._gold = dict() self._gold['upper'] = list() self._gold['lower'] = list() @staticmethod def _max_distance_for_method(method): if method == "natural": # d_max = Constant.MAX_NATURAL_EDIT_DISTANCE # FIXME: desegregated max turns DCPG murky and useless. d_max = 4 elif method == "hamming": d_max = 1 else: raise Exception("Not ready to measure {} gain".format(method)) return d_max @staticmethod def _proximal_gain(test_abcdf, gold_handed_strikers, gold_vote_counts, staff, method="hamming"): testee = DAnnotation.abcdf_to_handed_strike_digits(test_abcdf, staff=staff) d_max = DEvalSimple._max_distance_for_method(method) nugget_index = 0 total_gain = 0 for nugget in gold_handed_strikers: nugget_gain = 0 for i in range(len(testee)): distance = DAnnotation.strike_distance_cost( gold_handed_digit=nugget[i], test_handed_digit=testee[i], method=method) nugget_gain += (d_max - distance) nugget_gain *= gold_vote_counts[nugget_index] nugget_index += 1 total_gain += nugget_gain return total_gain @abstractmethod def load_data(self): return def gold_asts(self, score_index, staff="upper", last_digit=None): score_gold = self._score_gold(score_index=score_index, staff=staff, last_digit=last_digit) asts = list() for abcdf in score_gold: ast = DAnnotation.abcdf_to_ast(abcdf) asts.append(ast) return asts def gold_list_of_handed_strike_lists(self, score_index, staff="upper", last_digit=None): gold_asts = self.gold_asts(score_index, staff=staff, last_digit=last_digit) list_of_strike_lists = list() for gold_ast in gold_asts: nuggets = DAnnotation.ast_to_handed_strike_digits(gold_ast, staff=staff) list_of_strike_lists.append(nuggets) return list_of_strike_lists def gold_clusters(self, score_index, staff="upper", last_digit=None): score_gold = self._score_gold(score_index=score_index, staff=staff, last_digit=last_digit) @staticmethod def krippendorfs_alpha(upper_rh_advice, exercise_upper_gold): fingerings = list(upper_rh_advice) fingerings.pop(0) finger_ints = list(map(int, fingerings)) exercise_upper_gold.append(finger_ints) krip = alpha(reliability_data=exercise_upper_gold, level_of_measurement='interval') exercise_upper_gold.pop() return krip def assert_good_gold(self, staff="upper"): score_count = self._d_corpus.score_count() gold_score_count = len(self._gold[staff]) if score_count != gold_score_count: raise Exception( "Gold count ({0}) does not match score count ({1}).".format( gold_score_count, score_count)) @staticmethod def suggestion_data_by_cost(suggestions, costs, details, cutoff_rank=None): """ Return a dictionary of suggestion data keyed by total costs. :param suggestions: A list of abcDF suggestion strings, ordered by increasing cost. :param costs: A corresponding list of the particular suggestion costs. :param details: A corresponding list of cost details for each suggestion :param cutoff_rank: The final rank (as indicated by sorting by cost) to include in returned results. :return: data_by_cost: A dictionary of lists of dictionaries. """ data_by_cost = dict() sugg_count = 0 last_cost_to_include = None for i in range(len(suggestions)): sugg_count += 1 sugg = suggestions[i] cost = costs[i] detail = details[i] if last_cost_to_include is not None and cost > last_cost_to_include: break if cutoff_rank and cutoff_rank >= sugg_count: last_cost_to_include = cost if cost not in data_by_cost: data_by_cost[cost] = list() data = {'suggestion': sugg, 'details': detail} data_by_cost[cost].append(data) return data_by_cost def score_advice(self, score_index, staff="upper", cycle=None, last_digit=None, k=10): # FIXME: I don't see what this method buys us. generate_advice() should do the right # default thing, no? if cycle: suggestions, costs, details = \ self._dactyler.generate_advice(staff=staff, score_index=score_index, cycle=cycle, k=k) elif last_digit: suggestions, costs, details = \ self._dactyler.generate_advice(staff=staff, score_index=score_index, last_digit=last_digit, k=k) else: suggestions, costs, details = \ self._dactyler.generate_advice(staff=staff, score_index=score_index, k=k) return suggestions, costs, details def _recall_them_all(self, score_index, staff="upper", cycle=None, last_digit=None): k = 25 last_count = None while True: suggestions, costs, details = self.score_advice( score_index=score_index, staff=staff, last_digit=last_digit, cycle=cycle, k=k) suggestion_count = len(suggestions) if suggestion_count == last_count: break last_count = suggestion_count if self._all_gold_found(score_index=score_index, staff=staff, last_digit=last_digit, suggestions=suggestions): break k *= 2 suggestion_count = len(suggestions) if suggestion_count <= 0: raise Exception("Bad suggestion count") suggestions = self._trim_suggestions(suggestions=suggestions, score_index=score_index, last_digit=last_digit, staff=staff) costs = costs[0:len(suggestions)] details = details[0:len(suggestions)] return suggestions, costs, details @staticmethod def estimated_prob_user_happy(suggestion, score_gold): prob = 1 return prob
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. import copy import re import sys from pydactyl.dcorpus.DCorpus import DCorpus, DAnnotation from pydactyl.dactyler.Parncutt import Parncutt from pydactyl.dcorpus.PigIn import PigIn # import scamp # s = scamp.Session() # print(s.get_available_midi_output_devices()) # exit(0) ## pig_eater = PigIn() ## pig_eater.transform() staff = 'upper' k = 5 corpus_dir = "/Users/dave/tb2/didactyl/dd/corpora/pig/PianoFingeringDataset_v1.00/abcd/" d_corpus = DCorpus() d_corpus.append_dir(corpus_dir=corpus_dir, split_header_extension='abcd') model = Parncutt() model.load_corpus(d_corpus=d_corpus) advice = model.generate_advice(staff=staff, score_index=0, k=k) print(advice)
def aggregate_pair_counts(aggregate, pair_counts): for pair in pair_counts: if pair not in aggregate: aggregate[pair] = 0 aggregate[pair] += pair_counts[pair] def total_notes(pair_counts): total = 0 for pair in pair_counts: total += pair_counts[pair] return total da_corpus = DCorpus() da_corpus.append_dir(corpus_dir=INTERP_DIR) interpolated = {"2": ["14", "15"], "3": ["16", "17"]} annotated = [ "1", # Justin "7", # Anne ] one_interp_agg = { 'full': { 'upper': [], 'lower': [], 'both': [] },