Previous topic

music21.bar

Next topic

music21.beam

Table Of Contents

Table Of Contents

This Page

music21.base

music21.base is what you get in music21 if you type import music21. It contains all the most low-level objects that also appear in the music21 module (i.e., music21.base.Music21Object is the same as music21.Music21Object).

Music21 base classes for Stream objects and all elements contained within them including Notes, etc.. Additional objects for defining and manipulating elements are included.

The namespace of this file, as all base.py files, is loaded into the package that contains this file via __init__.py. Everything in this file is thus available after importing music21.

>>> import music21
>>> music21.Music21Object
<class 'music21.base.Music21Object'>
>>> music21.VERSION_STR
'1.8.0'

Alternatively, after doing a complete import, these classes are available under the module “base”:

>>> base.Music21Object
<class 'music21.base.Music21Object'>

Functions

music21.base.mainTest(*testClasses, **kwargs)

Takes as its arguments modules (or a string ‘noDocTest’ or ‘verbose’) and runs all of these modules through a unittest suite

Unless ‘noDocTest’ is passed as a module, a docTest is also performed on __main__, hence the name “mainTest”.

If ‘moduleRelative’ (a string) is passed as a module, then global variables are preserved.

Run example (put at end of your modules):

import unittest
class Test(unittest.TestCase):
    def testHello(self):
        hello = "Hello"
        self.assertEqual("Hello", hello)

import music21
if __name__ == '__main__':
    music21.mainTest(Test)

Music21Object

class music21.base.Music21Object(*arguments, **keywords)

Base class for all music21 objects.

All music21 objects have seven pieces of information:

  1. id: identification string unique to the objects container (optional)
  2. groups: a Groups object: which is a list of strings identifying internal subcollections (voices, parts, selections) to which this element belongs
  3. duration: Duration object representing the length of the object
  4. activeSite: a weakreference to the currently active Location
  5. offset: a floating point value, generally in quarter lengths, specifying the position of the object in a site.
  6. priority: int representing the position of an object among all objects at the same offset.
  7. sites: a Sites object that stores all the Streams and Contexts that an object is in.

Contexts, locations, and offsets are stored in a Sites object. Locations specify connections of this object to one location in a Stream subclass. Contexts are weakrefs for current objects that are associated with this object (similar to locations but without an offset)

Each of these may be passed in as a named keyword to any music21 object.

Some of these may be intercepted by the subclassing object (e.g., duration within Note)

Music21Object read-only properties

Music21Object.beat

Return the beat of this object as found in the most recently positioned Measure. Beat values count from 1 and contain a floating-point designation between 0 and 1 to show proportional progress through the beat.

>>> n = note.Note()
>>> n.quarterLength = .5
>>> m = stream.Measure()
>>> m.timeSignature = meter.TimeSignature('3/4')
>>> m.repeatAppend(n, 6)
>>> [m.notes[i].beat for i in range(6)]
[1.0, 1.5, 2.0, 2.5, 3.0, 3.5]
>>> m.timeSignature = meter.TimeSignature('6/8')
>>> [m.notes[i].beat for i in range(6)]
[1.0, 1.3333333..., 1.666666666..., 2.0, 2.33333333..., 2.66666...]
>>> s = stream.Stream()
>>> s.insert(0, meter.TimeSignature('3/4'))
>>> s.repeatAppend(note.Note(), 8)
>>> [n.beat for n in s.notes]
[1.0, 2.0, 3.0, 1.0, 2.0, 3.0, 1.0, 2.0]
Music21Object.beatDuration

Return a Duration of the beat active for this object as found in the most recently positioned Measure.

If extending beyond the Measure, or in a Stream with a TimeSignature, the meter modulus value will be returned.

>>> n = note.Note()
>>> n.quarterLength = .5
>>> m = stream.Measure()
>>> m.timeSignature = meter.TimeSignature('3/4')
>>> m.repeatAppend(n, 6)
>>> [m.notes[i].beatDuration.quarterLength for i in range(6)]
[1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
>>> m.timeSignature = meter.TimeSignature('6/8')
>>> [m.notes[i].beatDuration.quarterLength for i in range(6)]
[1.5, 1.5, 1.5, 1.5, 1.5, 1.5]
>>> s = stream.Stream()
>>> s.insert(0, meter.TimeSignature('2/4+3/4'))
>>> s.repeatAppend(note.Note(), 8)
>>> [n.beatDuration.quarterLength for n in s.notes]
[2.0, 2.0, 3.0, 3.0, 3.0, 2.0, 2.0, 3.0]
Music21Object.beatStr

Return a string representation of the beat of this object as found in the most recently positioned Measure. Beat values count from 1 and contain a fractional designation to show progress through the beat.

>>> n = note.Note()
>>> n.quarterLength = .5
>>> m = stream.Measure()
>>> m.timeSignature = meter.TimeSignature('3/4')
>>> m.repeatAppend(n, 6)
>>> [m.notes[i].beatStr for i in range(6)]
['1', '1 1/2', '2', '2 1/2', '3', '3 1/2']
>>> m.timeSignature = meter.TimeSignature('6/8')
>>> [m.notes[i].beatStr for i in range(6)]
['1', '1 1/3', '1 2/3', '2', '2 1/3', '2 2/3']
>>> s = stream.Stream()
>>> s.insert(0, meter.TimeSignature('3/4'))
>>> s.repeatAppend(note.Note(), 8)
>>> [n.beatStr for n in s.notes]
['1', '2', '3', '1', '2', '3', '1', '2']
Music21Object.beatStrength

Return the metrical accent of this object in the most recently positioned Measure. Accent values are between zero and one, and are derived from the local TimeSignature’s accent MeterSequence weights. If the offset of this object does not match a defined accent weight, a minimum accent weight will be returned.

>>> n = note.Note()
>>> n.quarterLength = .5
>>> m = stream.Measure()
>>> m.timeSignature = meter.TimeSignature('3/4')
>>> m.repeatAppend(n, 6)
>>> [m.notes[i].beatStrength for i in range(6)]
[1.0, 0.25, 0.5, 0.25, 0.5, 0.25]
>>> m.timeSignature = meter.TimeSignature('6/8')
>>> [m.notes[i].beatStrength for i in range(6)]
[1.0, 0.25, 0.25, 0.5, 0.25, 0.25]

We can also get the beatStrength for elements not in a measure, if the enclosing stream has a TimeSignature. We just assume that the time signature carries through to hypothetical following measures:

>>> n = note.QuarterNote("E--3")
>>> s = stream.Stream()
>>> s.insert(0.0, meter.TimeSignature('2/2'))
>>> s.repeatAppend(n, 12)
>>> [s.notes[i].beatStrength for i in range(12)]
[1.0, 0.25, 0.5, 0.25, 1.0, 0.25, 0.5, 0.25, 1.0, 0.25, 0.5, 0.25]

Changing the meter changes the output, of course:

>>> s.insert(4.0, meter.TimeSignature('3/4'))
>>> [s.notes[i].beatStrength for i in range(12)]
[1.0, 0.25, 0.5, 0.25, 1.0, 0.5, 0.5, 1.0, 0.5, 0.5, 1.0, 0.5]
Music21Object.classes

Returns a list containing the names (strings, not objects) of classes that this object belongs to – starting with the object’s class name and going up the mro() for the object. Very similar to Perl’s @ISA array:

>>> q = note.QuarterNote()
>>> q.classes
['QuarterNote', 'Note', 'NotRest', 'GeneralNote', 'Music21Object', 'object']

Having quick access to these things as strings makes it easier to do comparisons:

Example: find GClefs that are not Treble clefs (or treble 8vb, etc.):

>>> s = stream.Stream()
>>> s.insert(10, clef.GClef())
>>> s.insert(20, clef.TrebleClef())
>>> s.insert(30, clef.FrenchViolinClef())
>>> s.insert(40, clef.Treble8vbClef())
>>> s.insert(50, clef.BassClef())
>>> s2 = stream.Stream()
>>> for t in s:
...    if 'GClef' in t.classes and 'TrebleClef' not in t.classes:
...        s2.insert(t)
>>> s2.show('text')
{10.0} <music21.clef.GClef>
{30.0} <music21.clef.FrenchViolinClef>
Music21Object.derivationHierarchy

Return a list of Stream subclasses that this Stream is contained within or derived from. This provides a way of seeing Streams contained within Streams.

TODO: Better Name

>>> s = corpus.parse('bach/bwv66.6')
>>> [str(e.__class__) for e in s[1][2][3].derivationHierarchy]
["<class 'music21.stream.Measure'>", "<class 'music21.stream.Part'>", "<class 'music21.stream.Score'>"]
Music21Object.fullyQualifiedClasses

Similar to .classes, returns a list containing the names (strings, not objects) of classes with the full package name that this object belongs to – starting with the object’s class name and going up the mro() for the object. Very similar to Perl’s @ISA array:

>>> q = note.QuarterNote()
>>> q.fullyQualifiedClasses
['music21.note.QuarterNote', 'music21.note.Note', 'music21.note.NotRest', 'music21.note.GeneralNote', 'music21.base.Music21Object', '__builtin__.object']
Music21Object.isGrace

Return True or False if this music21 object has a GraceDuration.

>>> n = note.Note()
>>> n.isGrace
False
>>> ng = n.getGrace()
>>> ng.isGrace
True
Music21Object.measureNumber

Return the measure number of a Measure that contains this object if the object is in a measure.

Returns None if the object is not in a measure. Also note that by default Measure objects have measure number 0.

If an object belongs to multiple measures (not in the same hierarchy...) then it returns the measure number of the activeSite() if that is a Measure object. Otherwise it will use getContextByClass() to find the number of the measure it was most recently added to.

>>> m = stream.Measure()
>>> m.number = 12
>>> n = note.Note()
>>> m.append(n)
>>> n.measureNumber
12
>>> n2 = note.Note()
>>> n2.measureNumber is None
True
>>> m2 = stream.Measure()
>>> m2.append(n2)
>>> n2.measureNumber
0

This updates live if the measure number changes:

>>> m2.number = 11
>>> n2.measureNumber
11

The most recent measure added to is used unless activeSite is a measure:

>>> m.append(n2)
>>> n2.measureNumber
12
>>> n2.activeSite = m2
>>> n2.measureNumber
11

Music21Object read/write properties

Music21Object.activeSite

A reference to the most-recent object used to contain this object. In most cases, this will be a Stream or Stream sub-class. In most cases, an object’s activeSite attribute is automatically set when an the object is attached to a Stream.

>>> n = note.Note("C#4")
>>> p = stream.Part()
>>> p.insert(20.0, n)
>>> n.activeSite is p
True
>>> n.offset
20.0
>>> m = stream.Measure()
>>> m.insert(10.0, n)
>>> n.activeSite is m
True
>>> n.offset
10.0
>>> n.activeSite = p
>>> n.offset
20.0

DEVELOPER N.B. – the guts of this call will be moved to .sites soon.

Music21Object.duration

Get and set the duration of this object as a Duration object.

Music21Object.offset

The offset property sets or returns the position of this object (generally in quarterLengths) from the start of its activeSite, that is, the most recently referenced Stream or Stream subclass such as Part, Measure, or Voice. It is a simpler way of calling o.getOffsetBySite(o.activeSite).

If we put a Note into a Stream, we will see the activeSite changes.

>>> n1 = note.Note("D#3")
>>> n1.activeSite is None
True
>>> m1 = stream.Measure()
>>> m1.number = 4
>>> m1.insert(10.0, n1)
>>> n1.offset
10.0
>>> n1.activeSite
<music21.stream.Measure 4 offset=0.0>
>>> n1.activeSite is m1
True

The most recently referenced Stream becomes an object’s activeSite and thus the place where .offset looks to find its number.

>>> m2 = stream.Measure()
>>> m2.insert(20.0, n1)
>>> m2.number = 5
>>> n1.offset
20.0
>>> n1.activeSite is m2
True

Notice though that .offset depends on the .activeSite which is the most recently accessed/referenced Stream.

Here we will iterate over the elements in m1 and we will see that the .offset of n1 now is its offset in m1 even though we haven’t done anything directly to n1. Simply iterating over a site is enough to change the .activeSite of its elements:

>>> for element in m1:
...     pass
>>> n1.offset
10.0

The property can also set the offset for the object if no container has been set:

>>> n1 = note.Note()
>>> n1.id = 'hi'
>>> n1.offset = 20
>>> n1.offset
20.0
>>> s1 = stream.Stream()
>>> s1.append(n1)
>>> n1.offset
0.0
>>> s2 = stream.Stream()
>>> s2.insert(30.5, n1)
>>> n1.offset
30.5

After calling getElementById on s1, the returned element’s offset will be its offset in s1.

>>> n2 = s1.getElementById('hi')
>>> n2 is n1
True
>>> n2.offset
0.0

Iterating over the elements in a Stream will make its offset be the offset in iterated Stream.

>>> for thisElement in s2:
...     print thisElement.offset
30.5

When in doubt, use .getOffsetBySite(streamObj) which is safer.

Music21Object.priority

Get and set the priority integer value.

Priority specifies the order of processing from left (lowest number) to right (highest number) of objects at the same offset. For instance, if you want a key change and a clef change to happen at the same time but the key change to appear first, then set: keySigElement.priority = 1; clefElement.priority = 2 this might be a slightly counterintuitive numbering of priority, but it does mean, for instance, if you had two elements at the same offset, an allegro tempo change and an andante tempo change, then the tempo change with the higher priority number would apply to the following notes (by being processed second).

Default priority is 0; thus negative priorities are encouraged to have Elements that appear non-priority set elements.

In case of tie, there are defined class sort orders defined in music21.base.CLASS_SORT_ORDER. For instance, a key signature change appears before a time signature change before a note at the same offset. This produces the familiar order of materials at the start of a musical score.

>>> import music21
>>> a = music21.Music21Object()
>>> a.priority = 3
>>> a.priority = 'high'
Traceback (most recent call last):
ElementException: priority values must be integers.
Music21Object.seconds

Get or set the duration of this object in seconds, assuming that this object has a MetronomeMark or MetricModulation in its past context.

>>> s = stream.Stream()
>>> s.repeatAppend(note.Note(), 12)
>>> s.insert(0, tempo.MetronomeMark(number=120))
>>> s.insert(6, tempo.MetronomeMark(number=240))
>>> [n.seconds for n in s.notes]
[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25]

Music21Object methods

Music21Object.addContext(obj)

Add an object to the Sites object. For adding a location, use addLocation().

DEPRECATED – use self.sites.add()

>>> import music21
>>> class Mock(music21.Music21Object):
...     attr1 = 234
>>> aObj = Mock()
>>> aObj.attr1 = 'test'
>>> a = music21.Music21Object()
>>> a.sites.add(aObj)
>>> a.getContextAttr('attr1')
'test'
Music21Object.addLocation(site, offset)

DEPRECATED: use self.sites.add(site, offset)

Add a location to the Sites object. The supplied object is a reference to the object (the site) that contains an offset of this object. For example, if this Music21Object was Note, the site would be a Stream (or Stream subclass) and the offset would be a number for the offset.

This is only for advanced location method and is not a complete or sufficient way to add an object to a Stream.

>>> from music21 import note, stream
>>> s = stream.Stream()
>>> n = note.Note('E-5')
>>> n.sites.add(s, 10)
Music21Object.findAttributeInHierarchy(attrName)

If this element is contained within a Stream (or other Music21 element), findAttributeInHierarchy() searches the attributes of the activeSite for this attribute and returns its value.

If the activeSite does not have this attribute then we search its activeSite and up through the hierarchy until we find a value for this attribute. Or it Returns None if there is no match.

>>> m = stream.Measure()
>>> m.number = 12
>>> n = note.Note()
>>> m.append(n)
>>> n.activeSite is m
True
>>> n.findAttributeInHierarchy('number')
12
>>> print(n.findAttributeInHierarchy('elephant'))
None

Recursive searches also work. Here, the Score object is the only one with a ‘parts’ attribute.

>>> p1 = stream.Part()
>>> p1.insert(0, m)
>>> p2 = stream.Part()
>>> s = stream.Score()
>>> s.insert(0, p1)
>>> s.insert(0, p2)
>>> n.activeSite.activeSite is p1
True
>>> n.activeSite.activeSite.activeSite is s
True
>>> parts = n.findAttributeInHierarchy('parts')
>>> (parts[0] is p1, parts[1] is p2)
(True, True)
Music21Object.getAllContextsByClass(className, found=None, idFound=None, memo=None)

Search both Sites as well as associated objects to find all matchinging classes. Returns [] if not match is found.

Music21Object.getContextAttr(attr)

Given the name of an attribute, search the Sites object for contexts having this attribute and return the best match.

>>> import music21
>>> class Mock(music21.Music21Object):
...     attr1 = 234
>>> aObj = Mock()
>>> aObj.attr1 = 'test'
>>> a = music21.Music21Object()
>>> a.sites.add(aObj)
>>> a.getContextAttr('attr1')
'test'
Music21Object.getContextByClass(className, serialReverseSearch=True, callerFirst=None, sortByCreationTime=False, prioritizeActiveSite=True, getElementMethod='getElementAtOrBefore', memo=None)

A very powerful method in music21 of fundamental importance: Returns the element matching the className that is closest to this element in its current hierarchy. For instance, take this stream of changing time signatures:

>>> s1 = converter.parse('tinynotation: 3/4 C4 D E 2/4 F G A B 1/4 c')
>>> s2 = s1.makeMeasures()
>>> s2.show('t')
{0.0} <music21.stream.Measure 1 offset=0.0>
    {0.0} <music21.clef.BassClef>
    {0.0} <music21.meter.TimeSignature 3/4>
    {0.0} <music21.note.Note C>
    {1.0} <music21.note.Note D>
    {2.0} <music21.note.Note E>
{3.0} <music21.stream.Measure 2 offset=3.0>
    {0.0} <music21.meter.TimeSignature 2/4>
    {0.0} <music21.note.Note F>
    {1.0} <music21.note.Note G>
{5.0} <music21.stream.Measure 3 offset=5.0>
    {0.0} <music21.note.Note A>
    {1.0} <music21.note.Note B>
{7.0} <music21.stream.Measure 4 offset=7.0>
    {0.0} <music21.meter.TimeSignature 1/4>
    {0.0} <music21.note.Note C>
    {1.0} <music21.bar.Barline style=final>

Let’s get the last two notes of the piece, the B and high c:

>>> c = s2.measure(4).notes[0]
>>> c
<music21.note.Note C>
>>> b = s2.measure(3).notes[-1]
>>> b
<music21.note.Note B>

Now when we run getContextByClass(‘TimeSignature’) on c, we get a time signature of 1/4.

>>> c.getContextByClass('TimeSignature')
<music21.meter.TimeSignature 1/4>

Doing what we just did wouldn’t be hard to do with other methods, though getContextByClass makes it easier. But the time signature context for b would be much harder to get without this method, since in order to do it, it searches backwards within the measure, finds that there’s nothing there. It goes to the previous measure and searches that one backwards until it gets the proper TimeSignature of 2/4:

>>> b.getContextByClass('TimeSignature')
<music21.meter.TimeSignature 2/4>

The method is smart enough to stop when it gets to the beginning of the part. This is all you need to know for most uses. The rest of the docs are for advanced uses:

The methods searches both Sites as well as associated objects to find a matching class. Returns None if not match is found.

The a reference to the caller is required to find the offset of the object of the caller. This is needed for serialReverseSearch.

The caller may be a Sites reference from a lower-level object. If so, we can access the location of that lower-level object. However, if we need a flat representation, the caller needs to be the source Stream, not its Sites reference.

The callerFirst is the first object from which this method was called. This is needed in order to determine the final offset from which to search.

The prioritizeActiveSite parameter searches the object’s activeSite before any other object. By default this is True

The getElementMethod is a string that selects which Stream method is used to get elements for searching. The strings ‘getElementAtOrBefore’ and ‘getElementBeforeOffset’ are currently accepted.

Music21Object.getOffsetBySite(site)

If this class has been registered in a container such as a Stream, that container can be provided here, and the offset in that object can be returned.

Note that this is different than the getOffsetByElement() method on Stream in that this can never access the flat representation of a Stream.

>>> n = note.Note('A-4')  # a Music21Objecct
>>> n.offset = 30
>>> n.getOffsetBySite(None)
30.0
>>> s1 = stream.Stream()
>>> s1.id = 'containingStream'
>>> s1.insert(20.5, n)
>>> n.getOffsetBySite(s1)
20.5
>>> s2 = stream.Stream()
>>> s2.id = 'notContainingStream'
>>> n.getOffsetBySite(s2)
Traceback (most recent call last):
SitesException: The object <music21.note.Note A-> is not in site <music21.stream.Stream notContainingStream>.
Music21Object.getSiteIds()

DEPRECATED: use self.sites.getSiteIds() instead.

Return a list of all site Ids, or the id() value of the sites of this object.

Music21Object.getSites(idExclude=None)

DEPRECATED: use self.sites.getSites() instead...

Return a list of all objects that store a location for this object. Will include None, the default empty site placeholder.

If idExclude is provided, matching site ids will not be returned.

>>> from music21 import note, stream
>>> s1 = stream.Stream()
>>> s2 = stream.Stream()
>>> n = note.Note()
>>> s1.append(n)
>>> s2.append(n)
>>> n.getSites() == [None, s1, s2]
True
Music21Object.getSpannerSites(spannerClassList=None)

Return a list of all Spanner objects (or Spanner subclasses) that contain this element. This method provides a way for objects to be aware of what Spanners they reside in. Note that Spanners are not Streams but specialized Music21Objects that use a Stream subclass, SpannerStorage, internally to keep track of the elements that are spanned.

>>> n1 = note.Note('C4')
>>> n2 = note.Note('D4')
>>> sp1 = spanner.Slur(n1, n2)
>>> n1.getSpannerSites() == [sp1]
True

Note that not all Spanners are in the spanner module. They tend to reside in modules closer to their musical function:

>>> sp2 = dynamics.Crescendo(n2, n1)
>>> n2.getSpannerSites() == [sp1, sp2]
True

Optionally a class name or list of class names can be specified and only Spanners of that class will be returned

>>> sp3 = dynamics.Diminuendo(n1, n2)
>>> n2.getSpannerSites('Diminuendo') == [sp3]
True

A larger class name can be used to get all subclasses:

>>> n2.getSpannerSites('DynamicWedge') == [sp2, sp3]
True
>>> n2.getSpannerSites(['Slur','Diminuendo']) == [sp1, sp3]
True

The order spanners are returned is generally the order that they were added, but that is not guaranteed, so for safety sake, use set comparisons:

>>> set(n2.getSpannerSites(['Slur','Diminuendo'])) == set([sp3, sp1])
True

Example: see which pairs of notes are in the same slur.

>>> n3 = note.Note('E4')
>>> sp4 = spanner.Slur(n1, n3)
>>> for n in [n1, n2, n3]:
...    for nOther in [n1, n2, n3]:
...        if n is nOther:
...            continue
...        nSlurs = n.getSpannerSites('Slur')
...        nOtherSlurs = nOther.getSpannerSites('Slur')
...        for thisSlur in nSlurs:
...            if thisSlur in nOtherSlurs:
...               print("%s shares a slur with %s" % (n.name, nOther.name))
C shares a slur with D
C shares a slur with E
D shares a slur with C
E shares a slur with C
Music21Object.hasContext(obj)

Return a Boolean if an object reference is stored in the object’s Sites object.

This checks both all locations as well as all sites.

>>> import music21
>>> class Mock(music21.Music21Object):
...     attr1 = 234
>>> aObj = Mock()
>>> aObj.attr1 = 'test'
>>> a = music21.Music21Object()
>>> a.sites.add(aObj)
>>> a.hasContext(aObj)
True
>>> a.hasContext(None)
True
>>> a.hasContext(45)
False
Music21Object.hasSite(other)

Return True if other is a site in this Music21Object

>>> s = stream.Stream()
>>> n = note.Note()
>>> s.append(n)
>>> n.hasSite(s)
True
>>> n.hasSite(stream.Stream())
False
Music21Object.hasSpannerSite()

DEPRECATED: use self.sites.hasSpannerSite()

Return True if this object is found in any Spanner (i.e. has any spanners attached). This is determined by looking for a SpannerStorage Stream class as a Site.

>>> n1 = note.Note()
>>> n2 = note.Note()
>>> n3 = note.Note()
>>> sp1 = spanner.Slur(n1, n2)
>>> n1.getSpannerSites() == [sp1]
True
>>> sp2 = spanner.Slur(n2, n1)
>>> n1.hasSpannerSite()
True
>>> n2.hasSpannerSite()
True
>>> n3.hasSpannerSite()
False
Music21Object.hasVariantSite()

Return True if this object is found in any Variant This is determined by looking for a VariantStorage Stream class as a Site.

>>> n1 = note.Note()
>>> n2 = note.Note()
>>> n3 = note.Note()
>>> v1 = variant.Variant([n1, n2])
>>> n1.hasSpannerSite()
False
>>> n1.hasVariantSite()
True
>>> n2.hasVariantSite()
True
>>> n3.hasVariantSite()
False
Music21Object.isClassOrSubclass(classFilterList)

Given a class filter list (a list or tuple must be submitted), which may have strings or class objects, determine if this class is of the provided classes or a subclasses.

Music21Object.mergeAttributes(other)

Merge all elementary, static attributes. Namely, id and groups attributes from another music21 object. Can be useful for copy-like operations.

>>> m1 = base.Music21Object()
>>> m2 = base.Music21Object()
>>> m1.id = 'music21Object1'
>>> m1.groups.append("group1")
>>> m2.mergeAttributes(m1)
>>> m2.id
'music21Object1'
>>> "group1" in m2.groups
True
Music21Object.next(classFilterList=None, flattenLocalSites=False, beginNearest=True)

Get the next element found in a the activeSite (or other Sites) of this Music21Object.

The classFilterList can be used to specify one or more classes to match.

The flattenLocalSites parameter determines if the sites of this element (e.g., a Measure’s Part) are flattened on first search. When True, elements contained in adjacent containers may be selected first.

>>> s = corpus.parse('bwv66.6')
>>> s.parts[0].measure(3).next() == s.parts[0].measure(4)
True
>>> s.parts[0].measure(3).next('Note', flattenLocalSites=True) == s.parts[0].measure(3).notes[0]
True
Music21Object.previous(classFilterList=None, flattenLocalSites=False, beginNearest=True)

Get the previous element found in the activeSite or other .sites of this Music21Object.

The classFilterList can be used to specify one or more classes to match.

The flattenLocalSites parameter determines if the sites of this element (e.g., a Measure’s Part) are flattened on first search. When True, elements contained in adjacent containers may be selected first.

>>> s = corpus.parse('bwv66.6')
>>> s.parts[0].measure(3).previous() == s.parts[0].measure(2)
True
>>> s.parts[0].measure(3).previous('Note', flattenLocalSites=True) == s.parts[0].measure(2).notes[-1]
True
Music21Object.purgeLocations(rescanIsDead=False)

Remove references to all locations in objects that no longer exist.

Music21Object.purgeOrphans(excludeStorageStreams=True)

A Music21Object may, due to deep copying or other reasons, have contain a site (with an offset); yet, that site may no longer contain the Music21Object. These lingering sites are called orphans. This methods gets rid of them.

The excludeStorageStreams are SpannerStorage and VariantStorage.

Music21Object.removeLocationBySite(site)

TO-BE DEPRECATED: use self.sites.remove() instead and set activeSite manually.

Remove a location in the Sites object.

This is only for advanced location method and is not a complete or sufficient way to remove an object from a Stream.

>>> from music21 import note, stream
>>> s = stream.Stream()
>>> n = note.Note()
>>> n.sites.add(s, 10)
>>> n.activeSite = s
>>> n.removeLocationBySite(s)
>>> n.activeSite is None
True
Music21Object.removeLocationBySiteId(siteId)

DEPRECATED – use sites.removeById and set activeSite manually.

Remove a location in the Sites object by id.

>>> from music21 import note, stream
>>> s = stream.Stream()
>>> n = note.Note()
>>> n.sites.add(s, 10)
>>> n.activeSite = s
>>> n.removeLocationBySiteId(id(s))
>>> n.activeSite is None
True
Music21Object.setContextAttr(attrName, value)

Given the name of an attribute, search Contexts and return the best match.

>>> import music21
>>> class Mock(music21.Music21Object):
...     attr1 = 234
>>> aObj = Mock()
>>> aObj.attr1 = 'test'
>>> a = music21.Music21Object()
>>> a.sites.add(aObj)
>>> a.getContextAttr('attr1')
'test'
>>> a.setContextAttr('attr1', 3000)
>>> a.getContextAttr('attr1')
3000
Music21Object.setOffsetBySite(site, value)

Direct access to the Sites setOffsetBySite() method. This should only be used for advanced processing of known site that already has been added.

>>> import music21
>>> class Mock(music21.Music21Object):
...     pass
>>> aSite = Mock()
>>> a = music21.Music21Object()
>>> a.sites.add(aSite, 20)
>>> a.setOffsetBySite(aSite, 30)
>>> a.getOffsetBySite(aSite)
30
Music21Object.show(fmt=None, app=None, **keywords)

Displays an object in a format provided by the fmt argument or, if not provided, the format set in the user’s Environment

Valid formats include (but are not limited to)::
musicxml text midi lily (or lilypond) lily.png lily.pdf lily.svg braille vexflow musicxml.png

N.B. score.write(‘lily’) returns a bare lilypond file, score.show(‘lily’) runs it through lilypond and displays it as a png.

Music21Object.splitAtDurations()

Takes a Music21Object (e.g., a note.Note) and returns a list of similar objects with only a single duration.DurationUnit in each. Ties are added if the object supports ties.

Articulations only appear on the first note. Same with lyrics.

Fermatas should be on last note, but not done yet.

>>> a = note.Note()
>>> a.duration.clear() # remove defaults
>>> a.duration.addDurationUnit(duration.Duration('half'))
>>> a.duration.quarterLength
2.0
>>> a.duration.addDurationUnit(duration.Duration('whole'))
>>> a.duration.quarterLength
6.0
>>> b = a.splitAtDurations()
>>> b[0].pitch == b[1].pitch
True
>>> b[0].duration.type
'half'
>>> b[1].duration.type
'whole'
>>> c = note.Note()
>>> c.quarterLength = 2.5
>>> d, e = c.splitAtDurations()
>>> d.duration.type
'half'
>>> e.duration.type
'eighth'
>>> d.tie.type
'start'
>>> print e.tie
<music21.tie.Tie stop>

Assume c is tied to the next note. Then the last split note should also be tied

>>> c.tie = tie.Tie()
>>> d, e = c.splitAtDurations()
>>> e.tie.type
'start'

Rests have no ties:

>>> f = note.Rest()
>>> f.quarterLength = 2.5
>>> g, h = f.splitAtDurations()
>>> (g.duration.type, h.duration.type)
('half', 'eighth')
>>> g.tie is None
True
Music21Object.splitAtQuarterLength(quarterLength, retainOrigin=True, addTies=True, displayTiedAccidentals=False, delta=1e-06)

Split an Element into two Elements at a provided quarterLength (offset) into the Element.

>>> a = note.Note('C#5')
>>> a.duration.type = 'whole'
>>> a.articulations = [articulations.Staccato()]
>>> a.lyric = 'hi'
>>> a.expressions = [expressions.Mordent(), expressions.Trill(), expressions.Fermata()]
>>> b, c = a.splitAtQuarterLength(3)
>>> b.duration.type
'half'
>>> b.duration.dots
1
>>> b.duration.quarterLength
3.0
>>> b.articulations
[<music21.articulations.Staccato>]
>>> b.lyric
'hi'
>>> b.expressions
[<music21.expressions.Mordent>, <music21.expressions.Trill>]
>>> c.duration.type
'quarter'
>>> c.duration.dots
0
>>> c.duration.quarterLength
1.0
>>> c.articulations
[]
>>> c.lyric
>>> c.expressions
[<music21.expressions.Trill>, <music21.expressions.Fermata>]

Make sure that ties remain as they should be:

>>> d = note.Note('D#4')
>>> d.duration.quarterLength = 3.0
>>> d.tie = tie.Tie('start')
>>> e, f = d.splitAtQuarterLength(2.0)
>>> e.tie, f.tie
(<music21.tie.Tie start>, <music21.tie.Tie continue>)

Should be the same for chords...

>>> g = chord.Chord(['C4', 'E4', 'G4'])
>>> g.duration.quarterLength = 3.0
>>> g._notes[1].tie = tie.Tie('start')
>>> h, i = g.splitAtQuarterLength(2.0)
>>> for j in range(0,3):
...   print (h._notes[j].tie, i._notes[j].tie)
(<music21.tie.Tie start>, <music21.tie.Tie stop>)
(<music21.tie.Tie start>, <music21.tie.Tie continue>)
(<music21.tie.Tie start>, <music21.tie.Tie stop>)
Music21Object.splitByQuarterLengths(quarterLengthList, addTies=True, displayTiedAccidentals=False)

Given a list of quarter lengths, return a list of Music21Object objects, copied from this Music21Object, that are partitioned and tied with the specified quarter length list durations.

>>> n = note.Note()
>>> n.quarterLength = 3
>>> post = n.splitByQuarterLengths([1,1,1])
>>> [n.quarterLength for n in post]
[1.0, 1.0, 1.0]
Music21Object.unwrapWeakref()

Public interface to operation on Sites.

NOTE: Any Music21Object subclass that contains private Streams (like Spanner and Variant) must override these methods.

>>> import music21
>>> aM21Obj = music21.Music21Object()
>>> bM21Obj = music21.Music21Object()
>>> aM21Obj.offset = 30
>>> aM21Obj.getOffsetBySite(None)
30.0
>>> aM21Obj.sites.add(bM21Obj, 50)
>>> aM21Obj.activeSite = bM21Obj
>>> aM21Obj.unwrapWeakref()
Music21Object.wrapWeakref()

Public interface to operation on Sites.

>>> import music21
>>> aM21Obj = music21.Music21Object()
>>> bM21Obj = music21.Music21Object()
>>> aM21Obj.offset = 30
>>> aM21Obj.getOffsetBySite(None)
30.0
>>> aM21Obj.sites.add(bM21Obj, 50)
>>> aM21Obj.activeSite = bM21Obj
>>> aM21Obj.unwrapWeakref()
>>> aM21Obj.wrapWeakref()
Music21Object.write(fmt=None, fp=None, **keywords)

Write out a file of music notation (or an image, etc.) in a given format. If fp is specified as a file path then the file will be placed there. If it is not given then a temporary file will be created.

If fmt is not given then the default of your Environment’s ‘writeFormat’ will be used. For most people that is musicxml.

Returns the full path to the file.

Music21Object instance variables

Music21Object.classSortOrder

Property which returns an number (int or otherwise) depending on the class of the Music21Object that represents a priority for an object based on its class alone – used as a tie for stream sorting in case two objects have the same offset and priority. Lower numbers are sorted to the left of higher numbers. For instance, Clef, KeySignature, TimeSignature all come (in that order) before Note.

All undefined classes have classSortOrder of 20 – same as note.Note

>>> m21o = base.Music21Object()
>>> m21o.classSortOrder
20
>>> tc = clef.TrebleClef()
>>> tc.classSortOrder
0
>>> ks = key.KeySignature(3)
>>> ks.classSortOrder
1

New classes can define their own default classSortOrder

>>> class ExampleClass(base.Music21Object):
...     classSortOrderDefault = 5
...
>>> ec1 = ExampleClass()
>>> ec1.classSortOrder
5
Music21Object.groups

An instance of a Group object which describes arbitrary Groups that this object belongs to.

Music21Object.hideObjectOnPrint

if set to True will not print upon output (only used in MusicXML output at this point and Lilypond for notes, chords, and rests).

Music21Object.id

A unique identification string (not to be confused with the default .id() method.

Music21Object.isSpanner

Boolean value for quickly identifying Spanner objects (False by default).

Music21Object.isStream

Boolean value for quickly identifying Stream objects (False by default).

Music21Object.isVariant

Boolean value for quickly identifying Variant objects (False by default).

Music21Object.xPosition

if set, defines the display x-position from the start of the container (in musicxml “tenths” by default)

ElementWrapper

class music21.base.ElementWrapper(obj=None)

An ElementWrapper is a way of containing any object that is not a Music21Object, so that that object can be positioned within a Stream.

The object stored within ElementWrapper is available from the obj attribute. All the attributes of the stored object (except .id and anything else that conflicts with a Music21Object attribute) are gettable and settable by querying the ElementWrapper. This feature makes it possible easily to mix Music21Objects and non-Music21Objects with similarly named attributes in the same Stream.

This example inserts 10 random wave files into a music21 Stream and then reports their filename and number of audio channels (in this example, it’s always 2) if they fall on a strong beat in fast 6/8

>>> import music21
>>> from music21 import stream, meter
>>> import wave
>>> import random
>>> s = stream.Stream()
>>> s.append(meter.TimeSignature('fast 6/8'))
>>> for i in range(10):
...    fileName = 'thisSound_' + str(random.randint(1,20)) + '.wav'
...    soundFile = wave.open(fileName)
...    soundFile.fileName = fileName
...    el = music21.ElementWrapper(soundFile)
...    s.insert(i, el)
>>> for j in s.getElementsByClass('ElementWrapper'):
...    if j.beatStrength > 0.4:
...        print j.offset, j.beatStrength, j.getnchannels(), j.fileName
0.0 1.0 2 thisSound_1.wav
3.0 1.0 2 thisSound_16.wav
6.0 1.0 2 thisSound_12.wav
9.0 1.0 2 thisSound_8.wav

Test representation of an ElementWrapper

>>> for i, j in enumerate(s.getElementsByClass('ElementWrapper')):
...     if i == 2:
...         j.id = None
...     else:
...         j.id = str(i) + "_wrapper"
...     if i <=2:
...         print j
<ElementWrapper id=0_wrapper offset=0.0 obj="<...Wave_read object...">
<ElementWrapper id=1_wrapper offset=1.0 obj="<...Wave_read object...">
<ElementWrapper offset=2.0 obj="<...Wave_read object...">

ElementWrapper bases

ElementWrapper read-only properties

Read-only properties inherited from Music21Object:

ElementWrapper read/write properties

Read/write properties inherited from Music21Object:

ElementWrapper methods

ElementWrapper.isTwin(other)

A weaker form of equality. a.isTwin(b) is true if a and b store either the same object OR objects that are equal. In other words, it is essentially the same object in a different context

>>> import music21
>>> from music21 import note
>>> aE = music21.ElementWrapper(obj = "hello")
>>> bE = copy.copy(aE)
>>> aE is bE
False
>>> aE == bE
True
>>> aE.isTwin(bE)
True
>>> bE.offset = 14.0
>>> bE.priority = -4
>>> aE == bE
False
>>> aE.isTwin(bE)
True

Methods inherited from Music21Object:

ElementWrapper instance variables

ElementWrapper.obj

The object this wrapper wraps. It should not be a Music21Object.

Instance variables inherited from Music21Object:

Sites

class music21.base.Sites(containedById=None)

An object, stored within a Music21Object, that stores (weak) references to a collection of objects that may be contextually relevant to this object.

Some of these objects are locations (also called sites), or Streams that contain this object. In this case the Sites object stores an offset value, used for determining position within a Stream.

All defined contexts are stored as dictionaries in a dictionary. The outermost dictionary stores objects.

Sites bases

Sites methods

Sites.add(obj, offset=None, timeValue=None, idKey=None, classString=None)

Add a reference to the Sites collection for this object.

N.B. – like all .sites operations, this is an advanced tool not for standard music21 usage. Instead of:

elObj.add(streamObj, 20.0)

use this command, which will take care of .sites.add as well as putting elObj in streamObj.elements:

streamObj.insert(20.0, elObj)

If offset is None, then obj is interpreted as a Context (such as a temperament, a time period, etc.)

If offset is not None, then obj is interpreted as location, i.e., a Stream.

offset can also be the term highestTime which is the highest available time in the obj (used for streamObj.append(el))

The timeValue argument is used to store the time (in seconds after Jan 1, 1970) when this object was added to locations. If set to None, then the current time is used.

idKey stores the id() of the obj. If None, then id(obj) is used.

classString stores the class of obj. If None then obj.classes[0] is used.

TODO: Tests. Including updates.

Sites.clear()

Clear all stored data.

Sites.get(locationsTrail=False, sortByCreationTime=False, priorityTarget=None, excludeNone=False)

Get references; unwrap from weakrefs; order, based on dictionary keys, is from most recently added to least recently added.

The locationsTrail option forces locations to come after all other defined contexts.

The sortByCreationTime option will sort objects by creation time, where most-recently assigned objects are returned first.

If priorityTarget is defined, this object will be placed first in the list of objects.

>>> import music21
>>> class Mock(music21.Music21Object):
...     pass
...
>>> aObj = Mock()
>>> bObj = Mock()
>>> cObj = Mock()
>>> aSites = music21.Sites()
>>> aSites.add(cObj, 345) # a locations
>>> aSites.add(aObj)
>>> aSites.add(bObj)
>>> aSites.get() == [cObj, aObj, bObj]
True
>>> aSites.get(locationsTrail=True) == [aObj, bObj, cObj]
True
>>> aSites.get(sortByCreationTime=True) == [bObj, aObj, cObj]
True
Sites.getAllByClass(className, found=None, idFound=None, memo=None)

Return all known references of a given class found in any association with this Sites object.

This will recursively search the defined contexts of existing defined contexts, and return a list of all objects that match the given class.

>>> import music21
>>> class Mock(music21.Music21Object):
...    pass
...
>>> class Mocker(music21.Music21Object):
...    pass
...
>>> aObj = Mock()
>>> bObj = Mock()
>>> cObj = Mocker()
>>> dc = music21.Sites()
>>> dc.add(aObj)
>>> dc.add(bObj)
>>> dc.add(cObj)
>>> dc.getAllByClass(Mock) == [aObj, bObj]
True
Sites.getAttrByName(attrName)

Given an attribute name, search all objects and find the first that matches this attribute name; then return a reference to this attribute.

>>> import music21
>>> class Mock(music21.Music21Object):
...     attr1 = 234
...
>>> aObj = Mock()
>>> aObj.attr1 = 234
>>> bObj = Mock()
>>> bObj.attr1 = 98
>>> aSites = music21.Sites()
>>> aSites.add(aObj)
>>> len(aSites)
1
>>> aSites.getAttrByName('attr1') == 234
True
>>> aSites.remove(aObj)
>>> aSites.add(bObj)
>>> aSites.getAttrByName('attr1') == 98
True
Sites.getByClass(className, serialReverseSearch=True, callerFirst=None, sortByCreationTime=False, prioritizeActiveSite=False, priorityTarget=None, getElementMethod='getElementAtOrBefore', memo=None)

Return the most recently added reference based on className. Class name can be a string or the class name.

This will recursively search the defined contexts of existing defined contexts.

The callerFirst parameters is simply used to pass a reference of the first caller; this is necessary if we are looking within a Stream for a flat offset position.

If priorityTarget is specified, this location will be searched first. The prioritizeActiveSite is pased to to any recursively called getContextByClass() calls.

The getElementMethod is a string that selects which Stream method is used to get elements for searching with getElementsByClass() calls.

>>> import music21
>>> class Mock(music21.Music21Object):
...     pass
...
>>> import time
>>> aObj = Mock()
>>> bObj = Mock()
>>> aSites = music21.Sites()
>>> aSites.add(aObj)
>>> #time.sleep(.05)
>>> aSites.add(bObj)
>>> # we get the most recently added object first
>>> aSites.getByClass('Mock', sortByCreationTime=True) == bObj
True
>>> aSites.getByClass(Mock, sortByCreationTime=True) == bObj
True
Sites.getById(id)

Return the object specified by an id. Used for testing and debugging.

Sites.getOffsetByObjectMatch(obj)

For a given object, return the offset using a direct object match. The stored id value is not used; instead, the id() of both the stored object reference and the supplied object is used.

This should be replaced by getOffsetBySite(strictDeadCheck = True)...

>>> import music21
>>> class Mock(music21.Music21Object):
...     pass
...
>>> aSite = Mock()
>>> bSite = Mock()
>>> aLocations = music21.Sites()
>>> aLocations.add(aSite, 23)
>>> aLocations.add(bSite, 121.5)
>>> aLocations.getOffsetByObjectMatch(aSite)
23
>>> aLocations.getOffsetByObjectMatch(bSite)
121.5
Sites.getOffsetBySite(site)

For a given site return this Sites’s offset in it. The None site is permitted. The id() of the site is used to find the offset.

>>> import music21
>>> class Mock(music21.Music21Object):
...     pass
...
>>> aSite = Mock()
>>> bSite = Mock()
>>> aLocations = music21.Sites()
>>> aLocations.add(aSite, 23)
>>> aLocations.add(bSite, 121.5)
>>> aLocations.getOffsetBySite(aSite)
23
>>> aLocations.getOffsetBySite(bSite)
121.5
Sites.getOffsetBySiteId(idKey, strictDeadCheck=False)

Main method for getting an offset from a location key.

>>> import music21
>>> class Mock(music21.Music21Object):
...     pass
...
>>> aSite = Mock()
>>> bSite = Mock()
>>> cSite = Mock()
>>> dSite = Mock()
>>> eSite = Mock()
>>> aLocations = music21.Sites()
>>> aLocations.add(aSite, 0)
>>> aLocations.add(cSite) # a context
>>> aLocations.add(bSite, 234) # can add at same offset or a different one
>>> aLocations.add(dSite) # a context
>>> aLocations.getOffsetBySiteId(id(bSite))
234

If strictDeadCheck is False (default) we can still retrieve the context from a dead weakref. This is necessary to get the offset from an iterated Stream often. Eventually, this should become True – but too many errors for now.

>>> idBSite = id(bSite)
>>> del(bSite)
>>> aLocations._definedContexts[idBSite]['obj']
<weakref at 0x...; dead>
>>> aLocations._definedContexts[idBSite]['obj'] is None
False
>>> common.unwrapWeakref(aLocations._definedContexts[idBSite]['obj']) is None
True
>>> aLocations.getOffsetBySiteId(idBSite, strictDeadCheck = False) # default
234

With this, you’ll get an exception:

>>> aLocations.getOffsetBySiteId(idBSite, strictDeadCheck = True)
Traceback (most recent call last):
SitesException: Could not find the object with id ... in the Site marked with idKey ... (was there, now site is dead).
object <music21.base.Sites object at 0x...>, definedContexts: {...}
containedById = ...
Sites.getOffsets()

Return a list of all offsets.

>>> import music21
>>> class Mock(music21.Music21Object):
...     pass
...
>>> aSite = Mock()
>>> bSite = Mock()
>>> cSite = Mock()
>>> dSite = Mock()
>>> aLocations = music21.Sites()
>>> aLocations.add(aSite, 0)
>>> aLocations.add(cSite) # a context
>>> aLocations.add(bSite, 234) # can add at same offset or another
>>> aLocations.add(dSite) # a context
>>> aLocations.getOffsets()
[0, 234]
Sites.getSiteByOffset(offset)

For a given offset return the site that fits it

More than one Site may have the same offset; this at one point returned the last site added by sorting time, but now we use a dict, so there’s no guarantee that the one you want will be there – need orderedDicts!

>>> import music21
>>> class Mock(music21.Music21Object):
...     pass
...
>>> aSite = Mock()
>>> bSite = Mock()
>>> cSite = Mock()
>>> aLocations = music21.Sites()
>>> aLocations.add(aSite, 23)
>>> aLocations.add(bSite, 23121.5)
>>> aSite == aLocations.getSiteByOffset(23)
True
Sites.getSiteCount()

Return the number of non-dead sites, excluding the None site. This does not unwrap weakrefs for performance.

Sites.getSiteIds()

Return a list of all site Ids.

>>> import music21
>>> class Mock(music21.Music21Object):
...     pass
...
>>> aSite = Mock()
>>> bSite = Mock()
>>> dc = music21.Sites()
>>> dc.add(aSite, 0)
>>> dc.add(bSite) # a context
>>> dc.getSiteIds() == [id(aSite)]
True
Sites.getSites(idExclude=None, excludeNone=False)

Get all defined contexts that are locations. Note that this unwraps all sites from weakrefs and is thus an expensive operation.

>>> import music21
>>> class Mock(music21.Music21Object):
...     pass
...
>>> aObj = Mock()
>>> bObj = Mock()
>>> aSites = music21.Sites()
>>> aSites.add(aObj, 234)
>>> aSites.add(bObj, 3000)
>>> len(aSites._locationKeys) == 2
True
>>> len(aSites.getSites()) == 2
True
Sites.getSitesByClass(className)

Return sites that match the provided class.

Input can be either a Class object or a string

>>> import music21
>>> from music21 import stream
>>> class Mock(music21.Music21Object):
...     pass
...
>>> aObj = Mock()
>>> bObj = Mock()
>>> cObj = stream.Stream()
>>> aSites = music21.Sites()
>>> aSites.add(aObj, 234)
>>> aSites.add(bObj, 3000)
>>> aSites.add(cObj, 200)
>>> aSites.getSitesByClass(Mock) == [aObj, bObj]
True
>>> aSites.getSitesByClass('Stream') == [cObj]
True
Sites.hasSiteId(siteId)

Return True or False if this Sites object already has this site id defined as a location

>>> import music21
>>> class Mock(music21.Music21Object):
...     pass
...
>>> aSite = Mock()
>>> bSite = Mock()
>>> dc = music21.Sites()
>>> dc.add(aSite, 0)
>>> dc.add(bSite) # a context
>>> dc.hasSiteId(id(aSite))
True
>>> dc.hasSiteId(id(bSite))
False
Sites.hasSpannerSite()

Return True if this object is found in any Spanner. This is determined by looking for a SpannerStorage Stream class as a Site.

Sites.hasVariantSite()

Return True if this object is found in any Variant. This is determined by looking for a VariantStorage Stream class as a Site.

Sites.isSite(obj)

Given an object, determine if it is a site stored in this Sites. This will return False if the object is simply a context and not a location.

>>> import music21
>>> class Mock(music21.Music21Object):
...     pass
...
>>> aSite = Mock()
>>> bSite = Mock()
>>> aLocations = music21.Sites()
>>> aLocations.add(aSite, 0)
>>> aLocations.add(bSite) # a context
>>> aLocations.isSite(aSite)
True
>>> aLocations.isSite(bSite)
False
Sites.purgeLocations(rescanIsDead=False)

Clean all locations that refer to objects that no longer exist.

The removeOrphanedSites option removes sites that may have been the result of deepcopy: the element has the site, but the site does not have the element. This results b/c Sites are shallow-copied, and then elements are re-added.

>>> import music21
>>> class Mock(music21.Music21Object):
...     pass
...
>>> aSite = Mock()
>>> bSite = Mock()
>>> cSite = Mock()
>>> dSite = Mock()
>>> aLocations = music21.Sites()
>>> aLocations.add(aSite, 0)
>>> aLocations.add(cSite) # a context
>>> del aSite
>>> len(aLocations)
2
>>> aLocations.purgeLocations(rescanIsDead=True)
>>> len(aLocations)
1
Sites.remove(site)

Remove the object (a context or location site) specified from Sites. Object provided can be a location site (i.e., a Stream) or a pure context (like a Temperament).

N.B. – like all .sites operations, this is an advanced tool not for standard music21 usage. Instead of:

elObj.remove(streamObj)

use this command, which will take care of .sites.remove as well as removing elObj from streamObj.elements:

streamObj.remove(elObj)
>>> class Mock(base.Music21Object):
...     pass
...
>>> aSite = Mock()
>>> bSite = Mock()
>>> cSite = Mock()
>>> aSites = base.Sites()
>>> aSites.add(aSite, 23)
>>> len(aSites)
1
>>> aSites.add(bSite, 233)
>>> len(aSites)
2
>>> aSites.add(cSite, 232223)
>>> len(aSites)
3
>>> aSites.remove(aSite)
>>> len(aSites)
2
Sites.removeById(idKey)

Remove a site entry by id key, which is id() of the object.

Sites.setAttrByName(attrName, value)

Given an attribute name, search all objects and find the first that matches this attribute name; then return a reference to this attribute.

>>> import music21
>>> class Mock(music21.Music21Object):
...     attr1 = 234
...
>>> aObj = Mock()
>>> bObj = Mock()
>>> bObj.attr1 = 98
>>> aSites = music21.Sites()
>>> aSites.add(aObj)
>>> aSites.add(bObj)
>>> aSites.setAttrByName('attr1', 'test')
>>> aSites.getAttrByName('attr1') == 'test'
True
Sites.setOffsetBySite(site, value)

Changes the offset of the site specified. Note that this can also be done with add, but the difference is that if the site is not in Sites, it will raise an exception.

>>> import music21
>>> class Mock(music21.Music21Object):
...     pass
...
>>> aSite = Mock()
>>> bSite = Mock()
>>> cSite = Mock()
>>> aLocations = music21.Sites()
>>> aLocations.add(aSite, 23)
>>> aLocations.add(bSite, 121.5)
>>> aLocations.setOffsetBySite(aSite, 20)
>>> aLocations.getOffsetBySite(aSite)
20
>>> aLocations.setOffsetBySite(cSite, 30)
Traceback (most recent call last):
SitesException: an entry for this object (<...Mock object at 0x...>) is not stored in Sites
Sites.setOffsetBySiteId(siteId, value)

Set an offset by siteId. This assumes that the site is valid, is best used for advanced, performance critical usage only.

The siteId parameter can be None.

Sites.unwrapWeakref(purgeLocations=True)

Unwrap any and all weakrefs stored.

>>> class Mock(base.Music21Object):
...     pass
>>> aObj = Mock()
>>> bObj = Mock()
>>> aSites = base.Sites()
>>> aSites.add(aObj)
>>> aSites.add(bObj)
>>> common.isWeakref(aSites.get()[0]) # unwrapping happens
False
>>> common.isWeakref(aSites._definedContexts[id(aObj)]['obj'])
True
>>> aSites.unwrapWeakref()
>>> common.isWeakref(aSites._definedContexts[id(aObj)]['obj'])
False
>>> common.isWeakref(aSites._definedContexts[id(bObj)]['obj'])
False
Sites.wrapWeakref()

Wrap all stored objects with weakrefs.

>>> class Mock(base.Music21Object):
...     pass
...
>>> aObj = Mock()
>>> bObj = Mock()
>>> aSites = base.Sites()
>>> aSites.add(aObj)
>>> aSites.add(bObj)
>>> aSites.unwrapWeakref()
>>> aSites.wrapWeakref()
>>> common.isWeakref(aSites._definedContexts[id(aObj)]['obj'])
True
>>> common.isWeakref(aSites._definedContexts[id(bObj)]['obj'])
True

Groups

class music21.base.Groups

Groups is a list of strings used to identify associations that an element might have.

The Groups object enforces that all elements must be strings, and that the same element cannot be provided more than once.

>>> g = Groups()
>>> g.append("hello")
>>> g[0]
'hello'
>>> g.append("hello") # not added as already present
>>> len(g)
1
>>> g
['hello']
>>> g.append(5)
Traceback (most recent call last):
GroupException: Only strings can be used as list names

Groups bases

Groups methods

Groups.append(value)

SlottedObject

class music21.base.SlottedObject

Provides template for classes implementing slots.