def parseData(self, dataString, number=None): '''Create HumdrumFile object from a string, and create a music21 Stream from it. >>> humData = ('**kern\\n*M2/4\\n=1\\n24r\\n24g#\\n24f#\\n24e\\n24c#\\n' + ... '24f\\n24r\\n24dn\\n24e-\\n24gn\\n24e-\\n24dn\\n*-') >>> c = converter.subConverters.HumdrumConverter() >>> s = c.parseData(humData) >>> c.stream.show('text') {0.0} <music21.metadata.Metadata object at 0x7f33545027b8> {0.0} <music21.stream.Part spine_0> {0.0} <music21.stream.Measure 1 offset=0.0> {0.0} <music21.meter.TimeSignature 2/4> {0.0} <music21.note.Rest rest> {0.1667} <music21.note.Note G#> {0.3333} <music21.note.Note F#> {0.5} <music21.note.Note E> {0.6667} <music21.note.Note C#> {0.8333} <music21.note.Note F> {1.0} <music21.note.Rest rest> {1.1667} <music21.note.Note D> {1.3333} <music21.note.Note E-> {1.5} <music21.note.Note G> {1.6667} <music21.note.Note E-> {1.8333} <music21.note.Note D> ''' print("parsing krn string", file=sys.stderr) hf = HumdrumFile() hf.readString(dataString) self.stream = hf.createMusic21Stream() self.humdrumFile = hf return self.stream
def parseFile(self, filePath, number=None): ''' Create HumdrumFile object from a file path, and create a music21 Stream from it. Note that normally, implementing parseData is sufficient, but Humdrum files may be utf-8 or latin-1, so we need to handle various text encodings ourselves. ''' print("parsing krn file", file=sys.stderr) hf = HumdrumFile(filePath) self.stream = hf.createMusic21Stream() self.humdrumFile = hf return self.stream
def runTheFullTest(krnPath: Path): print(f'krn file: {krnPath}') # resultsFileName = krnPath.stem + '.json' # resultsPath = krnPath.parent / resultsFileName # import into HumdrumFile hfb = HumdrumFile(str(krnPath)) assert hfb.isValid # test against known good results # results = HumdrumFileTestResults.fromFiles(str(krnPath), str(resultsPath)) # CheckHumdrumFile(hfb, results) # import HumdrumFile into music21 stream score1 = hfb.createMusic21Stream() assert score1 is not None assert score1.isWellFormedNotation() or not score1.elements # now import via music21's Humdrum parser score2 = m21.converter.parse(krnPath, format='humdrum', forceSource=True) # if score2 is None or not score2.isWellFormedNotation(): # score1.show('musicxml.pdf') assert score2 is not None assert score2.isWellFormedNotation() # score2.show('musicxml.pdf') # compare the two music21 scores with musicdiff print('comparing the two m21 scores') score_lin1 = AnnScore(score1) print('loaded first score') score_lin2 = AnnScore(score2) print('loaded second score') diffList, _cost = Comparison.annotated_scores_diff(score_lin1, score_lin2) print('diffed the two scores:') numDiffs = len(diffList) print(f'\tnumber of differences = {numDiffs}') if numDiffs > 0: print('now we will mark and display the two scores') Visualization.mark_diffs(score1, score2, diffList) print('marked the scores to show differences') Visualization.show_diffs(score1, score2) print('displayed both annotated scores')
def ReadAllTestFilesInFolder(folder: str): krnPaths: [Path] = sorted(list(Path(folder).glob('**/*.krn')), key=str) print('numTestFiles in', folder, ' =', len(krnPaths)) assert len(krnPaths) > 0 numCrashes = 0 crashIdxes = [] for i, krnPath in enumerate(krnPaths): print('krn file {}: {}'.format(i, krnPath)) # use this to skip files in folder (i.e. start with n, which is 0-based) # n = 78 # if i < n: # print(f'\tskipping any files before {n}th file in folder') # continue # # if krnPath.name == 'sonata07-1.krn': # print('hi') resultsFileName = krnPath.stem + '.json' resultsPath = krnPath.parent / resultsFileName # try: if 'tasso-scores' in str(krnPath) and krnPath.name in ( 'Tam2031034a-Vorro_veder_cio_che_Tirsi_avra_fatto--Balsamino_1594.krn', ): print('skipping test because krnFile contains more than one score (not yet supported)') continue hfb = HumdrumFile(str(krnPath)) assert(hfb.isValid) results = HumdrumFileTestResults.fromFiles(str(krnPath), str(resultsPath)) CheckHumdrumFile(hfb, results) # import humdrum into music21 stream score = hfb.createMusic21Stream() assert(score is not None) assert(score.isWellFormedNotation() or not score.elements) # export score back to humdrum (without any makeNotation fixups) # if the score is empty, exporting from it will not produce anything interesting if not score.elements: print('\tskipping export of empty score') continue # The following are worth working on, but I am skipping for now so I can run # all the tests to see where we are. # these are cases that cause extendTokenDuration to fail because it ran out # of room before the next note (music21 has overlapping notes, most likely) if krnPath.name in ( 'test-manipulators.krn', ): print('\tskipping export due to overlapping note durations (caused perhaps by *+)') continue hdw: HumdrumWriter = HumdrumWriter(score) hdw.makeNotation = False hdw.addRecipSpine = krnPath.name == 'test-rhythms.krn' success: bool = True fp = Path(tempfile.gettempdir()) / krnPath.name with open(fp, 'w') as f: success = hdw.write(f) assert(success) # and then try to parse the exported humdrum file # These are cases where export produced an unparseable humdrum file. # The exported test-spine-float.krn is unparseable because it has duration differences # between spines (it gets really confused either during export or maybe during original # import) if krnPath.name in ( 'test-spine-float.krn', ): print('\tskipping parse of export due to *+ issues') continue # this is a weird one... if 'rds-scores' in str(krnPath) and krnPath.name in ( 'R262x_Ive-w33b4p26.krn', 'R443_Ber-w10p321m593-595.krn', ): # rds-scores print('\tskipping parse of export due to missing fields') continue if 'rds-scores' in str(krnPath) and krnPath.name in ( 'R258_Ive-w30p9m55-57.krn', ): print('\tskipping parse of export due to unparseable manipulators (original is even weirder, but parseable)') continue hfb = HumdrumFile(str(fp)) assert(hfb.isValid) score2 = hfb.createMusic21Stream() assert(score2 is not None) assert(score2.isWellFormedNotation())
def runTheDiff(krnPath: Path, results) -> bool: print(f'{krnPath}: ', end='') print(f'{krnPath}: ', end='', file=results) results.flush() # import into HumdrumFile hfb = HumdrumFile(str(krnPath)) if not hfb.isValid: print('HumdrumFile1 parse failure') print('HumdrumFile1 parse failure', file=results) results.flush() return False # import HumdrumFile into music21 stream score1 = hfb.createMusic21Stream() if score1 is None: print('score1 creation failure') print('score1 creation failure', file=results) results.flush() return False if not score1.elements: # empty score is valid result, but assume diff will be exact # (export of empty score fails miserably) print('numDiffs = 0 (empty score1)') print('numDiffs = 0 (empty score1)', file=results) results.flush() return True if not score1.isWellFormedNotation(): print('score1 not well formed') print('score1 not well formed', file=results) results.flush() return False # export score back to humdrum (without any makeNotation fixups) hdw: HumdrumWriter = HumdrumWriter(score1) hdw.makeNotation = False hdw.addRecipSpine = krnPath.name == 'test-rhythms.krn' # hdw.expandTremolos = False success: bool = True fp = Path(tempfile.gettempdir()) / krnPath.name with open(fp, 'w', encoding='utf-8') as f: success = hdw.write(f) if not success: print('export failed') print('export failed', file=results) results.flush() return False # and then try to parse the exported humdrum file hfb2 = HumdrumFile(str(fp)) if not hfb2.isValid: print('HumdrumFile2 parse failure') print('HumdrumFile2 parse failure', file=results) results.flush() return False score2 = hfb2.createMusic21Stream() if score2 is None: print('score2 creation failure') print('score2 creation failure', file=results) results.flush() return False if not score2.elements: print('score2 was empty') print('score2 was empty', file=results) results.flush() return False # empty score2 is bad, because score1 was not empty if not score2.isWellFormedNotation(): print('score2 not well formed') print('score2 not well formed', file=results) results.flush() return False # use music-score-diff to compare the two music21 scores, # and return whether or not they were identical annotatedScore1 = AnnScore(score1, DetailLevel.AllObjectsWithStyle) annotatedScore2 = AnnScore(score2, DetailLevel.AllObjectsWithStyle) op_list, _cost = Comparison.annotated_scores_diff(annotatedScore1, annotatedScore2) numDiffs = len(op_list) print(f'numDiffs = {numDiffs}') print(f'numDiffs = {numDiffs}', file=results) results.flush() if numDiffs > 0: summ: str = '\t' + oplistSummary(op_list, score1, score2) print(summ) print(summ, file=results) results.flush() return False return True
def runTheDiff(krnPath: Path, results) -> bool: print(f'{krnPath}: ', end='') print(f'{krnPath}: ', end='', file=results) results.flush() # import into HumdrumFile try: hfb = HumdrumFile(str(krnPath)) if not hfb.isValid: print('HumdrumFile1 parse failure') print('HumdrumFile1 parse failure', file=results) results.flush() return False except KeyboardInterrupt: sys.exit(0) except: print('HumdrumFile1 parse crash') print('HumdrumFile1 parse crash', file=results) results.flush() return False # import HumdrumFile into music21 stream try: score1 = hfb.createMusic21Stream() if score1 is None: print('score1 creation failure') print('score1 creation failure', file=results) results.flush() return False except KeyboardInterrupt: sys.exit(0) except: print('score1 creation crash') print('score1 creation crash', file=results) results.flush() return False if not score1.elements: # empty score is valid result, but assume diff will be exact # (export of empty score fails miserably) print('numDiffs = 0 (empty score1)') print('numDiffs = 0 (empty score1)', file=results) results.flush() return True if not score1.isWellFormedNotation(): print('score1 not well formed') print('score1 not well formed', file=results) results.flush() return False # now import via music21's Humdrum parser try: score2 = m21.converter.parse(krnPath, format='humdrum', forceSource=True) if score2 is None: print('score2 creation failure') print('score2 creation failure', file=results) results.flush() return False except KeyboardInterrupt: sys.exit(0) except: print('score2 creation crash') print('score2 creation crash', file=results) results.flush() return False if not score2.elements: print('score2 was empty') print('score2 was empty', file=results) results.flush() return False # empty score2 is bad, because score1 was not empty if not score2.isWellFormedNotation(): print('score2 not well formed') print('score2 not well formed', file=results) results.flush() return False # use music-score-diff to compare the two music21 scores, # and return whether or not they were identical try: annotatedScore1 = AnnScore(score1, DetailLevel.AllObjectsWithStyle) annotatedScore2 = AnnScore(score2, DetailLevel.AllObjectsWithStyle) op_list, _cost = Comparison.annotated_scores_diff( annotatedScore1, annotatedScore2) numDiffs = len(op_list) print(f'numDiffs = {numDiffs}') print(f'numDiffs = {numDiffs}', file=results) results.flush() if numDiffs > 0: summ: str = '\t' + oplistSummary(op_list, score1, score2) print(summ) print(summ, file=results) results.flush() return False return True except KeyboardInterrupt: sys.exit(0) except: print('musicdiff crashed') print('musicdiff crashed', file=results) results.flush() return False return True
def runTheFullTest(krnPath: Path): print(f'krn file: {krnPath}') # resultsFileName = krnPath.stem + '.json' # resultsPath = krnPath.parent / resultsFileName # import into HumdrumFile hfb = HumdrumFile(str(krnPath)) assert hfb.isValid # test against known good results # results = HumdrumFileTestResults.fromFiles(str(krnPath), str(resultsPath)) # CheckHumdrumFile(hfb, results) # import HumdrumFile into music21 stream score1 = hfb.createMusic21Stream() assert score1 is not None assert score1.isWellFormedNotation() or not score1.elements # export score back to humdrum (without any makeNotation fixups) # if the score is empty, exporting from it will not produce anything interesting if not score1.elements: print('\tskipping export of empty score') return # score1.show('musicxml.pdf') hdw: HumdrumWriter = HumdrumWriter(score1) hdw.makeNotation = False hdw.addRecipSpine = krnPath.name == 'test-rhythms.krn' # hdw.expandTremolos = False success: bool = True fp = Path(tempfile.gettempdir()) / krnPath.name with open(fp, 'w', encoding='utf-8') as f: success = hdw.write(f) # if not success: # score1.show('musicxml.pdf') assert success # and then try to parse the exported humdrum file hfb = HumdrumFile(str(fp)) # if not hfb.isValid: # score1.show('musicxml.pdf') assert hfb.isValid score2 = hfb.createMusic21Stream() # if score2 is None or not score2.isWellFormedNotation(): # score1.show('musicxml.pdf') assert score2 is not None assert score2.isWellFormedNotation() # compare the two music21 scores # first with bbdiff: subprocess.run(['bbdiff', str(krnPath), str(fp)], check=False) # next with music-score-diff: print('comparing the two m21 scores') score_lin1 = AnnScore(score1) print('loaded first score') score_lin2 = AnnScore(score2) print('loaded second score') diffList, _cost = Comparison.annotated_scores_diff(score_lin1, score_lin2) print('diffed the two scores:') numDiffs = len(diffList) print(f'\tnumber of differences = {numDiffs}') if numDiffs > 0: print('now we will mark and display the two scores') Visualization.mark_diffs(score1, score2, diffList) print('marked the scores to show differences') Visualization.show_diffs(score1, score2) print('displayed both annotated scores')
def ReadAllTestFilesInFolder(folder: str): krnPaths: [Path] = sorted(list(Path(folder).glob('**/*.krn')), key=str) print('numTestFiles in', folder, ' =', len(krnPaths)) assert len(krnPaths) > 0 numCrashes = 0 crashIdxes = [] for i, krnPath in enumerate(krnPaths): print('krn file {}: {}'.format(i, krnPath)) # use this to skip files in folder (i.e. start with n, which is 0-based) # n = 78 # if i < n: # print(f'\tskipping any files before {n}th file in folder') # continue # # if krnPath.name == 'sonata07-1.krn': # print('hi') resultsFileName = krnPath.stem + '.json' resultsPath = krnPath.parent / resultsFileName # try: if 'tasso-scores' in str(krnPath) and krnPath.name in ( 'Tam2031034a-Vorro_veder_cio_che_Tirsi_avra_fatto--Balsamino_1594.krn', ): print( 'skipping test because krnFile contains more than one score (not yet supported)' ) continue # if 'rds-scores' in str(krnPath) and krnPath.name in ( # 'R408_Web-w13p1-2m1-12.krn', # ): # print('\tskipping import due to no note/chord/rest at end of tuplet') # continue if 'jrp-scores' in str(krnPath) and krnPath.name in ( 'Agr1001c-Missa_In_myne_zin-Sanctus.krn', 'Agr1001d-Missa_In_myne_zin-Agnus.krn', 'Mar2085-Salve_regina.krn', ): print( 'skipping test because krnFile does not parse (inexpressible duration in tuplet)' ) continue hfb = HumdrumFile(str(krnPath)) assert (hfb.isValid) results = HumdrumFileTestResults.fromFiles(str(krnPath), str(resultsPath)) CheckHumdrumFile(hfb, results) # import humdrum into music21 stream score = hfb.createMusic21Stream() assert (score is not None) assert (score.isWellFormedNotation() or not score.elements) # export score back to humdrum (without any makeNotation fixups) # if the score is empty, exporting from it will not produce anything interesting if not score.elements: print('\tskipping export of empty score') continue # The following are worth working on, but I am skipping for now so I can run # all the tests to see where we are. # these are cases that cause extendTokenDuration to fail because it ran out # of room before the next note (music21 has overlapping notes, most likely) if krnPath.name in ( 'Tam2010724a-Picciola_e_lape_e_fa_col_picciol_morso--Balsamino_1594.krn', # tasso-scores ): print( '\tskipping export due to overlapping note durations (unknown reason)' ) continue if 'rds-scores' in str(krnPath) and krnPath.name in ( 'R319_Fal-w6p178-179h44m1-5.krn'): print( '\tskipping export due to unexported *tremolo causing overlapping note durations' ) continue hdw: HumdrumWriter = HumdrumWriter(score) hdw.makeNotation = False hdw.addRecipSpine = krnPath.name == 'test-rhythms.krn' success: bool = True fp = Path(tempfile.gettempdir()) / krnPath.name with open(fp, 'w') as f: success = hdw.write(f) assert (success) # and then try to parse the exported humdrum file # These are cases where export produced an unparseable humdrum file. # The exported test-spine-float.krn is unparseable because it has duration differences # between spines (it gets really confused either during export or maybe during original # import) if krnPath.name in ('test-spine-float.krn', ): print('\tskipping parse of export due to *+ issues') continue # this is a weird one... if 'rds-scores' in str(krnPath) and krnPath.name in ( 'R262x_Ive-w33b4p26.krn', ): # rds-scores print( '\tskipping parse of export due to two missing instrument abbreviation spines' ) continue if 'tasso-scores' in str(krnPath) and krnPath.name in ( 'Trm0247a-Io_vidi_gia_sotto_lardente_sole--Marenzio_1584.krn', ): print( '\tskipping parse of export due to missing note weirdness (perhaps because of [whole]->[whole-dot)' ) continue if 'rds-scores' in str(krnPath) and krnPath.name in ( 'R258_Ive-w30p9m55-57.krn', ): print( '\tskipping parse of export due to unparseable manipulators (original is even weirder, but parseable)' ) continue if 'jrp-scores' in str(krnPath) and krnPath.name in ( 'Ock1013e-Requiem-Offertory_Domine_Jesu_Christe.krn', ): print( 'skipping parse of export due to unparseable duration in tuplet' ) continue hfb = HumdrumFile(str(fp)) assert (hfb.isValid) score2 = hfb.createMusic21Stream() assert (score2 is not None) assert (score2.isWellFormedNotation())