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_pivot_alignment(): parncutt = Parncutt() d_corpus = DCorpus(corpus_str=TestConstant.A_MAJ_SCALE_SHORT) parncutt.load_corpus(d_corpus=d_corpus) evaluations = parncutt.evaluate_pivot_alignment(staff="both") # for he in hamming_evaluations: # print(he) assert evaluations[0] > 0, "Undetected pivot alignment costs" assert evaluations[3] == 0, "Bad fish in pivot alignment barrel"
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_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_bl1(): parncutt = Parncutt() parncutt.segment_combiner(method="cost") midi_1 = None handed_digit_1 = '-' midi_2 = 61 handed_digit_2 = '>1' midi_3 = 65 handed_digit_3 = '>3' trigram_node = TrigramNode(midi_1, handed_digit_1, midi_2, handed_digit_2, midi_3, handed_digit_3) cost, costs = parncutt.trigram_node_cost(trigram_node) assert costs['bl1'] == 3, "Bad bl1 cost"
def test_good_rules(): parncutt = Parncutt() parncutt.segment_combiner(method="cost") for id in subcosts: 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=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 # parncutt.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 == 'bl1': # 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_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 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 __init__(self, dactyler=Parncutt(segment_combiner="cost"), corpus="parncutt_published"): super().__init__() self._conn = pymysql.connect(host='127.0.0.1', port=3306, user='******', passwd='', db='didactyl2') self._dactyler = dactyler self._corpus = corpus
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_reentry(): parncutt = Parncutt() # 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) parncutt.load_corpus(d_corpus=d_corpus) reentry_hamming_evals = parncutt.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 = parncutt.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 = parncutt.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 = parncutt.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_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)
def get_model(self, model_name, weights=None): if model_name == 'random': model = Random() elif model_name == 'parncutt': model = Parncutt() elif model_name == 'jacobs': model = Jacobs() elif model_name == 'jarules': model = Jacobs(finger_spans=FINGER_SPANS, ruler=Ruler()) elif model_name == 'jaball': model = Jacobs(finger_spans=BALLIAUW_LARGE_FINGER_SPANS, ruler=ImaginaryBlackKeyRuler()) elif model_name == 'jaSball': model = Jacobs(finger_spans=BALLIAUW_SMALL_FINGER_SPANS, ruler=ImaginaryBlackKeyRuler()) elif model_name == 'jaMball': model = Jacobs(finger_spans=BALLIAUW_MEDIUM_FINGER_SPANS, ruler=ImaginaryBlackKeyRuler()) elif model_name == 'badgerow': # model = Badgerow(finger_spans=FINGER_SPANS, ruler=PhysicalRuler()) # model = Badgerow(finger_spans=BALLIAUW_LARGE_FINGER_SPANS, ruler=ImaginaryBlackKeyRuler()) model = Badgerow() elif model_name == 'badpar': # model = Badgerow(finger_spans=FINGER_SPANS, ruler=PhysicalRuler()) # model = Badgerow(finger_spans=BALLIAUW_FINGER_SPANS, ruler=ImaginaryBlackKeyRuler()) model = Badgerow(finger_spans=FINGER_SPANS) elif model_name == 'balliauw': model = Balliauw() elif model_name == 'badball': model = Badgerow(finger_spans=BALLIAUW_LARGE_FINGER_SPANS, ruler=ImaginaryBlackKeyRuler()) elif model_name == 'badSball': model = Badgerow(finger_spans=BALLIAUW_SMALL_FINGER_SPANS, ruler=ImaginaryBlackKeyRuler()) elif model_name == 'badMball': model = Badgerow(finger_spans=BALLIAUW_MEDIUM_FINGER_SPANS, ruler=ImaginaryBlackKeyRuler()) else: raise Exception("Bad model") if weights: model.init_rule_weights(weights) return model
#!/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)
print("Interpol 1 {} staff{} Section {}.1 Alpha: {}".format( staff, plural, score_index + 1, alpha)) alpha = d_score.nltk_alpha(ids=[16, 17], staff=staff, common_id=3) kappa, pairs = d_score.cohens_kappa(16, 17, staff=staff, common_id=3) aggregate_pairs(interpolation2_pairs, pairs) print("Interpol 2 {} staff{} Section {}.1 Kappa: {}".format( staff, plural, score_index + 1, kappa)) print("Interpol 2 {} staff{} Section {}.1 Alpha: {}".format( staff, plural, score_index + 1, alpha)) score_index += 1 print_pairs("Annotation 1 pairs:", annotation_pairs) print_pairs("Interpolation 1 pairs:", interpolation_pairs) print_pairs("Interpolation 2 pairs:", interpolation2_pairs) exit(0) parncutt = Parncutt() d_corpus = DCorpus(paths=phrase_paths) parncutt.load_corpus(d_corpus=d_corpus) jacobs = Jacobs() jacobs.load_corpus(d_corpus=d_corpus) justin = Badgerow() justin.load_corpus(d_corpus=d_corpus) model_years = {'Parncutt': '1997', 'Jacobs': '2001', 'Badgerow': '2019'} models = [parncutt, jacobs, justin] for model in models: model_name = str(type(model)).split('.')[-1] model_name = model_name[0:-2] model_version = model.version() version_str = ".".join(map(str, model_version))
# 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 test_parncutt_edges(): parncutt = Parncutt() d_corpus = DCorpus(corpus_str=TestConstant.ONE_NOTE) parncutt.load_corpus(d_corpus=d_corpus) upper_rh_advice = parncutt.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 = parncutt.advise(staff="both") # both_re = re.compile('^>\d@$') # assert both_re.match(both_advice), "Bad one-note, segregated, both-staff advice" parncutt = Parncutt() d_corpus = DCorpus(corpus_str=TestConstant.ONE_BLACK_NOTE_PER_STAFF) parncutt.load_corpus(d_corpus=d_corpus) upper_advice = parncutt.advise(staff="upper") right_re = re.compile('^>2$') assert right_re.match(upper_advice), "Bad black-note, upper-staff advice" lower_advice = parncutt.advise(staff="lower") left_re = re.compile('^<2$') assert left_re.match(lower_advice), "Bad black-note, upper-staff advice" both_advice = parncutt.advise(staff="both") both_re = re.compile('^>2@<2$') assert both_re.match(both_advice), "Bad black-note, both-staff advice" lower_advice = parncutt.advise(staff="lower", first_digit=3) lower_re = re.compile('^<3$') assert lower_re.match(lower_advice), "Bad preset black-note, both-staff advice" parncutt = Parncutt() d_corpus = DCorpus(corpus_str=TestConstant.TWO_WHITE_NOTES_PER_STAFF) parncutt.load_corpus(d_corpus=d_corpus) upper_advice = parncutt.advise(staff="upper") right_re = re.compile('^>\d\d$') assert right_re.match(upper_advice), "Bad two white-note, upper-staff advice" upper_advice = parncutt.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_distance_metrics(): parncutt = Parncutt() d_corpus = DCorpus(corpus_str=TestConstant.A_MAJ_SCALE_SHORT) parncutt.load_corpus(d_corpus=d_corpus) complete_rh_advice = parncutt.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 = parncutt.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 = parncutt.advise(staff="upper", offset=10, first_digit=1, last_digit=3) short_advice_len = len(rh_advice) assert complete_rh_advice_len - 10 == short_advice_len, "Bad offset for advise() call" ff_re = re.compile('^>1\d+3$') assert ff_re.match(rh_advice), "Bad first and last finger constraints" lh_advice = parncutt.advise(staff="lower") left_re = re.compile('^<\d+$') assert left_re.match(lh_advice), "Bad left-hand, lower-staff advice" combo_advice = parncutt.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 = parncutt.evaluate_strike_distance(method="hamming", staff="both") assert hamming_evaluations[0] > 0, "Undetected Hamming costs" assert hamming_evaluations[3] == 0, "Bad fish in Hamming barrel" natural_evaluations = parncutt.evaluate_strike_distance(method="natural", staff="both") assert natural_evaluations[0] > 0, "Undetected natural costs" assert natural_evaluations[3] == 0, "Bad fish in natural barrel" pivot_evaluations = parncutt.evaluate_strike_distance(method="pivot", staff="both") assert pivot_evaluations[0] > 0, "Undetected pivot costs" assert pivot_evaluations[3] == 0, "Bad fish in pivot barrel"