def CheckHumdrumFile(hf: HumdrumFile, results: HumdrumFileTestResults): assert hf.lineCount == results.lineCount assert hf.maxTrack == results.maxTrack assert getTokenDataTypes(hf) == results.tokenDataTypes assert hf.tpq() == results.tpq assert hf.tpq( ) == results.tpq # check it twice, for code coverage of "I already computed that" path if results.fileContentsUnmodified: if results.fileContents is None: assert str(hf) == '' else: assert str(hf) == results.fileContents for lineIdx, line in enumerate(hf.lines()): if results.fileContentsUnmodified: # LATER: keep track of which lines not to check assert line.text == results.lines[lineIdx] assert str(line) == results.lines[ lineIdx] # test HumdrumLine.__str__ assert hf[lineIdx].text == results.lines[ lineIdx] # test HumdrumFile.__getitem__ assert [tok.text for tok in line.tokens()] == results.tokens[lineIdx] assert line.lineNumber == results.lineNumbers[lineIdx] assert line.isExclusiveInterpretation == results.isExclusiveInterpretation[ lineIdx] assert line.isManipulator == results.isManipulator[lineIdx] assert line.tokenCount == len(results.tokens[lineIdx])
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 generateTokenDataTypeChanges(hf: HumdrumFile) -> dict: result = {} currTokenDataTypes: [str] = [] for line in hf.lines(): newTokenDataTypes = [token.dataType.text for token in line.tokens()] if newTokenDataTypes != currTokenDataTypes: result[str(line.lineNumber)] = newTokenDataTypes currTokenDataTypes = newTokenDataTypes return result
def generateSpineInfoChanges(hf: HumdrumFile) -> dict: result = {} currSpineInfos: [str] = [] for line in hf.lines(): newSpineInfos = [token.spineInfo for token in line.tokens()] if newSpineInfos != currSpineInfos: result[str(line.lineNumber)] = newSpineInfos currSpineInfos = newSpineInfos return result
def test_getMergedSpineInfo(): assert HumdrumFile.getMergedSpineInfo(['1'], 0, 0) == '1' #assert getMergedSpineInfo(['1', '2'], 0, 1) == '1 2' assert HumdrumFile.getMergedSpineInfo(['(1)a', '((1)b)a', '((1)b)b', '(2)a', '(2)b', '3'], 1, 1) == '(1)b' assert HumdrumFile.getMergedSpineInfo(['(1)a', '((1)b)a', '((1)b)b', '(2)a', '(2)b', '3'], 0, 2) == '1' assert HumdrumFile.getMergedSpineInfo(['(1)a', '(((1)b)a)a', '(((1)b)a)b', '(((1)b)b)a', '(((1)b)b)b', '(2)a', '(2)b', '3'], 0, 4) == '1' assert HumdrumFile.getMergedSpineInfo(['(1)a', '(((1)b)a)a', '(((1)b)a)b', '(((1)b)b)a', '(((1)b)b)b', '(2)a', '(2)b', '3'], 5, 1) == '2' assert HumdrumFile.getMergedSpineInfo(['(1)a', '((((1)b)a)a)a', '((((1)b)a)a)b', '((((1)b)a)b)a', '((((1)b)a)b)b', '((((1)b)b)a)a', '((((1)b)b)a)b', '((((1)b)b)b)a', '((((1)b)b)b)b', '(2)a', '(2)b', '3'], 0, 8) == '1'
def transferTokens(self, outFile: HumdrumFile, recip: bool): line: HumdrumLine = HumdrumLine() voice: GridVoice = None emptyStr: str = '.' if self.isMeasureSlice: if len(self.parts) > 0: if len(self.parts[0].staves[0].voices) > 0: voice = self.parts[0].staves[0].voices[0] if voice.token is not None: emptyStr = voice.token.text else: emptyStr = '=YYYYYY' else: emptyStr = '=YYYYYY' elif self.isInterpretationSlice: emptyStr = '*' elif self.isLocalLayoutSlice: emptyStr = '!' elif not self.hasSpines: emptyStr = '???' if recip: token: HumdrumToken = None if self.isNoteSlice: token = self._createRecipTokenFromDuration(self.duration) elif self.isClefSlice: token = HumdrumToken('*') emptyStr = '*' elif self.isMeasureSlice: if len(self.parts[0].staves[0]) > 0: voice = self.parts[0].staves[0].voices[0] token = HumdrumToken(voice.token.text) else: token = HumdrumToken('=XXXXX') emptyStr = token.text elif self.isInterpretationSlice: token = HumdrumToken('*') emptyStr = '*' elif self.isGraceSlice: token = HumdrumToken('q') emptyStr = '.' elif self.hasSpines: token = HumdrumToken('55') emptyStr = '!' if token is not None: if self.hasSpines: line.appendToken(token) else: token = None # extract the Tokens from each part/staff for p in range(len(self.parts) - 1, -1, -1): part = self.parts[p] if not self.hasSpines and p != 0: continue for s in range(len(part.staves) - 1, -1, -1): staff = part.staves[s] if not self.hasSpines and s != 0: continue if len(staff.voices) == 0: # 888: fix this later. For now if there are no notes # 888: ... on the staff, add a null token. Fix so that # 888: ... all open voices are given null tokens. line.appendToken(HumdrumToken(emptyStr)) else: for voice in staff.voices: # NOT reversed (voices different from parts/staves) if voice is not None and voice.token is not None: line.appendToken(voice.token) else: line.appendToken(HumdrumToken(emptyStr)) if not self.hasSpines: # Don't add sides to non-spined lines continue maxxcount: int = self.getXmlIdCount(p, s) maxdcount: int = self.getDynamicsCount(p, s) maxvcount: int = self.getVerseCount(p, s) self.transferSidesFromStaff(line, staff, emptyStr, maxxcount, maxdcount, maxvcount) if not self.hasSpines: # Don't add sides to non-spined lines continue maxhcount: int = self.getHarmonyCount(p) maxfcount: int = self.getFiguredBassCount(p) self.transferSidesFromPart(line, part, emptyStr, maxhcount, maxfcount) outFile.appendLine(line)
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 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 test_HumdrumFile_default_init(): f = HumdrumFile() results = HumdrumFileTestResults() CheckHumdrumFile(f, results)
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 test_HumdrumToken_global_param(): hf = HumdrumFile() hf.readString(\ '''**kern *M4/4 =1- !!LO:CL:x=3 *clefG2 4c 4d !!LO:N:vis=1:t=this is a colon::i . 4e !!LO:B:i == *-''') for lineIdx, line in enumerate(hf.lines()): #print('line: {}'.format(line.text)) for tokenIdx, token in enumerate(line.tokens()): #print('line[{}]: {}'.format(tokenIdx, token)) assert tokenIdx == 0 # this file has only one token per line if lineIdx == 0: # **kern CheckHumdrumToken(token, expectedText='**kern', expectedDataType='**kern', expectedTokenType=TOKENTYPE_INTERPRETATION, expectedSpecificType=SPECIFICTYPE_EXINTERP, expectedDuration=-1, ) elif lineIdx == 1: # *M4/4 CheckHumdrumToken(token, expectedText='*M4/4', expectedDataType='**kern', expectedTokenType=TOKENTYPE_INTERPRETATION, expectedSpecificType=SPECIFICTYPE_TIMESIGNATURE, expectedDuration=-1, ) elif lineIdx == 2: # =1- CheckHumdrumToken(token, expectedText='=1-', expectedDataType='**kern', expectedTokenType=TOKENTYPE_BARLINE, expectedSpecificType=SPECIFICTYPE_NOTHINGSPECIFIC, expectedDuration=-1, ) elif lineIdx == 3: # !!LO:CL:x=3 CheckHumdrumToken(token, expectedText='!!LO:CL:x=3', expectedDataType='', expectedTokenType=TOKENTYPE_GLOBALCOMMENT, expectedSpecificType=SPECIFICTYPE_NOTHINGSPECIFIC, expectedDuration=-1, ) elif lineIdx == 4: # *clefG2 CheckHumdrumToken(token, expectedText='*clefG2', expectedDataType='**kern', expectedTokenType=TOKENTYPE_INTERPRETATION, expectedSpecificType=SPECIFICTYPE_CLEF, expectedDuration=-1, ) elif lineIdx == 5: # 4c CheckHumdrumToken(token, expectedText='4c', expectedDataType='**kern', expectedTokenType=TOKENTYPE_DATA, expectedSpecificType=SPECIFICTYPE_NOTE, expectedDuration=1, # one quarter-note ) elif lineIdx == 6: # 4d CheckHumdrumToken(token, expectedText='4d', expectedDataType='**kern', expectedTokenType=TOKENTYPE_DATA, expectedSpecificType=SPECIFICTYPE_NOTE, expectedDuration=1, ) elif lineIdx == 7: # !!LO:N:vis=1:t=this is a colon::i CheckHumdrumToken(token, expectedText='!!LO:N:vis=1:t=this is a colon::i', expectedDataType='', expectedTokenType=TOKENTYPE_GLOBALCOMMENT, expectedSpecificType=SPECIFICTYPE_NOTHINGSPECIFIC, expectedDuration=-1, ) elif lineIdx == 8: # . CheckHumdrumToken(token, expectedText='.', expectedDataType='**kern', expectedTokenType=TOKENTYPE_DATA, expectedSpecificType=SPECIFICTYPE_NULLDATA, expectedDuration=-1, ) elif lineIdx == 9: # 4e CheckHumdrumToken(token, expectedText='4e', expectedDataType='**kern', expectedTokenType=TOKENTYPE_DATA, expectedSpecificType=SPECIFICTYPE_NOTE, expectedDuration=1, ) elif lineIdx == 10: # !!LO:B:i CheckHumdrumToken(token, expectedText='!!LO:B:i', expectedDataType='', expectedTokenType=TOKENTYPE_GLOBALCOMMENT, expectedSpecificType=SPECIFICTYPE_NOTHINGSPECIFIC, expectedDuration=-1, ) elif lineIdx == 11: # == CheckHumdrumToken(token, expectedText='==', expectedDataType='**kern', expectedTokenType=TOKENTYPE_BARLINE, expectedSpecificType=SPECIFICTYPE_NOTHINGSPECIFIC, expectedDuration=-1, ) elif lineIdx == 12: # *- CheckHumdrumToken(token, expectedText='*-', expectedDataType='**kern', expectedTokenType=TOKENTYPE_INTERPRETATION, expectedSpecificType=SPECIFICTYPE_TERMINATE, expectedDuration=-1, ) else: assert False # too many lines in file!
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 generateManipulatorLineNumbers(hf: HumdrumFile) -> list: result = [] for line in hf.lines(): if line.isManipulator: result.append(line.lineNumber) return result
def generateExclusiveInterpretationLineNumbers(hf: HumdrumFile) -> list: result = [] for line in hf.lines(): if line.isExclusiveInterpretation: result.append(line.lineNumber) return result
args = parser.parse_args() folder = args.folder.rstrip('/') # to be pretty if args.recurse: patt = '**/*.krn' else: patt = '*.krn' krnPaths: [Path] = list(Path(folder).glob(patt)) print('numTestFiles =', len(krnPaths)) for krnPath in krnPaths: print("krnPath =", krnPath) try: hf: HumdrumFile = HumdrumFile(krnPath) except: print("Exception parsing", str(krnPath)) continue resultsDict = dict( fileContentsUnmodified = not hf.fixedUpRecipOnlyToken, tpq = hf.tpq(), exclusiveInterpretationLineNumbers = generateExclusiveInterpretationLineNumbers(hf), manipulatorLineNumbers = generateManipulatorLineNumbers(hf), tokenDataTypeChanges = generateTokenDataTypeChanges(hf), spineInfoChanges = generateSpineInfoChanges(hf) ) if len(resultsDict['exclusiveInterpretationLineNumbers']) > 1: print('**** > 1 exclusiveInterpretation in ', krnPath)
def getTokenDataTypes(hf: HumdrumFile) -> [[str]]: #returns a '**blah' string for every token in every line in the file return [[token.dataType.text for token in line.tokens()] for line in hf.lines()]
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())