music21.stream.core

the Stream Core Mixin handles the core attributes of streams that should be thought of almost as private values and not used except by advanced programmers who need the highest speed in programming.

Nothing here promises to be stable. The music21 team can make any changes here for efficiency reasons while being considered backwards compatible so long as the public methods that call this remain stable.

All functions here will eventually begin with .core.

StreamCoreMixin

class music21.stream.core.StreamCoreMixin

StreamCoreMixin read-only properties

StreamCoreMixin.spannerBundle

A low-level object for Spanner management. This is a read-only property.

StreamCoreMixin methods

StreamCoreMixin.asTimespans(classList=None, flatten=True)

Convert stream to a TimespanTree instance, a highly optimized data structure for searching through elements and offsets.

>>> score = tree.makeExampleScore()
>>> scoreTree = score.asTimespans()
>>> print(scoreTree)
<TimespanTree {20} (0.0 to 8.0) <music21.stream.Score exampleScore>>
    <ElementTimespan (0.0 to 0.0) <music21.clef.BassClef>>
    <ElementTimespan (0.0 to 0.0) <music21.meter.TimeSignature 2/4>>
    <ElementTimespan (0.0 to 0.0) <music21.instrument.Instrument 'PartA: : '>>
    <ElementTimespan (0.0 to 0.0) <music21.clef.BassClef>>
    <ElementTimespan (0.0 to 0.0) <music21.meter.TimeSignature 2/4>>
    <ElementTimespan (0.0 to 0.0) <music21.instrument.Instrument 'PartB: : '>>
    <PitchedTimespan (0.0 to 1.0) <music21.note.Note C>>
    <PitchedTimespan (0.0 to 2.0) <music21.note.Note C#>>
    <PitchedTimespan (1.0 to 2.0) <music21.note.Note D>>
    <PitchedTimespan (2.0 to 3.0) <music21.note.Note E>>
    <PitchedTimespan (2.0 to 4.0) <music21.note.Note G#>>
    <PitchedTimespan (3.0 to 4.0) <music21.note.Note F>>
    <PitchedTimespan (4.0 to 5.0) <music21.note.Note G>>
    <PitchedTimespan (4.0 to 6.0) <music21.note.Note E#>>
    <PitchedTimespan (5.0 to 6.0) <music21.note.Note A>>
    <PitchedTimespan (6.0 to 7.0) <music21.note.Note B>>
    <PitchedTimespan (6.0 to 8.0) <music21.note.Note D#>>
    <PitchedTimespan (7.0 to 8.0) <music21.note.Note C>>
    <ElementTimespan (8.0 to 8.0) <music21.bar.Barline type=final>>
    <ElementTimespan (8.0 to 8.0) <music21.bar.Barline type=final>>
StreamCoreMixin.asTree(flatten=False, classList=None, useTimespans=False, groupOffsets=False)

Returns an elementTree of the score, using exact positioning.

See tree.fromStream.asTree() for more details.

>>> score = tree.makeExampleScore()
>>> scoreTree = score.asTree(flatten=True)
>>> scoreTree
<ElementTree {20} (0.0 <0.-25...> to 8.0) <music21.stream.Score exampleScore>>
StreamCoreMixin.coreAppend(element, setActiveSite=True)

N.B. – a “core” method, not to be used by general users. Run .append() instead.

Low level appending; like coreInsert does not error check, determine elements changed, or similar operations.

When using this method, the caller is responsible for calling Stream.coreElementsChanged after all operations are completed.

StreamCoreMixin.coreElementsChanged(*, updateIsFlat=True, clearIsSorted=True, memo=None, keepIndex=False)

NB – a “core” stream method that is not necessary for most users.

This method is called automatically any time the elements in the Stream are changed. However, it may be called manually in case sites or other advanced features of an element have been modified. It was previously a private method and for most users should still be treated as such.

The various arguments permit optimizing the clearing of cached data in situations when completely dropping all cached data is excessive.

>>> a = stream.Stream()
>>> a.isFlat
True

Here we manipulate the private ._elements storage (which generally shouldn’t be done) and thus need to call .coreElementsChanged directly.

>>> a._elements.append(stream.Stream())
>>> a.isFlat # this is wrong.
True
>>> a.coreElementsChanged()
>>> a.isFlat
False
StreamCoreMixin.coreGatherMissingSpanners(recurse=True, requireAllPresent=True, insert=True)

find all spanners that are referenced by elements in the (recursed if recurse=True) stream and either inserts them in the Stream (if insert is True) or returns them if insert is False.

If requireAllPresent is True (default) then only those spanners whose complete spanned elements are in the Stream are returned.

Because spanners are stored weakly in .sites this is only guaranteed to find the spanners in cases where the spanner is in another stream that is still active.

Here’s a little helper function since we’ll make the same Stream several times:

>>> def getStream():
...    s = stream.Stream()
...    n = note.Note('C')
...    m = note.Note('D')
...    sl = spanner.Slur(n, m)
...    n.bogusAttributeNotWeakref = sl # prevent garbage collecting sl
...    s.append([n, m])
...    return s
>>> s = getStream()
>>> s.show('text')
{0.0} <music21.note.Note C>
{1.0} <music21.note.Note D>
>>> s.coreGatherMissingSpanners()
>>> s.show('text')
{0.0} <music21.note.Note C>
{0.0} <music21.spanner.Slur <music21.note.Note C><music21.note.Note D>>
{1.0} <music21.note.Note D>

Insert is False:

>>> s = getStream()
>>> spList = s.coreGatherMissingSpanners(insert=False)
>>> spList
[<music21.spanner.Slur <music21.note.Note C><music21.note.Note D>>]
>>> s.show('text')
{0.0} <music21.note.Note C>
{1.0} <music21.note.Note D>

Not all elements are present:

>>> s = getStream()
>>> s.remove(s[-1])
>>> s.show('text')
{0.0} <music21.note.Note C>
>>> s.coreGatherMissingSpanners()
>>> s.show('text')
{0.0} <music21.note.Note C>
>>> s.coreGatherMissingSpanners(requireAllPresent=False)
>>> s.show('text')
{0.0} <music21.note.Note C>
{0.0} <music21.spanner.Slur <music21.note.Note C><music21.note.Note D>>

Test recursion:

>>> t = stream.Part()
>>> s = getStream()
>>> t.insert(0, s)
>>> t.coreGatherMissingSpanners(recurse=False)
>>> t.show('text')
{0.0} <music21.stream.Stream 0x104935b00>
    {0.0} <music21.note.Note C>
    {1.0} <music21.note.Note D>

Default: with recursion:

>>> t.coreGatherMissingSpanners()
>>> t.show('text')
{0.0} <music21.stream.Stream 0x104935b00>
    {0.0} <music21.note.Note C>
    {1.0} <music21.note.Note D>
{0.0} <music21.spanner.Slur <music21.note.Note C><music21.note.Note D>>

Make sure that spanners already in the stream are not put there twice:

>>> s = getStream()
>>> sl = s[0].getSpannerSites()[0]
>>> s.insert(0, sl)
>>> s.coreGatherMissingSpanners()
>>> s.show('text')
{0.0} <music21.note.Note C>
{0.0} <music21.spanner.Slur <music21.note.Note C><music21.note.Note D>>
{1.0} <music21.note.Note D>

And with recursion?

>>> t = stream.Part()
>>> s = getStream()
>>> sl = s[0].getSpannerSites()[0]
>>> s.insert(0, sl)
>>> t.insert(0, s)
>>> t.coreGatherMissingSpanners()
>>> t.show('text')
{0.0} <music21.stream.Stream 0x104935b00>
    {0.0} <music21.note.Note C>
    {0.0} <music21.spanner.Slur <music21.note.Note C><music21.note.Note D>>
    {1.0} <music21.note.Note D>
StreamCoreMixin.coreGetElementByMemoryLocation(objId)

NB – a “core” stream method that is not necessary for most users.

Low-level tool to get an element based only on the object id.

This is not the same as getElementById, which refers to the id attribute which may be manually set and not unique.

However, some implementations of python will reuse object locations, sometimes quickly, so don’t keep these around.

Used by spanner and variant.

>>> s = stream.Stream()
>>> n1 = note.Note('g')
>>> n2 = note.Note('g#')
>>> s.append(n1)
>>> s.coreGetElementByMemoryLocation(id(n1)) is n1
True
>>> s.coreGetElementByMemoryLocation(id(n2)) is None
True
>>> b = bar.Barline()
>>> s.storeAtEnd(b)
>>> s.coreGetElementByMemoryLocation(id(b)) is b
True
StreamCoreMixin.coreGuardBeforeAddElement(element, checkRedundancy=True)

Before adding an element, this method provides important checks to that element.

Used by both insert() and append()

Returns None or raises a StreamException

>>> s = stream.Stream()
>>> s.coreGuardBeforeAddElement(s)
Traceback (most recent call last):
music21.exceptions21.StreamException: this Stream cannot be contained within itself
StreamCoreMixin.coreHasElementByMemoryLocation(objId)

NB – a “core” stream method that is not necessary for most users. use hasElement(obj)

Return True if an element object id, provided as an argument, is contained in this Stream.

>>> s = stream.Stream()
>>> n1 = note.Note('g')
>>> n2 = note.Note('g#')
>>> s.append(n1)
>>> s.coreHasElementByMemoryLocation(id(n1))
True
>>> s.coreHasElementByMemoryLocation(id(n2))
False
StreamCoreMixin.coreInsert(offset, element, *, ignoreSort=False, setActiveSite=True)

N.B. – a “core” method, not to be used by general users. Run .insert() instead.

A faster way of inserting elements that does no checks, just insertion.

Only be used in contexts that we know we have a proper, single Music21Object. Best for usage when taking objects in a known Stream and creating a new Stream

When using this method, the caller is responsible for calling Stream.coreElementsChanged after all operations are completed.

Do not mix coreInsert with coreAppend operations.

Returns boolean if the Stream is now sorted.

StreamCoreMixin.coreStoreAtEnd(element, setActiveSite=True)

NB – this is a “core” method. Use .storeAtEnd() instead.

Core method for adding end elements. To be called by other methods.