music21.text

#### Next topic

music21.theoryAnalysis.theoryResult

# music21.theoryAnalysis.theoryAnalyzer¶

## Module Introduction¶

Theory Analyzer methods provide easy analysis tools for common music theory type queries regarding a Score (must have parts), such as finding the parallel fifths, locating the passing tones, finding dissonant harmonic intervals, etc. These analysis methods typically operate in the following way:

1. the score is automatically parsed into small bits for analysis (such as Verticality, VoiceLeadingQuartet, etc.)
2. these bits are analyzed for certain attributes, according to analysis methods in voiceLeading
3. the results are stored in the score’s analysisData dictionary, (and also returned as a list depending on which method is called)

## Example Module Uses¶

get voiceLeading objects from a score these methods break the score up into voiceLeading atoms, and return objects of that type. These objects are then useful because they provide easy access to the components within them, and those components (notes, chords, etc.) contain a direct pointer to the original object in the score.

You can then iterate through these objects and access the attributes directly. Here is an example of this that will analyze the root motion in a score:

>>> p = harmony.realizeChordSymbolDurations(p)
>>> averageMotion = 0
>>> l = theoryAnalysis.theoryAnalyzer.getLinearSegments(p,0,2, ['Harmony']) #gets a list of tuples, adjacent chord symbol objects in the score
>>> for x in l:
...    averageMotion+= abs(x.rootInterval().intervalClass) #rootInterval() returns the interval between the roots of the first chordSymbol and second
>>> averageMotion=averageMotion // len(l)
>>> averageMotion #average intervalClass in this piece is about 4
4

get only interesting music theory voiceLeading objects from a score These methods return voiceLeading objects identified by certain methods. For example, they may return all the parallel fifths in the score as voiceLeadingQuartetObjects.

identify music theory objects in score These identify methods were the original purpose of theoryAnalyzer, to identify interesting music theory anomalies in a score, color them, and write specific text regarding them. However, if you find these methods more useful as ‘get’ methods (such as those above), merely run the identify method and access the score’s self.analysisData['dictKey']

special use case: remove passing tones/neighbor tones These methods provide a preliminary implementation for removing passing tones & neighbor tones from a score. As an example, the steps involved in these methods calls include:

1. break the score into Verticalities

2. forms verticalityTriplets out of these vertical slices

3. break each verticalityTriplet into threeNoteLinearSegments

4. check to see if the threeNoteLinearSegment couldBePassingTone() or couldBeNeighborTone() (horizontal analysis)

5. check to see if the Verticality identified as a possible passingTone or neighborTone is dissonant

6. check to see if previous Verticality and next Verticality isdissonant

7. if all checks are true, the passingTone or neighborTone is removed from the score (because the whole point of parsing the score into voiceLeadingObjects was to maintain a direct pointer to the original object in the score.

8. the gap created by the deletion is filled in by extending the duration of the previous note

>>> p = corpus.parse('bwv6.6').measures(0,20)
>>> p.show()
.. image:: images/completebach.*
:width: 500

>>> theoryAnalysis.theoryAnalyzer.removePassingTones(p)
>>> theoryAnalysis.theoryAnalyzer.removeNeighborTones(p)
>>> p.show()
.. image:: images/bachnononharm.*
:width: 500

## Functions¶

adds an attribute “analysisData” to a Stream object if it does not exist.

also adds to any embedded Streams...

>>> p = stream.Part()
>>> s = stream.Score()
>>> s.insert(0, p)
>>> hasattr(p, 'analysisData')
False
>>> hasattr(s, 'analysisData')
False
>>> hasattr(p, 'analysisData')
True
>>> hasattr(s, 'analysisData')
True
>>> 'ResultDict' in p.analysisData
True
music21.theoryAnalysis.theoryAnalyzer.colorResults(score, color='red', typeList=None)

colors the notes of all results found in typeList by calling all identify methods on Theory Analyzer.

music21.theoryAnalysis.theoryAnalyzer.getAllPartNumPairs(score)

Gets a list of all possible pairs of partNumbers: tuples (partNum1, partNum2) where 0 <= partNum1 < partnum2 < numParts

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> part0.append(note.Note('c5'))
>>> part1 = stream.Part()
>>> part1.append(note.Note('g4'))
>>> part2 = stream.Part()
>>> part2.append(note.Note('c4'))
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> sc.insert(part2)
>>> theoryAnalysis.theoryAnalyzer.getAllPartNumPairs(sc)
[(0, 1), (0, 2), (1, 2)]
>>> theoryAnalysis.theoryAnalyzer.getAllPartNumPairs(sc)[0]
(0, 1)
>>> theoryAnalysis.theoryAnalyzer.getAllPartNumPairs(sc)[1]
(0, 2)
>>> theoryAnalysis.theoryAnalyzer.getAllPartNumPairs(sc)[2]
(1, 2)
music21.theoryAnalysis.theoryAnalyzer.getHTMLResultsString(score, typeList=None)

returns string of all results found by calling all identify methods on the TheoryAnalyzer score

music21.theoryAnalysis.theoryAnalyzer.getHarmonicIntervals(score, partNum1, partNum2)

returns a list of all the harmonic intervals (Interval ) occurring between the two specified parts.

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> part0.append(note.Note('e4'))
>>> part0.append(note.Note('d4'))
>>> part1 = stream.Part()
>>> part1.append(note.Note('a3'))
>>> part1.append(note.Note('b3'))
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> len(theoryAnalysis.theoryAnalyzer.getHarmonicIntervals(sc, 0,1))
2
>>> theoryAnalysis.theoryAnalyzer.getHarmonicIntervals(sc, 0,1)[0].name
'P5'
>>> theoryAnalysis.theoryAnalyzer.getHarmonicIntervals(sc, 0,1)[1].name
'm3'
music21.theoryAnalysis.theoryAnalyzer.getKeyAtMeasure(score, measureNumber)

uses keyMeasureMap to return music21 key object. If keyMeasureMap not specified, returns key analysis of theory score as a whole.

>>> from music21.theoryAnalysis import *
>>> s = stream.Score()
>>> theoryAnalysis.theoryAnalyzer.setKeyMeasureMap(s, {1:'C', 2:'G', 4:'a', 7:'C'})
>>> theoryAnalysis.theoryAnalyzer.getKeyAtMeasure(s, 3)
<music21.key.Key of G major>
>>> theoryAnalysis.theoryAnalyzer.getKeyAtMeasure(s, 5)
<music21.key.Key of a minor>
>>> sc = corpus.parse('bach/bwv66.6')
>>> theoryAnalysis.theoryAnalyzer.getKeyAtMeasure(sc, 5)
<music21.key.Key of f# minor>
music21.theoryAnalysis.theoryAnalyzer.getKeyMeasureMap(score)

returns the keymeasuremap in the score, if present. returns None otherwise

music21.theoryAnalysis.theoryAnalyzer.getLinearSegments(score, partNum, lengthLinearSegment, classFilterList=None)

extracts and returns a list of all the linear segments in the piece at the partNum specified, the length of which specified by lengthLinearSegment: Currently Supported: ThreeNoteLinearSegment

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> part0.append(note.Note('c4'))
>>> part0.append(note.Note('g4'))
>>> part0.append(note.Note('c5'))
>>> part0.append(note.Note('c6'))
>>> sc.insert(part0)
>>> len(theoryAnalysis.theoryAnalyzer.getLinearSegments(sc, 0,3, ['Note']))
2
>>> theoryAnalysis.theoryAnalyzer.getLinearSegments(sc, 0,3, ['Note'])
[<music21.voiceLeading.ThreeNoteLinearSegment n1=<music21.note.Note C> n2=<music21.note.Note G> n3=<music21.note.Note C> >,
<music21.voiceLeading.ThreeNoteLinearSegment n1=<music21.note.Note G> n2=<music21.note.Note C> n3=<music21.note.Note C> >]
>>> sc2 = stream.Score()
>>> part1 = stream.Part()
>>> part1.append(chord.Chord(['C','E','G']))
>>> part1.append(chord.Chord(['G','B','D']))
>>> part1.append(chord.Chord(['E','G','C']))
>>> part1.append(chord.Chord(['F','A','C']))
>>> sc2.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.getLinearSegments(sc2, 0,2, ['Chord'])
[<music21.voiceLeading.TwoChordLinearSegment objectList=[<music21.chord.Chord C E G>, <music21.chord.Chord G B D>]  >,
<music21.voiceLeading.TwoChordLinearSegment objectList=[<music21.chord.Chord G B D>, <music21.chord.Chord E G C>]  >,
<music21.voiceLeading.TwoChordLinearSegment objectList=[<music21.chord.Chord E G C>, <music21.chord.Chord F A C>]  >]
>>> len(theoryAnalysis.theoryAnalyzer.getLinearSegments(sc2, 0,2, ['Chord']))
3
>>> for x in theoryAnalysis.theoryAnalyzer.getLinearSegments(sc2, 0,2, ['Chord']):
...   print("%r %r" % (x.rootInterval(), x.bassInterval()))
<music21.interval.ChromaticInterval 7> <music21.interval.ChromaticInterval 2>
<music21.interval.ChromaticInterval -7> <music21.interval.ChromaticInterval -2>
<music21.interval.ChromaticInterval 5> <music21.interval.ChromaticInterval 0>
>>> sc3 = stream.Score()
>>> part2 = stream.Part()
>>> part2.append(harmony.ChordSymbol('D-', quarterLength = 1))
>>> part2.append(harmony.ChordSymbol('C11', quarterLength = 1))
>>> part2.append(harmony.ChordSymbol('C7', quarterLength = 1))
>>> sc3.insert(part2)
>>> len(theoryAnalysis.theoryAnalyzer.getLinearSegments(sc3, 0,2, ['Harmony']))
2
>>> theoryAnalysis.theoryAnalyzer.getLinearSegments(sc3,0,2, ['Harmony'])
[<music21.voiceLeading.TwoChordLinearSegment objectList=[<music21.harmony.ChordSymbol D->, <music21.harmony.ChordSymbol C11>]  >,
<music21.voiceLeading.TwoChordLinearSegment objectList=[<music21.harmony.ChordSymbol C11>, <music21.harmony.ChordSymbol C7>]  >]
music21.theoryAnalysis.theoryAnalyzer.getMelodicIntervals(score, partNum)

returns a list of all the melodic intervals (Interval) in the specified part.

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> part0.append(note.Note('c4'))
>>> part0.append(note.Note('g4'))
>>> part0.append(note.Note('c5'))
>>> sc.insert(part0)
>>> theoryAnalysis.theoryAnalyzer.getMelodicIntervals(sc,0)
[<music21.interval.Interval P5>, <music21.interval.Interval P4>]
>>> theoryAnalysis.theoryAnalyzer.getMelodicIntervals(sc, 0)[0].name
'P5'
>>> theoryAnalysis.theoryAnalyzer.getMelodicIntervals(sc, 0)[1].name
'P4'
music21.theoryAnalysis.theoryAnalyzer.getNeighborTones(score, dictKey=None, partNumToIdentify=None, unaccentedOnly=True)

returns a list of all passing tones present in the score, as identified by hasNeighborTone()

>>> sc = stream.Score()
>>> sc.insert(0, meter.TimeSignature('2/4'))
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('E-3', quarterLength = 1.0))
>>> p0measure1.append(note.Note('C3', quarterLength = 1.0))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('C2', quarterLength = 0.5))
>>> p1measure1.append(note.Note('B1', quarterLength = 0.5))
>>> p1measure1.append(note.Note('C2', quarterLength = 1.0))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.getNeighborTones(sc)
[<music21.note.Note B>]
music21.theoryAnalysis.theoryAnalyzer.getNotes(score, partNum)

returns a list of notes present in the score. If Rests are present, appends None to the list

>>> sc = stream.Score()
>>> p = stream.Part()
>>> p.repeatAppend(note.Note('C'), 3)
>>> p.append(note.Rest(1.0))
>>> sc.append(p)
>>> theoryAnalysis.theoryAnalyzer.getNotes(sc, 0)
[<music21.note.Note C>, <music21.note.Note C>, <music21.note.Note C>, None]
music21.theoryAnalysis.theoryAnalyzer.getParallelFifths(score, partNum1=None, partNum2=None)

Identifies all parallel fifths in score, or only the parallel fifths found between partNum1 and partNum2, and returns these as instances of VoiceLeadingQuartet

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('c5'))
>>> p0measure1.append(note.Note('d5'))
>>> p0measure1.append(note.Note('e5'))
>>> p0measure1.append(note.Note('g5'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('c4'))
>>> p1measure1.append(note.Note('g4'))
>>> p1measure1.append(note.Note('a4'))
>>> p1measure1.append(note.Note('c4'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.getParallelFifths(sc)
>>> len(sc.analysisData['ResultDict']['parallelFifths'])
2
music21.theoryAnalysis.theoryAnalyzer.getParallelOctaves(score, partNum1=None, partNum2=None)

Identifies all parallel octaves in score (if no part numbers specified), or only the parallel octaves found between partNum1 and partNum2, and returns these as instances of VoiceLeadingQuartet

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('c5'))
>>> p0measure1.append(note.Note('g5'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('c4'))
>>> p1measure1.append(note.Note('g4'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.getParallelOctaves(sc)
music21.theoryAnalysis.theoryAnalyzer.getPassingTones(score, dictKey=None, partNumToIdentify=None, unaccentedOnly=True)

returns a list of all passing tones present in the score, as identified by hasPassingTone()

>>> sc = stream.Score()
>>> sc.insert(0, meter.TimeSignature('2/4'))
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('A4', quarterLength = 0.5))
>>> p0measure1.append(note.Note('G4', quarterLength = 0.5))
>>> p0measure1.append(note.Note('F#4', quarterLength = 1.0))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('A2', quarterLength = 1.0))
>>> p1measure1.append(note.Note('D3', quarterLength = 1.0))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.getPassingTones(sc)
[<music21.note.Note G>]
music21.theoryAnalysis.theoryAnalyzer.getResultsString(score, typeList=None)

returns string of all results found by calling all identify methods on the TheoryAnalyzer score

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('c5'))
>>> p0measure1.append(note.Note('d5'))
>>> p0measure1.append(note.Note('e5'))
>>> p0measure1.append(note.Note('g5'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('c4'))
>>> p1measure1.append(note.Note('g4'))
>>> p1measure1.append(note.Note('a4'))
>>> p1measure1.append(note.Note('c4'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.identifyCommonPracticeErrors(sc)
>>> print(theoryAnalysis.theoryAnalyzer.getResultsString(sc))
commonPracticeErrors:
Parallel fifth in measure 1: Part 1 moves from D to E while part 2 moves from G to A
Parallel fifth in measure 1: Part 1 moves from E to G while part 2 moves from A to C
Hidden fifth in measure 1: Part 1 moves from C to D while part 2 moves from C to G
Closing harmony is not in style
music21.theoryAnalysis.theoryAnalyzer.getThreeNoteLinearSegments(score, partNum)

extracts and returns a list of the ThreeNoteLinearSegment objects present in partNum in the score (three note linear segments are made up of ONLY three notes)

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> part0.append(note.Note('c4'))
>>> part0.append(note.Note('g4'))
>>> part0.append(note.Note('c5'))
>>> part0.append(note.Note('c6'))
>>> sc.insert(part0)
>>> theoryAnalysis.theoryAnalyzer.getThreeNoteLinearSegments(sc, 0)
[<music21.voiceLeading.ThreeNoteLinearSegment n1=<music21.note.Note C> n2=<music21.note.Note G> n3=<music21.note.Note C> >,
<music21.voiceLeading.ThreeNoteLinearSegment n1=<music21.note.Note G> n2=<music21.note.Note C> n3=<music21.note.Note C> >]
>>> len(theoryAnalysis.theoryAnalyzer.getThreeNoteLinearSegments(sc, 0))
2
>>> theoryAnalysis.theoryAnalyzer.getThreeNoteLinearSegments(sc, 0)[1]
<music21.voiceLeading.ThreeNoteLinearSegment n1=<music21.note.Note G> n2=<music21.note.Note C> n3=<music21.note.Note C> >
music21.theoryAnalysis.theoryAnalyzer.getVLQs(score, partNum1, partNum2)

extracts and returns a list of the VoiceLeadingQuartet objects present between partNum1 and partNum2 in the score

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> part0.append(note.Note('c4'))
>>> part0.append(note.Note('g4'))
>>> part0.append(note.Note('c5'))
>>> sc.insert(part0)
>>> part1 = stream.Part()
>>> part1.append(note.Note('d4'))
>>> part1.append(note.Note('e4'))
>>> part1.append(note.Note('f5'))
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.getVLQs(sc, 0, 1)
>>> len(theoryAnalysis.theoryAnalyzer.getVLQs(sc, 0, 1))
2
music21.theoryAnalysis.theoryAnalyzer.getVerticalities(score, classFilterList=['Note', 'Chord', 'Harmony', 'Rest'])

returns a list of Verticality objects in by parsing the score. Note that it uses the combined rhythm of the parts to determine what vertical slices to take. Default is to return only objects of type Note, Chord, Harmony, and Rest.

>>> n1 = note.Note('c5')
>>> n1.quarterLength = 4
>>> n2 = note.Note('f4')
>>> n2.quarterLength = 2
>>> n3 = note.Note('g4')
>>> n3.quarterLength = 2
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> part0.append(n1)
>>> part1 = stream.Part()
>>> part1.append(n2)
>>> part1.append(n3)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.getVerticalities(sc)
>>> len(theoryAnalysis.theoryAnalyzer.getVerticalities(sc))
2
>>> sc4 = stream.Score()
>>> part4 = stream.Part()
>>> part4.append(chord.Chord(['A','B','C']))
>>> part4.append(chord.Chord(['A','B','C']))
>>> part4.append(chord.Chord(['A','B','C']))
>>> sc4.insert(part4)
>>> theoryAnalysis.theoryAnalyzer.getVerticalities(sc4)
[<music21.voiceLeading.Verticality contentDict=defaultdict(<... 'list'>, {0: [<music21.chord.Chord A B C>]}) >,
<music21.voiceLeading.Verticality contentDict=defaultdict(<... 'list'>, {0: [<music21.chord.Chord A B C>]}) >,
<music21.voiceLeading.Verticality contentDict=defaultdict(<... 'list'>, {0: [<music21.chord.Chord A B C>]}) >]
>>> sc3 = stream.Score()
>>> p1 = stream.Part()
>>> p1.append(harmony.ChordSymbol('C', quarterLength = 1))
>>> p1.append(harmony.ChordSymbol('D', quarterLength = 3))
>>> p1.append(harmony.ChordSymbol('E7', quarterLength = 4))
>>> sc3.append(p1)
>>> theoryAnalysis.theoryAnalyzer.getVerticalities(sc3)
[<music21.voiceLeading.Verticality contentDict=defaultdict(<... 'list'>, {0: [<music21.harmony.ChordSymbol C>]}) >,
<music21.voiceLeading.Verticality contentDict=defaultdict(<... 'list'>, {0: [<music21.harmony.ChordSymbol D>]}) >,
<music21.voiceLeading.Verticality contentDict=defaultdict(<... 'list'>, {0: [<music21.harmony.ChordSymbol E7>]}) >]
music21.theoryAnalysis.theoryAnalyzer.getVerticalityNTuplets(score, ntupletNum)

extracts and returns a list of the VerticalityNTuplet or the corresponding subclass (currently only supports triplets)

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> part1 = stream.Part()
>>> part0.append(note.Note('c4'))
>>> part0.append(note.Note('g4'))
>>> part0.append(note.Note('c5'))
>>> part0.append(note.Note('e6'))
>>> part1.append(note.Note('e4'))
>>> part1.append(note.Note('f4'))
>>> part1.append(note.Note('a5'))
>>> part1.append(note.Note('d6'))
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> len(theoryAnalysis.theoryAnalyzer.getVerticalityNTuplets(sc, 3))
2
>>> theoryAnalysis.theoryAnalyzer.getVerticalityNTuplets(sc, 3)[1]
music21.theoryAnalysis.theoryAnalyzer.identifyAntiParallelMotion(score, partNum1=None, partNum2=None, color=None)
music21.theoryAnalysis.theoryAnalyzer.identifyClosesIncorrectly(score, partNum1=None, partNum2=None, color=None, dictKey='closesIncorrectly')

Identifies if the piece closes correctly; calls closesIncorrectly()

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('B4'))
>>> p0measure1.append(note.Note('A4'))
>>> p0measure1.append(note.Note('A4'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('G2'))
>>> p1measure1.append(note.Note('F2'))
>>> p1measure1.append(note.Note('G2'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.setKeyMeasureMap(sc,{1:'G'})
>>> theoryAnalysis.theoryAnalyzer.identifyClosesIncorrectly(sc)
>>> len(sc.analysisData['ResultDict']['closesIncorrectly'])
1
>>> sc.analysisData['ResultDict']['closesIncorrectly'][0].text
'Closing harmony is not in style'
music21.theoryAnalysis.theoryAnalyzer.identifyCommonPracticeErrors(score, partNum1=None, partNum2=None, dictKey='commonPracticeErrors')

wrapper method that calls all identify methods for common-practice counterpoint errors, assigning a color identifier to each

ParallelFifths = red, ParallelOctaves = yellow, HiddenFifths = orange, HiddenOctaves = green, ParallelUnisons = blue, ImproperResolutions = purple, improperDissonances = white, DissonantMelodicIntervals = cyan, incorrectOpening = brown, incorrectClosing = gray

music21.theoryAnalysis.theoryAnalyzer.identifyContraryMotion(score, partNum1=None, partNum2=None, color=None)
music21.theoryAnalysis.theoryAnalyzer.identifyDissonantHarmonicIntervals(score, partNum1=None, partNum2=None, color=None, dictKey='dissonantHarmonicIntervals')

Identifies dissonant harmonic intervals (calls isConsonant()) between the two parts (if specified) or between all possible pairs of parts (if not specified) and stores the resulting list of IntervalTheoryResultObject objects in self.resultDict['dissonantHarmonicIntervals']. Optionally, a color attribute may be specified to color all corresponding notes in the score.

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('c'))
>>> p0measure1.append(note.Note('f'))
>>> p0measure1.append(note.Note('b'))
>>> p0measure1.append(note.Note('c'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('b-'))
>>> p1measure1.append(note.Note('c'))
>>> p1measure1.append(note.Note('f'))
>>> p1measure1.append(note.Note('c'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.identifyDissonantHarmonicIntervals(sc)
>>> len(sc.analysisData['ResultDict']['dissonantHarmonicIntervals'])
3
>>> sc.analysisData['ResultDict']['dissonantHarmonicIntervals'][2].text
'Dissonant harmonic interval in measure 1: Augmented Fourth from F to B between part 1 and part 2'
music21.theoryAnalysis.theoryAnalyzer.identifyDissonantMelodicIntervals(score, partNum=None, color=None, dictKey='dissonantMelodicIntervals')

Identifies dissonant melodic intervals (A2, A4, d5, m7, M7) in the part (if specified) or for all parts (if not specified) and stores the resulting list of IntervalTheoryResultObject objects in self.resultDict['dissonantMelodicIntervals']. Optionally, a color attribute may be specified to color all corresponding notes in the score.

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('f3'))
>>> p0measure1.append(note.Note('g#3'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('d2'))
>>> p1measure1.append(note.Note('a-2'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.identifyDissonantMelodicIntervals(sc)
>>> len(sc.analysisData['ResultDict']['dissonantMelodicIntervals'])
2
>>> sc.analysisData['ResultDict']['dissonantMelodicIntervals'][0].text
'Dissonant melodic interval in part 1 measure 1: Augmented Second from F to G#'
>>> sc.analysisData['ResultDict']['dissonantMelodicIntervals'][1].text
'Dissonant melodic interval in part 2 measure 1: Diminished Fifth from D to A-'
music21.theoryAnalysis.theoryAnalyzer.identifyHarmonicIntervals(score, partNum1=None, partNum2=None, color=None, dictKey='harmonicIntervals')

identify all the harmonic intervals in the score between partNum1 or partNum2, or if not specified ALL possible combinations

theoryAnalyzerIntervalTheoryResult created with .value set to the string most commonly used to identify the interval (0 through 9, with A4 and d5)

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('a3'))
>>> p0measure1.append(note.Note('f#3'))
>>> p0measure1.append(note.Note('e3'))
>>> p0measure1.append(note.Note('c4'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('b2'))
>>> p1measure1.append(note.Note('c3'))
>>> p1measure1.append(note.Note('b2'))
>>> p1measure1.append(note.Note('c3'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.identifyHarmonicIntervals(sc)
>>> len(sc.analysisData['ResultDict']['harmonicIntervals'])
4
>>> sc.analysisData['ResultDict']['harmonicIntervals'][1].value
'A4'
>>> sc.analysisData['ResultDict']['harmonicIntervals'][0].text
'harmonic interval between B and A between parts 1 and 2 is a Minor Seventh'
music21.theoryAnalysis.theoryAnalyzer.identifyHiddenFifths(score, partNum1=None, partNum2=None, color=None, dictKey='hiddenFifths')

Identifies hidden fifths (calls hiddenFifth()) between two parts (if specified) or between all possible pairs of parts (if not specified) and stores the resulting list of VLQTheoryResult objects in self.resultDict['hiddenFifths']. Optionally, a color attribute may be specified to color all corresponding notes in the score.

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('e5'))
>>> p0measure1.append(note.Note('d5'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('c5'))
>>> p1measure1.append(note.Note('g4'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.identifyHiddenFifths(sc)
>>> len(sc.analysisData['ResultDict']['hiddenFifths'])
1
>>> sc.analysisData['ResultDict']['hiddenFifths'][0].text
'Hidden fifth in measure 1: Part 1 moves from E to D while part 2 moves from C to G'
music21.theoryAnalysis.theoryAnalyzer.identifyHiddenOctaves(score, partNum1=None, partNum2=None, color=None, dictKey='hiddenOctaves')

Identifies hidden octaves (calls hiddenOctave()) between two parts (if specified) or between all possible pairs of parts (if not specified) and stores the resulting list of VLQTheoryResult objects in score.analysisData['ResultDict']['hiddenOctaves']. Optionally, a color attribute may be specified to color all corresponding notes in the score.

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('e4'))
>>> p0measure1.append(note.Note('f4'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('d3'))
>>> p1measure1.append(note.Note('f3'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.identifyHiddenOctaves(sc)
>>> len(sc.analysisData['ResultDict']['hiddenOctaves'])
1
>>> sc.analysisData['ResultDict']['hiddenOctaves'][0].text
'Hidden octave in measure 1: Part 1 moves from E to F while part 2 moves from D to F'
music21.theoryAnalysis.theoryAnalyzer.identifyImproperDissonantIntervals(score, partNum1=None, partNum2=None, color=None, dictKey='improperDissonantIntervals', unaccentedOnly=True)

Identifies dissonant harmonic intervals that are not passing tones or neighbor tones or don’t resolve correctly

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('a3'))
>>> p0measure1.append(note.Note('f3'))
>>> p0measure1.append(note.Note('e3'))
>>> p0measure1.append(note.Note('c4'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('b2'))
>>> p1measure1.append(note.Note('c3'))
>>> p1measure1.append(note.Note('b2'))
>>> p1measure1.append(note.Note('c3'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.identifyImproperDissonantIntervals(sc)
>>> len(sc.analysisData['ResultDict']['improperDissonantIntervals'])
2
>>> sc.analysisData['ResultDict']['improperDissonantIntervals'][1].text
'Improper dissonant harmonic interval in measure 1: Perfect Fourth from C to F between part 1 and part 2'
music21.theoryAnalysis.theoryAnalyzer.identifyImproperResolutions(score, partNum1=None, partNum2=None, color=None, dictKey='improperResolution', editorialMarkList=[])

Identifies improper resolutions of dissonant intervals (calls improperResolution()) between two parts (if specified) or between all possible pairs of parts (if not specified) and stores the resulting list of VLQTheoryResult objects in self.resultDict['improperResolution']. Optionally, a color attribute may be specified to color all corresponding notes in the score.

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('f#4'))
>>> p0measure1.append(note.Note('a4'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('C3'))
>>> p1measure1.append(note.Note('B2'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.identifyImproperResolutions(sc)
>>> len(sc.analysisData['ResultDict']['improperResolution'])
1
>>> sc.analysisData['ResultDict']['improperResolution'][0].text
'Improper resolution of Augmented Fourth in measure 1: Part 1 moves from F# to A while part 2 moves from C to B'
music21.theoryAnalysis.theoryAnalyzer.identifyInwardContraryMotion(score, partNum1=None, partNum2=None, color=None)
music21.theoryAnalysis.theoryAnalyzer.identifyLeapNotSetWithStep(score, partNum1=None, partNum2=None, color=None, dictKey='LeapNotSetWithStep')

Identifies a leap/skip in one voice not set with a step in the other voice (calls leapNotSetWithStep()) between two parts (if specified) or between all possible pairs of parts (if not specified) and stores the resulting list of VLQTheoryResult objects in self.resultDict['leapNotSetWithStep']. Optionally, a color attribute may be specified to color all corresponding notes in the score.

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('C4'))
>>> p0measure1.append(note.Note('G3'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('A2'))
>>> p1measure1.append(note.Note('D2'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.identifyLeapNotSetWithStep(sc)
>>> len(sc.analysisData['ResultDict']['LeapNotSetWithStep'])
1
>>> sc.analysisData['ResultDict']['LeapNotSetWithStep'][0].text
'Leap not set with step in measure 1: Part 1 moves from C to G while part 2 moves from A to D'
music21.theoryAnalysis.theoryAnalyzer.identifyMotionType(score, partNum1=None, partNum2=None, color=None, dictKey='motionType')

Identifies the motion types in the score by analyzing each voice leading quartet between partNum1 and partNum2, or all possible voiceLeadingQuartets if not specified

VLQTheoryResult by calling motionType() Possible values for VLQTheoryResult are ‘Oblique’, ‘Parallel’, ‘Similar’, ‘Contrary’, ‘Anti-Parallel’, ‘No Motion’

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('a3'))
>>> p0measure1.append(note.Note('f#3'))
>>> p0measure1.append(note.Note('e3'))
>>> p0measure1.append(note.Note('c4'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('b2'))
>>> p1measure1.append(note.Note('c3'))
>>> p1measure1.append(note.Note('b2'))
>>> p1measure1.append(note.Note('c3'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.identifyMotionType(sc)
>>> len(sc.analysisData['ResultDict']['motionType'])
3
>>> sc.analysisData['ResultDict']['motionType'][1].value
'Similar'
>>> sc.analysisData['ResultDict']['motionType'][1].text
'Similar Motion in measure 1: Part 1 moves from F# to E while part 2 moves from C to B'
music21.theoryAnalysis.theoryAnalyzer.identifyNeighborTones(score, partNumToIdentify=None, color=None, dictKey=None, unaccentedOnly=True, editorialDictKey='isNeighborTone', editorialValue=True)

Identifies the neighbor tones in the piece by looking at the vertical and horizontal cross-sections. Optionally specify unaccentedOnly to identify only unaccented neighbor tones (neighbor tones on weak beats). unaccentedOnly by default set to True

>>> sc = stream.Score()
>>> sc.insert(0, meter.TimeSignature('2/4'))
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('E-3', quarterLength = 1.0))
>>> p0measure1.append(note.Note('C3', quarterLength = 1.0))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('C2', quarterLength = 0.5))
>>> p1measure1.append(note.Note('B1', quarterLength = 0.5))
>>> p1measure1.append(note.Note('C2', quarterLength = 1.0))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.identifyNeighborTones(sc)
>>> len(sc.analysisData['ResultDict']['unaccentedNeighborTones'])
1
>>> sc.analysisData['ResultDict']['unaccentedNeighborTones'][0].text
'B identified as a neighbor tone in part 2'
music21.theoryAnalysis.theoryAnalyzer.identifyObliqueMotion(score, partNum1=None, partNum2=None, color=None)
music21.theoryAnalysis.theoryAnalyzer.identifyOpensIncorrectly(score, partNum1=None, partNum2=None, color=None, dictKey='opensIncorrectly')

Identifies if the piece opens correctly; calls opensIncorrectly()

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('C#4'))
>>> p0measure1.append(note.Note('G3'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('A2'))
>>> p1measure1.append(note.Note('D2'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.identifyOpensIncorrectly(sc)
>>> len(sc.analysisData['ResultDict']['opensIncorrectly'])
1
>>> sc.analysisData['ResultDict']['opensIncorrectly'][0].text
'Opening harmony is not in style'
music21.theoryAnalysis.theoryAnalyzer.identifyOutwardContraryMotion(score, partNum1=None, partNum2=None, color=None)
music21.theoryAnalysis.theoryAnalyzer.identifyParallelFifths(score, partNum1=None, partNum2=None, color=None, dictKey='parallelFifths')

Identifies parallel fifths (calls parallelFifth()) between two parts (if specified) or between all possible pairs of parts (if not specified) and stores the resulting list of VLQTheoryResult objects in score.analysisData['ResultDict']['parallelFifths']. Optionally, a color attribute may be specified to color all corresponding notes in the score.

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('c5'))
>>> p0measure1.append(note.Note('d5'))
>>> p0measure1.append(note.Note('e5'))
>>> p0measure1.append(note.Note('g5'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('c4'))
>>> p1measure1.append(note.Note('g4'))
>>> p1measure1.append(note.Note('a4'))
>>> p1measure1.append(note.Note('c4'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.identifyParallelFifths(sc)
>>> len(sc.analysisData['ResultDict']['parallelFifths'])
2
>>> sc.analysisData['ResultDict']['parallelFifths'][0].text
'Parallel fifth in measure 1: Part 1 moves from D to E while part 2 moves from G to A'
music21.theoryAnalysis.theoryAnalyzer.identifyParallelMotion(score, partNum1=None, partNum2=None, color=None)
music21.theoryAnalysis.theoryAnalyzer.identifyParallelOctaves(score, partNum1=None, partNum2=None, color=None, dictKey='parallelOctaves')

Identifies parallel octaves (calls parallelOctave()) between two parts (if specified) or between all possible pairs of parts (if not specified) and stores the resulting list of VLQTheoryResult objects in score.analysisData['ResultDict']['parallelOctaves']. Optionally, a color attribute may be specified to color all corresponding notes in the score.

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('c5'))
>>> p0measure1.append(note.Note('g5'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('c4'))
>>> p1measure1.append(note.Note('g4'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.identifyParallelOctaves(sc)
>>> len(sc.analysisData['ResultDict']['parallelOctaves'])
1
>>> sc.analysisData['ResultDict']['parallelOctaves'][0].text
'Parallel octave in measure 1: Part 1 moves from C to G while part 2 moves from C to G'
music21.theoryAnalysis.theoryAnalyzer.identifyParallelUnisons(score, partNum1=None, partNum2=None, color=None, dictKey='parallelUnisons')

Identifies parallel unisons (calls parallelUnison()) between two parts (if specified) or between all possible pairs of parts (if not specified) and stores the resulting list of VLQTheoryResult objects in score.analysisData['ResultDict']['parallelUnisons']. Optionally, a color attribute may be specified to color all corresponding notes in the score.

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('c5'))
>>> p0measure1.append(note.Note('d5'))
>>> p0measure1.append(note.Note('e5'))
>>> p0measure1.append(note.Note('f5'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('c5'))
>>> p1measure1.append(note.Note('d5'))
>>> p1measure1.append(note.Note('e5'))
>>> p1measure1.append(note.Note('f5'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.identifyParallelUnisons(sc)
>>> len(sc.analysisData['ResultDict']['parallelUnisons'])
3
>>> sc.analysisData['ResultDict']['parallelUnisons'][2].text
'Parallel unison in measure 1: Part 1 moves from E to F while part 2 moves from E to F'
music21.theoryAnalysis.theoryAnalyzer.identifyPassingTones(score, partNumToIdentify=None, color=None, dictKey=None, unaccentedOnly=True, editorialDictKey=None, editorialValue=True)

Identifies the passing tones in the piece by looking at the vertical and horizontal cross-sections. Optionally specify unaccentedOnly to identify only unaccented passing tones (passing tones on weak beats). unaccentedOnly by default set to True

Optionally label each identified passing tone with an editorial NoteEditorial value of editorialValue at note.editorial.misc[editorialDictKey]

>>> sc = stream.Score()
>>> sc.insert(0, meter.TimeSignature('2/4'))
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('A4', quarterLength = 0.5))
>>> p0measure1.append(note.Note('G4', quarterLength = 0.5))
>>> p0measure1.append(note.Note('F#4', quarterLength = 1.0))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('A2', quarterLength = 1.0))
>>> p1measure1.append(note.Note('D3', quarterLength = 1.0))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.identifyPassingTones(sc)
>>> len(sc.analysisData['ResultDict']['unaccentedPassingTones'])
1
>>> sc.analysisData['ResultDict']['unaccentedPassingTones'][0].text
'G identified as a passing tone in part 1'
music21.theoryAnalysis.theoryAnalyzer.identifyScaleDegrees(score, partNum=None, color=None, dictKey='scaleDegrees')

identify all the scale degrees in the score in partNum, or if not specified ALL partNums

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('a3'))
>>> p0measure1.append(note.Note('f#3'))
>>> p0measure1.append(note.Note('e3'))
>>> p0measure1.append(note.Note('c4'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('b2'))
>>> p1measure1.append(note.Note('c3'))
>>> p1measure1.append(note.Note('b2'))
>>> p1measure1.append(note.Note('c3'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.setKeyMeasureMap(sc, {0:'G'})
>>> theoryAnalysis.theoryAnalyzer.identifyScaleDegrees(sc)
>>> len(sc.analysisData['ResultDict']['scaleDegrees'])
8
>>> sc.analysisData['ResultDict']['scaleDegrees'][1].value
'7'
>>> sc.analysisData['ResultDict']['scaleDegrees'][1].text
'scale degree of F# in part 1 is 7'
music21.theoryAnalysis.theoryAnalyzer.identifySimilarMotion(score, partNum1=None, partNum2=None, color=None)
music21.theoryAnalysis.theoryAnalyzer.identifyTonicAndDominantRomanNumerals(score, color=None, dictKey='romanNumeralsVandI', responseOffsetMap=[])

Identifies the roman numerals in the piece by iterating throgh the vertical slices and figuring out which roman numeral best corresponds to that vertical slice. Optionally specify the responseOffsetMap which limits the resultObjects returned to only those with verticality's.offset(leftAlign=True) included in the list. For example, if only roman numerals were to be written for the vertical slice at offset 0, 6, and 7 in the piece, pass responseOffsetMap = [0,6,7]

>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('a3'))
>>> p0measure1.append(note.Note('B-3'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('c2'))
>>> p1measure1.append(note.Note('g2'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.setKeyMeasureMap(sc, {0:'Bb'} )
>>> theoryAnalysis.theoryAnalyzer.identifyTonicAndDominantRomanNumerals(sc)
>>> len(sc.analysisData['ResultDict']['romanNumeralsVandI'])
2
>>> sc.analysisData['ResultDict']['romanNumeralsVandI'][0].text
'Roman Numeral of A,C is V64'
>>> sc.analysisData['ResultDict']['romanNumeralsVandI'][1].text
'Roman Numeral of B-,G is I'
music21.theoryAnalysis.theoryAnalyzer.removeFromAnalysisData(score, dictKeys)

remove a result entry or entries from the resultDict by specifying which key or keys in the dictionary you’d like removed. Pass in a list of dictKeys or just a single dictionary key.

>>> sc = stream.Score()
>>> sc.analysisData['ResultDict'] = {'sampleDictKey': 'sample response', 'h1':'another sample response', '5':'third sample response'}
>>> theoryAnalysis.theoryAnalyzer.removeFromAnalysisData(sc, 'sampleDictKey')
>>> for k in sorted(list(sc.analysisData['ResultDict'].keys())):
...     print("{0}  {1}".format(k, sc.analysisData['ResultDict'][k]))
5   third sample response
h1  another sample response
>>> theoryAnalysis.theoryAnalyzer.removeFromAnalysisData(sc, ['h1', '5'])
>>> sc.analysisData['ResultDict']
{}
music21.theoryAnalysis.theoryAnalyzer.removeNeighborTones(score, dictKey='unaccentedNeighborTones')

primitively removes the neighbor tones found in a piece and fills the gap by extending note duraitons (method under development)

>>> from music21.theoryAnalysis import *
>>> sc = stream.Score()
>>> sc.insert(0, meter.TimeSignature('2/4'))
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('E-3', quarterLength = 1.0))
>>> p0measure1.append(note.Note('C3', quarterLength = 1.0))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('C2', quarterLength = 0.5))
>>> p1measure1.append(note.Note('B1', quarterLength = 0.5))
>>> p1measure1.append(note.Note('C2', quarterLength = 1.0))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.removeNeighborTones(sc)
>>> for x in sc.flat.notes:
...   print(x)
<music21.note.Note E->
<music21.note.Note C>
<music21.note.Note C>
<music21.note.Note C>
music21.theoryAnalysis.theoryAnalyzer.removePassingTones(score, dictKey='unaccentedPassingTones')

primitively removes the passing tones found in a piece and fills the gap by extending note duraitons (method under development)

>>> sc = stream.Score()
>>> sc.insert(0, meter.TimeSignature('2/4'))
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('A4', quarterLength = 0.5))
>>> p0measure1.append(note.Note('G4', quarterLength = 0.5))
>>> p0measure1.append(note.Note('F#4', quarterLength = 1.0))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('A2', quarterLength = 1.0))
>>> p1measure1.append(note.Note('D3', quarterLength = 1.0))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.removePassingTones(sc)
>>> for x in sc.flat.notes:
...   print(x)
<music21.note.Note A>
<music21.note.Note A>
<music21.note.Note F#>
<music21.note.Note D>
music21.theoryAnalysis.theoryAnalyzer.setKeyMeasureMap(score, keyMeasureMap)

easily specify the key of the score by measure in a dictionary correlating measure number to key, such as {1:’C’, 2:’D’, 3:’B-‘,5:’g’}. optionally pass in the music21 key object or the key string. This is used for analysis purposes only - no key object is actually added to the score. Check the music xml to verify measure numbers; pickup measures are usually 0.

>>> from music21.theoryAnalysis import *
>>> n1 = note.Note('c5')
>>> n1.quarterLength = 4
>>> n2 = note.Note('f4')
>>> n2.quarterLength = 2
>>> n3 = note.Note('g4')
>>> n3.quarterLength = 2
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> part0.append(n1)
>>> part1 = stream.Part()
>>> part1.append(n2)
>>> part1.append(n3)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalysis.theoryAnalyzer.setKeyMeasureMap(sc, {1:'C',2:'a'})
>>> theoryAnalysis.theoryAnalyzer.getKeyMeasureMap(sc)[1]
'C'
>>> theoryAnalysis.theoryAnalyzer.getKeyMeasureMap(sc)[2]
'a'