This module defines the ContourFinder and AggregateContour objects.
ContourFinder methods
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
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]
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]
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
Sets the key of ContourFinder’s internal stream. If not set manually, self.key will be determined by self.s.analyze(‘key’).
Defines a metric which takes a music21 stream containng measures and no parts. This metric measures how spaced out notes in a piece are.
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 methods
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.
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
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.
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.