Previous topic

music21.composition.seeger

Next topic

music21.converter

Table Of Contents

Table Of Contents

This Page

music21.contour

This module defines the ContourFinder and AggregateContour objects.

ContourFinder

class music21.contour.ContourFinder(s=None)

ContourFinder methods

ContourFinder.dissonanceMetric(inpStream)

inpStream is a stream containing some number of measures which each contain chords. Output is a number between 0 and 1 which is proportional to the number of dissonant chords.

To work correctly, input must contain measures and no parts.

>>> c = corpus.parse('bwv102.7').chordify()
>>> contour.ContourFinder().dissonanceMetric( c.measures(1, 1) )
0.25
>>> contour.ContourFinder().dissonanceMetric( c.measures(8, 8) )
0.5
>>> contour.ContourFinder().dissonanceMetric( c.measures(1, 10)) < 1.0
True
ContourFinder.getContour(cType, window=None, slide=None, overwrite=False, metric=None, needsChordify=False, normalized=False)

Stores and then returns a normalized contour of the type cType. cType can be either ‘spacing’, ‘tonality’, or ‘dissonance’.

If using a metric that is not predefined, cType is any string that signifies what your metric measures. In this case, you must pass getContour a metric function which takes in a music21 stream and outputs a score. If passing a metric that requires the music21 stream be just chords, specify needsChordify=True.

Window is how many measures are considered at a time and slide is the number of measures the window moves over each time. By default, measure and slide are both 1.

Each time you call getContour for a cType, the result is cached. If you wish to get the contour for the same cType more than once, with different parameters (with a different window and slide, for example) then specify overwrite=True

To get a contour where measures map to the metric values, use normalized=False (the default), but to get a contour which evenly divides time between 1.0 and 100.0, use normalized=True

>>> cf = contour.ContourFinder( corpus.parse('bwv10.7'))
>>> mycontour = cf.getContour('dissonance')
>>> [mycontour[x] for x in sorted(mycontour.keys())]
[0.0, 0.25, 0.5, 0.5, 0.0, 0.0, 0.25, 0.75, 0.0, 0.0, 0.5, 0.75, 0.75, 0.0, 0.5, 0.5, 0.5, 0.5, 0.75, 0.75, 0.75, 0.0]
>>> mycontour = cf.getContour('always one', 2, 2, metric= lambda x: 1.0)
>>> [mycontour[x] for x in sorted(mycontour.keys())]
[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
>>> mycontour = cf.getContour('spacing', metric = lambda x: 2, overwrite=False)
Traceback (most recent call last):
OverwriteException: Attempted to overwrite 'spacing' metric but did not specify overwrite=True
>>> mycontour = cf.getContour('spacing', slide=3, metric = lambda x: 2.0, overwrite=True)
>>> [mycontour[x] for x in sorted(mycontour.keys())]
[2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0]
>>> mycontour = cf.getContour('spacing')
>>> [mycontour[x] for x in sorted(mycontour.keys())]
[2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0]
ContourFinder.getContourValuesForMetric(metric, window=1, slide=1, needChordified=False)

Returns a dictionary mapping measure numbers to that measure’s score under the provided metric. Ignores pickup measures entirely.

Window is a positive integer indicating how many measure the metric should look at at once, and slide is a positive integer indicating by how many measures the window should slide over each time the metric is measured.

e.g. if window=4 and slide=2, metric = f, the result will be of the form: { measures 1-4: f(measures 1-4), measures 3-6: f(measures 3-6), measures 5-8: f( measures5-8), ...}

>>> metric = lambda s: len(s.measureOffsetMap())
>>> c = corpus.parse('bwv10.7')
>>> res = contour.ContourFinder(c).getContourValuesForMetric(metric, 3, 2, False)
>>> resList = sorted(list(res.keys()))
>>> resList
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21]
>>> [res[x] for x in resList]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2]
ContourFinder.plot(cType, contour=None, regression=True, order=4, title='Contour Plot', fileName=None)
ContourFinder.randomize(contourDict)

Returns a version of contourDict where the keys-to-values mapping is scrambled.

>>> myDict = {1:1, 2:2, 3:3, 4:4, 5:5, 6:6, 7:7, 8:8, 9:9, 10:10, 11:11, 12:12, 13:13, 
...           14:14, 15:15, 16:16, 17:17, 18:18, 19:19, 20:20}
>>> res = contour.ContourFinder().randomize(myDict)
>>> res == myDict
False
>>> sorted(list(res.keys())) == sorted(list(myDict.keys()))
True
>>> sorted(list(res.values())) == sorted(list(myDict.values()))
True         
ContourFinder.setKey(key)

Sets the key of ContourFinder’s internal stream. If not set manually, self.key will be determined by self.s.analyze(‘key’).

ContourFinder.spacingMetric(inpStream)

Defines a metric which takes a music21 stream containng measures and no parts. This metric measures how spaced out notes in a piece are.

ContourFinder.tonalDistanceMetric(inpStream)

Returns a number between 0.0 and 1.0 that is a measure of how far away the key of inpStream is from the key of ContourFinder’s internal stream.

AggregateContour

class music21.contour.AggregateContour(aggContours=None)

AggregateContour methods

AggregateContour.addPieceToContour(piece, cType, metric=None, window=1, slide=1, order=8, needsChordify=False)

Adds a piece to the aggregate contour.

piece is either a music21 stream, or a ContourFinder object (which should have a stream wrapped inside of it).

cType is the contour type.

If using a metric that is not predefined, cType is any string that signifies what your metric measures. In this case, you must pass getContour a metric function which takes in a music21 stream and outputs a score. If passing a metric that requires the music21 stream be just chords, specify needsChordify=True.

Window is how many measures are considered at a time and slide is the number of measures the window moves over each time. By default, measure and slide are both 1.

AggregateContour.dissimilarityScore(cType, contourDict)

Returns a score based on how dissimilar the input contourDict is from the aggregate contour of type cType.

Requires contourDict be normalized with values from 1.0 to 100.0

AggregateContour.getCombinedContour(cType)

Returns the combined contour of the type specified by cType. Instead of a dictionary, this contour is just a list of ordered pairs (tuples) with the first value being time and the second value being the score.

AggregateContour.getCombinedContourPoly(cType, order=8)

Returns the polynomial fit for the aggregate contour of type cType.

Order is the order of the resulting polynomial. e.g. For a linear regression, order=1.

AggregateContour.plot(cType, showPoints=True, comparisonContour=None, regression=True, order=6)