Пример #1
0
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])
Пример #2
0
    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
Пример #3
0
 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
Пример #4
0
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'
Пример #8
0
    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)
Пример #9
0
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)
Пример #12
0
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
Пример #13
0
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&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&colon;:i
                CheckHumdrumToken(token,
                                  expectedText='!!LO:N:vis=1:t=this is a colon&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!
Пример #14
0
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
Пример #15
0
def generateManipulatorLineNumbers(hf: HumdrumFile) -> list:
    result = []
    for line in hf.lines():
        if line.isManipulator:
            result.append(line.lineNumber)
    return result
Пример #16
0
def generateExclusiveInterpretationLineNumbers(hf: HumdrumFile) -> list:
    result = []
    for line in hf.lines():
        if line.isExclusiveInterpretation:
            result.append(line.lineNumber)
    return result
Пример #17
0
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)
Пример #18
0
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()]
Пример #19
0
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())