music21.graph.axis

Definitions for extracting data from a Stream to place on one axis of a PlotStream or similar object.

Axis

class music21.graph.axis.Axis(client=None, axisName='x')

An Axis is an easier way of specifying what to plot on any given axis.

Client should be a .plot.PlotStream or None. Eventually a Stream may be allowed, but not yet.

Axis read-only properties

Axis.stream

Returns a reference to the client’s .streamObj (or None if client is None)

If the client is itself a stream, return it.

Read-only

Axis read/write properties

Axis.client

The client stores a reference to the Plot that makes reference to this axis.

(Like all music21 clients, It is normally stored internally as a weakref, so no need for garbage collecting)

Axis.label

Returns self.label or class.labelDefault if not set:

>>> ax = graph.axis.Axis(axisName='y')
>>> ax.label
'an axis'
>>> ax.label = 'velocity'
>>> ax.label
'velocity'

Axis methods

Axis.extractOneElement(n, formatDict)

Override in subclasses...

Axis.postProcessData(dataList=None)

Routine to be called after data has been extracted to do any cleanup, etc. Defaults to doing nothing, but see CountingAxis for an example of how this works.

Axis.setBoundariesFromData(values)

If self.minValue is not set, then set self.minValue to be the minimum of these values.

Same with maxValue

>>> ax = graph.axis.Axis()
>>> print(ax.minValue)
None
>>> values = [10, 0, 3, 5]
>>> ax.setBoundariesFromData(values)
>>> ax.minValue
0
>>> ax.maxValue
10

If a boundary is given or .setXXXFromData is False then no changes are made

>>> ax = graph.axis.Axis()
>>> ax.minValue = -1
>>> ax.setBoundariesFromData(values)
>>> ax.minValue
-1
>>> ax.maxValue
10
Axis.ticks()

Get a set of ticks for this data. Used by several numeric axes to make a reasonable number of ticks.

>>> cax = graph.axis.Axis()
>>> cax.minValue = 1
>>> cax.maxValue = 9
>>> cax.ticks()
[(0, '0'), (1, '1'), (2, '2'), (3, '3'), (4, '4'),
 (5, '5'), (6, '6'), (7, '7'), (8, '8'), (9, '9'), (10, '10')]

For larger data, the ticks are farther apart.

>>> cax.minValue = 7
>>> cax.maxValue = 80
>>> cax.ticks()
[(0, '0'), (10, '10'), (20, '20'), (30, '30'), (40, '40'),
 (50, '50'), (60, '60'), (70, '70'), (80, '80'), (90, '90')]
>>> cax.minValue = 712
>>> cax.maxValue = 2213
>>> cax.ticks()
[(600, '600'), (700, '700'), (800, '800'), (900, '900'), (1000, '1000'),
 (1100, '1100'), (1200, '1200'), (1300, '1300'), (1400, '1400'), (1500, '1500'),
 (1600, '1600'), (1700, '1700'), (1800, '1800'), (1900, '1900'), (2000, '2000'),
 (2100, '2100'), (2200, '2200'), (2300, '2300')]

Axis instance variables

Axis.axisDataMap

a dict of {‘x’: 0, ‘y’: 1, ‘z’: 2} mapping where an axis’s data can be found in self.client.data after extract data is run:

>>> b = corpus.parse('bwv66.6')
>>> plot = graph.plot.ScatterPitchClassOffset(b)
>>> pcAxis = plot.axisY
>>> pcAxis.axisName
'y'
>>> pcAxisDataIndex = pcAxis.axisDataMap[pcAxis.axisName]
>>> pcAxisDataIndex
1
>>> plot.extractData()
>>> pcValues = [dataTuple[pcAxisDataIndex] for dataTuple in plot.data]
>>> pcValues[0:2]
[1, 11]
Axis.axisName

the name of the axis. One of “x” or “y” or for 3D Plots, “z”

Axis.maxValue

None or number representing the axis maximum. Default None.

Axis.minValue

None or number representing the axis minimum. Default None.

Axis.quantities

a tuple of strings representing the quantities the axis can plot. The first element of the tuple is the authoritative name.

>>> ax = graph.axis.DynamicsAxis()
>>> ax.quantities
('dynamic', 'dynamics', 'volume')

CountingAxis

class music21.graph.axis.CountingAxis(client=None, axisName='y')

Axis subclass for counting data in another Axis.

Used for histograms, weighted scatter, etc.

>>> bach = corpus.parse('bwv66.6')
>>> plotS = graph.plot.PlotStream(bach)
>>> plotS.axisX = graph.axis.PitchSpaceAxis(plotS, 'x')
>>> plotS.axisY = graph.axis.CountingAxis(plotS)
>>> plotS.doneAction = None
>>> plotS.run()
>>> plotS.data
[(42.0, 1, {}), (45.0, 1, {}), (46.0, 1, {}), (47.0, 5, {}), (49.0, 6, {}), ...]

CountingAxis bases

CountingAxis read-only properties

Read-only properties inherited from Axis:

CountingAxis read/write properties

Read/write properties inherited from Axis:

CountingAxis methods

CountingAxis.postProcessData()

Replace client.data with a list that only includes each key once.

Methods inherited from Axis:

CountingAxis instance variables

CountingAxis.countAxes

a string or tuple of strings representing an axis or axes to use in counting

Instance variables inherited from Axis:

DynamicsAxis

class music21.graph.axis.DynamicsAxis(client=None, axisName='x')

Axis subclass for dealing with Dynamics

DynamicsAxis bases

DynamicsAxis read-only properties

Read-only properties inherited from Axis:

DynamicsAxis read/write properties

Read/write properties inherited from Axis:

DynamicsAxis methods

DynamicsAxis.setBoundariesFromData(values=None)
DynamicsAxis.ticks()

Utility method to get ticks in dynamic values:

>>> ax = graph.axis.DynamicsAxis()
>>> ax.ticks()
[(0, '$pppppp$'), (1, '$ppppp$'), (2, '$pppp$'), (3, '$ppp$'), (4, '$pp$'),
 (5, '$p$'), (6, '$mp$'), (7, '$mf$'), (8, '$f$'), (9, '$fp$'), (10, '$sf$'),
 (11, '$ff$'), (12, '$fff$'), (13, '$ffff$'), (14, '$fffff$'), (15, '$ffffff$')]

A minimum and maximum dynamic index can be specified as minValue and maxValue

>>> ax.minValue = 3
>>> ax.maxValue = 6
>>> ax.ticks()
[(3, '$ppp$'), (4, '$pp$'), (5, '$p$'), (6, '$mp$')]

Methods inherited from Axis:

DynamicsAxis instance variables

Instance variables inherited from Axis:

OffsetAxis

class music21.graph.axis.OffsetAxis(client=None, axisName='x')

Axis subclass for dealing with Offsets

OffsetAxis bases

OffsetAxis read-only properties

Read-only properties inherited from Axis:

OffsetAxis read/write properties

OffsetAxis.label

Return an axis label for measure or offset, depending on if measures are available.

>>> a = graph.axis.OffsetAxis()
>>> a.label
'Offset'
>>> a.useMeasures = True
>>> a.label
'Measure Number'

Read/write properties inherited from Axis:

OffsetAxis methods

OffsetAxis.extractOneElement(n, formatDict)
OffsetAxis.getOffsetMap()

Find the first partlike object and get the measureOffsetMap from it, or an empty-dict if not.

>>> b = corpus.parse('bwv66.6')
>>> p = graph.plot.PlotStream(b)
>>> ax = graph.axis.OffsetAxis(p, 'x')
>>> om = ax.getOffsetMap()
>>> om
OrderedDict([(0.0, [<music21.stream.Measure 0 offset=0.0>]),
             (1.0, [<music21.stream.Measure 1 offset=1.0>]),
             (5.0, [<music21.stream.Measure 2 offset=5.0>]),
             ...])

Same if called on a single part:

>>> p = graph.plot.PlotStream(b.parts[0])
>>> ax = graph.axis.OffsetAxis(p, 'x')
>>> om2 = ax.getOffsetMap()
>>> om2
OrderedDict([(0.0, [<music21.stream.Measure 0 offset=0.0>]),
             (1.0, [<music21.stream.Measure 1 offset=1.0>]),
             (5.0, [<music21.stream.Measure 2 offset=5.0>]),
             ...])

But empty if called on a single Measure ...

>>> p = graph.plot.PlotStream(b.parts[0].getElementsByClass('Measure')[2])
>>> ax = graph.axis.OffsetAxis(p, 'x')
>>> om3 = ax.getOffsetMap()
>>> om3
{}
OffsetAxis.setBoundariesFromData(values=None)
OffsetAxis.setUseMeasuresFromOffsetMap(offsetMap=None)

Given an offsetMap and .useMeasures=None return True or False based on whether the offsetMap or self.getOffsetMap() is non-empty.

>>> b = corpus.parse('bwv66.6')
>>> p = graph.plot.PlotStream(b)
>>> ax = graph.axis.OffsetAxis(p, 'x')
>>> print(ax.useMeasures)
None
>>> ax.setUseMeasuresFromOffsetMap()
True

Sets .useMeasures as a side effect:

>>> ax.useMeasures
True

same as:

>>> ax = graph.axis.OffsetAxis(p, 'x')
>>> om = ax.getOffsetMap()
>>> ax.setUseMeasuresFromOffsetMap(om)
True

If .useMeasures is set explicitly, then we return that

>>> ax.useMeasures = False
>>> ax.setUseMeasuresFromOffsetMap()
False

Returns False if the offsetMap is empty

>>> p = graph.plot.PlotStream(b.parts[0].getElementsByClass('Measure')[2])
>>> axMeasure = graph.axis.OffsetAxis(p, 'x')
>>> axMeasure.setUseMeasuresFromOffsetMap()
False
>>> axMeasure.useMeasures
False
OffsetAxis.ticks()

Get offset or measure ticks

>>> s = corpus.parse('bach/bwv281.xml')
>>> plotS = graph.plot.PlotStream(s)
>>> ax = graph.axis.OffsetAxis(plotS)
>>> ax.setBoundariesFromData()
>>> ax.ticks() # on whole score, showing anacrusis spacing
[(0.0, '0'), (1.0, '1'), (5.0, '2'), (9.0, '3'), (13.0, '4'), (17.0, '5'),
 (21.0, '6'), (25.0, '7'), (29.0, '8')]
>>> a = graph.plot.PlotStream(s.parts[0].flat) # on a Part
>>> plotS = graph.plot.PlotStream(s)
>>> ax = graph.axis.OffsetAxis(plotS)
>>> ax.setBoundariesFromData()
>>> ax.ticks() # on whole score, showing anacrusis spacing
[(0.0, '0'), (1.0, '1'), (5.0, '2'), (9.0, '3'), (13.0, '4'), (17.0, '5'),
 (21.0, '6'), (25.0, '7'), (29.0, '8')]
>>> ax.minMaxMeasureOnly = True
>>> ax.ticks() # on whole score, showing anacrusis spacing
[(0.0, '0'), (29.0, '8')]
>>> ax.minMaxMeasureOnly = False
>>> ax.minValue = 8
>>> ax.maxValue = 12
>>> ax.ticks()
[(9.0, '3')]
>>> n = note.Note('a') # on a raw collection of notes with no measures
>>> s = stream.Stream()
>>> s.repeatAppend(n, 20)
>>> plotS = graph.plot.PlotStream(s)
>>> ax = graph.axis.OffsetAxis(plotS)
>>> ax.setBoundariesFromData()
>>> ax.ticks()
[(0, '0'), (10, '10'), (20, '20')]
>>> ax.offsetStepSize = 5
>>> ax.ticks()
[(0, '0'), (5, '5'), (10, '10'), (15, '15'), (20, '20')]

Methods inherited from Axis:

OffsetAxis instance variables

OffsetAxis.minMaxMeasureOnly

If True then only the first and last values will be used to create ticks for measures. Default False.

OffsetAxis.offsetStepSize

If measures are not used then this number is used to create the number of steps between an axis tick. Currently the default is 10, but it might become a function of the length of the stream eventually.

OffsetAxis.useMeasures

bool or None for whether offsets (False) or measure numbers (True) should be used in the case of an offset access. Default, None, meaning to check whether the stream has measures first.

Instance variables inherited from PositionAxis:

Instance variables inherited from Axis:

OffsetEndAxis

class music21.graph.axis.OffsetEndAxis(client=None, axisName='x')

An Axis that gives beginning and ending values for each element

OffsetEndAxis bases

OffsetEndAxis read-only properties

Read-only properties inherited from Axis:

OffsetEndAxis read/write properties

Read/write properties inherited from OffsetAxis:

Read/write properties inherited from Axis:

OffsetEndAxis methods

OffsetEndAxis.extractOneElement(n, formatDict)

Methods inherited from OffsetAxis:

Methods inherited from Axis:

OffsetEndAxis instance variables

OffsetEndAxis.noteSpacing

amount in QL to leave blank between untied notes. (default = graceNoteQL)

Instance variables inherited from OffsetAxis:

Instance variables inherited from PositionAxis:

Instance variables inherited from Axis:

PitchAxis

class music21.graph.axis.PitchAxis(client=None, axisName='x')

Axis subclass for dealing with Pitches

PitchAxis bases

PitchAxis read-only properties

Read-only properties inherited from Axis:

PitchAxis read/write properties

Read/write properties inherited from Axis:

PitchAxis methods

static PitchAxis.makePitchLabelsUnicode(ticks)

Given a list of ticks, replace all labels with alternative/unicode symbols where necessary.

>>> ticks = [(60, 'C4'), (61, 'C#4'), (62, 'D4'), (63, 'E-4')]
>>> t2 = graph.axis.PitchAxis.makePitchLabelsUnicode(ticks)
>>> len(t2)
4
>>> [num for num, label in t2]
[60, 61, 62, 63]
>>> t2[0]
(60, 'C4')
>>> for num, label in t2:
...     print(label) # printing for PY2
C4
C♯4
D4
E♭4

Methods inherited from Axis:

PitchAxis instance variables

PitchAxis.blankLabelUnused

bool on whether to hide labels for unused pitches, default True.

PitchAxis.hideUnused

bool on whether not to even show a tick when a pitch doesn’t exist. default True.

PitchAxis.showEnharmonic

bool on whether to show both common enharmonics in labels, default True

PitchAxis.showOctaves

bool or ‘few’ about whether to show octave numbers. If ‘few’ then only the first pitch in each octave is shown. Default ‘few’

Instance variables inherited from Axis:

PitchClassAxis

class music21.graph.axis.PitchClassAxis(client=None, axisName='x')

Axis subclass for dealing with PitchClasses

By default, axis is not set from data, but set to 0, 11

PitchClassAxis bases

PitchClassAxis read-only properties

Read-only properties inherited from Axis:

PitchClassAxis read/write properties

Read/write properties inherited from Axis:

PitchClassAxis methods

PitchClassAxis.extractOneElement(n, formatDict)
PitchClassAxis.ticks()

Get ticks and labels for pitch classes.

If showEnharmonic is True (default) then when choosing whether to display as sharp or flat use the most commonly used enharmonic.

>>> s = corpus.parse('bach/bwv324.xml')
>>> s.analyze('key')
<music21.key.Key of G major>
>>> plotS = graph.plot.PlotStream(s)
>>> ax = graph.axis.PitchClassAxis(plotS)
>>> ax.hideUnused = True

Ticks returnes a list of two-element tuples:

>>> ax.ticks()
[(0, 'C'), (2, 'D'), ..., (11, 'B')]
>>> for position, noteName in ax.ticks():
...            print (str(position) + " " + noteName)
0 C
2 D
3 D♯
4 E
6 F♯
7 G
9 A
11 B
>>> s = corpus.parse('bach/bwv281.xml')
>>> plotS = graph.plot.PlotStream(s)
>>> ax = graph.axis.PitchClassAxis(plotS)
>>> ax.hideUnused = True
>>> ax.showEnharmonic = True
>>> for position, noteName in ax.ticks():
...            print (str(position) + " " + noteName)
0 C
2 D
3 E♭
4 E
5 F
7 G
9 A
10 B♭
11 B
>>> ax.blankLabelUnused = True
>>> ax.hideUnused = False
>>> for position, noteName in ax.ticks():
...            print (str(position) + " " + noteName)
0 C
1
2 D
3 E♭
4 E
5 F
6
7 G
8
9 A
10 B♭
11 B

.showEnharmonic will change here...

>>> s.append(note.Note('A#4'))
>>> s.append(note.Note('G#4'))
>>> s.append(note.Note('A-4'))
>>> s.append(note.Note('A-4'))
>>> for position, noteName in ax.ticks():
...            print (str(position) + " " + noteName)
0 C
1
2 D
3 E♭
4 E
5 F
6
7 G
8 G♯/A♭
9 A
10 A♯/B♭
11 B

Make sure that Ab shows since there are two of them and only one G#

>>> ax.showEnharmonic = False
>>> for position, noteName in ax.ticks():
...            print (str(position) + " " + noteName)
0 C
1
2 D
3 E♭
4 E
5 F
6
7 G
8 A♭
9 A
10 B♭
11 B

Methods inherited from PitchAxis:

Methods inherited from Axis:

PitchClassAxis instance variables

Instance variables inherited from PitchAxis:

Instance variables inherited from Axis:

PitchSpaceAxis

class music21.graph.axis.PitchSpaceAxis(client=None, axisName='x')

Axis subclass for dealing with PitchSpace (MIDI numbers...)

PitchSpaceAxis bases

PitchSpaceAxis read-only properties

Read-only properties inherited from Axis:

PitchSpaceAxis read/write properties

Read/write properties inherited from Axis:

PitchSpaceAxis methods

PitchSpaceAxis.extractOneElement(n, formatDict)
PitchSpaceAxis.ticks(dataMin=36, dataMax=100)
>>> ax = graph.axis.PitchSpaceAxis()
>>> ax.hideUnused = False
>>> ax.blankLabelUnused = False
>>> ax.minValue = 20
>>> ax.maxValue = 24
>>> for ps, label in ax.ticks():
...     print(str(ps) + " " + label)
20 G♯0
21 A
22 B♭
23 B
24 C1
>>> ax.showOctaves = False
>>> for ps, label in ax.ticks():
...     print(str(ps) + " " + label)
20 G♯
21 A
22 B♭
23 B
24 C
>>> ax.showOctaves = True
>>> for ps, label in ax.ticks():
...     print(str(ps) + " " + label)
20 G♯0
21 A0
22 B♭0
23 B0
24 C1
>>> ax.minValue = 60
>>> ax.maxValue = 72
>>> [x for x, y in ax.ticks()]
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72]
>>> bach = corpus.parse('bwv66.6')
>>> plotS = graph.plot.PlotStream(bach.parts[-1])
>>> ax = graph.axis.PitchSpaceAxis(plotS)
>>> ax.hideUnused = False
>>> ax.minValue = 36
>>> ax.maxValue = 100
>>> ticks = ax.ticks()
>>> ticks[0] # blank because no note 36 in data
(36, '')
>>> ticks[21]
(57, 'A')

Methods inherited from PitchAxis:

Methods inherited from Axis:

PitchSpaceAxis instance variables

Instance variables inherited from PitchAxis:

Instance variables inherited from Axis:

PitchSpaceOctaveAxis

class music21.graph.axis.PitchSpaceOctaveAxis(client=None, axisName='x')

An axis similar to pitch classes, but just shows the octaves

PitchSpaceOctaveAxis bases

PitchSpaceOctaveAxis read-only properties

Read-only properties inherited from Axis:

PitchSpaceOctaveAxis read/write properties

Read/write properties inherited from Axis:

PitchSpaceOctaveAxis methods

PitchSpaceOctaveAxis.ticks()

This class does not currently take into account whether the octaves themselves are found in the Stream.

>>> ax = graph.axis.PitchSpaceOctaveAxis()
>>> ax.minValue = 36
>>> ax.maxValue = 100
>>> ax.ticks()
[(36, 'C2'), (48, 'C3'), (60, 'C4'), (72, 'C5'), (84, 'C6'), (96, 'C7')]
>>> ax.startNameWithOctave = 'A2'
>>> ax.ticks()
[(45, 'A2'), (57, 'A3'), (69, 'A4'), (81, 'A5'), (93, 'A6')]

Methods inherited from PitchSpaceAxis:

Methods inherited from PitchAxis:

Methods inherited from Axis:

PitchSpaceOctaveAxis instance variables

Instance variables inherited from PitchAxis:

Instance variables inherited from Axis:

PositionAxis

class music21.graph.axis.PositionAxis(client=None, axisName='x')

Axis subclass for dealing with Positions

PositionAxis bases

PositionAxis read-only properties

Read-only properties inherited from Axis:

PositionAxis read/write properties

Read/write properties inherited from Axis:

PositionAxis methods

Methods inherited from Axis:

PositionAxis instance variables

PositionAxis.graceNoteQL

length to substitute a grace note or other Zero-length element for. Default is the length of a 64th note (1/16 of a QL)

Instance variables inherited from Axis:

QuarterLengthAxis

class music21.graph.axis.QuarterLengthAxis(client=None, axisName='x')

Axis subclass for dealing with QuarterLengths

QuarterLengthAxis bases

QuarterLengthAxis read-only properties

Read-only properties inherited from Axis:

QuarterLengthAxis read/write properties

QuarterLengthAxis.label

Read/write properties inherited from Axis:

QuarterLengthAxis methods

QuarterLengthAxis.dataFromQL(ql)
QuarterLengthAxis.extractOneElement(n, formatDict)
QuarterLengthAxis.labelLogTag()

Returns a TeX formatted tag to the axis label depending on whether the scale is logrithmic or not. Checks .useLogScale

>>> a = graph.axis.QuarterLengthAxis()
>>> a.useLogScale
True
>>> a.labelLogTag()
' ($log_2$)'
>>> a.useLogScale = False
>>> a.labelLogTag()
''
>>> a.useLogScale = 10
>>> a.labelLogTag()
' ($log_10$)'
QuarterLengthAxis.remapQuarterLength(x)

Remap a quarter length as its log2. Essentially it’s just math.log(x, 2), but x=0 is replaced with self.graceNoteQL.

QuarterLengthAxis.ticks()

Get ticks for quarterLength.

If remap is True (the default), the remapQuarterLength() method will be used to scale displayed quarter lengths by log base 2.

Note that mix and max do nothing, but must be included in order to set the tick style.

>>> s = stream.Stream()
>>> for t in ['32nd', '16th', 'eighth', 'quarter', 'half']:
...     n = note.Note()
...     n.duration.type = t
...     s.append(n)
>>> plotS = graph.plot.PlotStream(s)
>>> ax = graph.axis.QuarterLengthAxis(plotS)
>>> ax.ticks()
[(-3.0, '0.1...'), (-2.0, '0.25'), (-1.0, '0.5'), (0.0, '1.0'), (1.0, '2.0')]
>>> ax.useLogScale = False
>>> ax.ticks()
[(0.125, '0.1...'), (0.25, '0.25'), (0.5, '0.5'), (1.0, '1.0'), (2.0, '2.0')]
>>> ax.useDurationNames = True
>>> ax.ticks()
[(0.125, '32nd'), (0.25, '16th'), (0.5, 'Eighth'), (1.0, 'Quarter'), (2.0, 'Half')]

The second entry is 0.125 but gets rounded differently in python 2 (1.3) and python 3 (1.2)

>>> nGrace = note.Note()
>>> nGrace.getGrace(inPlace=True)
>>> s.append(nGrace)
>>> plotS = graph.plot.PlotStream(s)
>>> ax = graph.axis.QuarterLengthAxis(plotS)
>>> ax.ticks()[0]
(-4.0, '0.0')
>>> ax.useLogScale = False
>>> ax.ticks()[0]
(0.0625, '0.0')

Methods inherited from Axis:

QuarterLengthAxis instance variables

QuarterLengthAxis.useDurationNames

If used then duration names replace numbers for ticks. If set, probably will want to change tickFontSize in the graph object

QuarterLengthAxis.useLogScale

bool or int for whether to scale numbers logrithmicly. Adds (log2) to the axis label if used. If True (default) then log2 is assumed. If an int, then log the int (say, 10) is used. instead.

Instance variables inherited from PositionAxis:

Instance variables inherited from Axis: