.. _moduleHumdrum.spineParser:

music21.humdrum.spineParser
===========================

.. WARNING: DO NOT EDIT THIS FILE: AUTOMATICALLY GENERATED. Edit the .py file directly

.. module:: music21.humdrum.spineParser


music21.humdrum.spineParser is a collection of utilities for changing
native humdrum code into music21 streams.  Most music21 users will
simply want to call:




>>> from music21 import *
>>> myFile = converter.parse('myfile.krn')
>>> myFile.show()


The methods in here are documented for developers wishing to expand
music21's ability to parse humdrum.

SpineParsing consists of several steps.

* The data file is read in and all events are sliced horizontally (EventCollections) and vertically (Protospines)
* Protospines are parsed into HumdrumSpines by following Spine Path Indicators (:samp:`*^` and :samp:`*v` especially)
    Protospines that separate become new Protospines with their parentSpine indicated.  Protospines
    that merge again then followed by the same Protospine as before.  This will cause problems if
    a voice remerges with another staff, but in practice I have not seen a .krn file that does this and
    should be avoided in any case.
* HumdrumSpines are reclassed according to their exclusive definition.  :samp:`**kern` becomes KernSpines, etc.
* All reclassed HumdrumSpines are filled with music21 objects in their .stream property.
    Measures are put into the spine but are empty containers.  The resulting
    HumdrumSpine.stream objects
    look like Stream.semiFlat versions in many ways.
* For HumdrumSpines with parent spines their .stream contents are then inserted into their parent spines with
    voice tagged as a music21 Group property.
* Lyrics and Dynamics are placed into their corresponding HumdrumSpine.stream objects
* Stream elements are moved into their measures within a Stream
* Measures are searched for elements with voice groups and Voice objects are created





.. function:: hdStringToMeasure(contents, previousMeasure=None)


    kern uses an equals sign followed by processing instructions to
    create new measures.  Here is how...



.. function:: hdStringToNote(contents)


    returns a music21.note.Note (or Rest or Unpitched, etc.)
    matching the current SpineEvent.
    Does not check to see that it is sane or part of a :samp:`**kern` spine, etc.


    New rhythmic extensions defined in
    http://wiki.humdrum.org/index.php/Rational_rhythms
    are fully implemented:




    >>> n = hdStringToNote("CC3%2")
    >>> n.duration.quarterLength
    2.6666666...
    >>> n.duration.fullName
    'Whole Triplet (2.67QL)'
    ⁠ 
    >>> n = hdStringToNote("e-00.")
    >>> n.duration.quarterLength
    24.0
    >>> n.duration.fullName
    'Perfect Longa'



    >>> n = hdStringToNote("F#000")
    >>> n.duration.quarterLength
    32.0
    >>> n.duration.fullName
    'Imperfect Maxima'


    Note that this is one note in the time of a double-dotted quarter,
    not a double-dotted quarter-note triplet (incorrectly used in
    http://kern.ccarh.org/cgi-bin/ksdata?l=musedata/mozart/quartet&file=k421-01.krn&f=kern
    but contradicts the specification in
    http://www.lib.virginia.edu/artsandmedia/dmmc/Music/Humdrum/kern_hlp.html#tuplets



    >>> n = hdStringToNote("6..fff")
    >>> n.duration.quarterLength
    1.166666...
    >>> n.duration.dots
    0
    >>> n.duration.tuplets[0].durationNormal.dots
    2



.. function:: kernTandamToObject(tandam)


    Kern uses symbols such as :samp:`*M5/4` and :samp:`*clefG2`, etc., to control processing

    This method converts them to music21 objects.



    >>> from music21 import *
    >>> m = humdrum.spineParser.kernTandamToObject('*M3/1')
    >>> m
    <music21.meter.TimeSignature 3/1>


    Unknown objects are converted to MiscTandem objects:



    >>> m2 = humdrum.spineParser.kernTandamToObject('*TandyUnk')
    >>> m2
    <music21.humdrum.spineParser.MiscTandam *TandyUnk humdrum control>



DynamSpine
----------

Inherits from: :class:`~music21.humdrum.spineParser.HumdrumSpine`

.. class:: DynamSpine(id=0, eventList=None, streamClass=<class 'music21.stream.Stream'>)


    A DynamSpine is a type of humdrum spine with the \*\*dynam
    attribute set and thus events are processed as if they
    are dynamics.




EventCollection
---------------



.. class:: EventCollection(maxSpines=0)


    An EventCollection is a time slice of all events that have
    an onset of a certain time.  If an event does not occur at
    a certain time, then you should check EventCollection[n].lastEvents
    to get the previous event.  (If it is a note, it is the note
    still sounding, etc.).  The happeningEvent method gets either
    currentEvent or lastEvent.


    These objects normally get created by
    :meth:`~music21.humdrum.spineParser.HumdrumDataCollection.parseProtoSpinesAndEventCollections`
    so you won't need to do all the setup.


    Assume that ec1 is
         C4     pp

    and ec2 is:
         D4     .





    >>> from music21 import *
    >>> SE = humdrum.spineParser.SpineEvent
    >>> eventList1 = [SE('C4'),SE('pp')]
    >>> eventList2 = [SE('D4'),SE('.')]
    >>> ec1 = humdrum.spineParser.EventCollection(maxSpines = 2)
    >>> ec1.events = eventList1
    >>> ec2 = humdrum.spineParser.EventCollection(maxSpines = 2)
    >>> ec2.events = eventList2
    >>> ec2.lastEvents[1] = eventList1[1]
    >>> ec2.maxSpines
    2
    >>> ec2.getAllOccurring()
    [<music21.humdrum.spineParser.SpineEvent D4>, <music21.humdrum.spineParser.SpineEvent pp>]





    **EventCollection** **attributes**

        Attributes without Documentation: `lastEvents`, `maxSpines`, `events`, `spinePathData`

    **EventCollection** **methods**

        .. method:: addGlobalEvent(globalEvent)

            No documentation.


        .. method:: addLastSpineEvent(spineNum, spineEvent)

            No documentation.


        .. method:: addSpineEvent(spineNum, spineEvent)

            No documentation.


        .. method:: getAllOccurring()

            No documentation.


        .. method:: getSpineEvent(spineNum)

            No documentation.


        .. method:: getSpineOccurring(spineNum)

            No documentation.



GlobalComment
-------------

Inherits from: :class:`~music21.humdrum.spineParser.HumdrumLine`

.. class:: GlobalComment(position=0, contents='')


    A GlobalComment is a humdrum comment that pertains to all spines
    In humdrum it is represented by two exclamation points (and usually one space)


    The GlobalComment object takes two inputs and stores them as attributes::


        position (line number in the humdrum file)
        contents (string of contents)
        value    (contents minus !!)


    The constructor can be passed (position, contents)
    if contents begins with bangs, they are removed along with up to one space directly afterwards




    >>> from music21 import *
    >>> com1 = music21.humdrum.spineParser.GlobalComment(
    ...          position = 4, contents='!! this comment is global')
    >>> com1.position
    4
    >>> com1.contents
    '!! this comment is global'
    >>> com1.value
    'this comment is global'




    **GlobalComment** **attributes**

        Attributes without Documentation: `contents`, `isComment`, `isGlobal`, `isSpineLine`, `numSpines`, `position`, `value`

        Attributes inherited from :class:`~music21.humdrum.spineParser.HumdrumLine`: :attr:`~music21.humdrum.spineParser.HumdrumLine.isReference`


GlobalReference
---------------

Inherits from: :class:`~music21.humdrum.spineParser.HumdrumLine`

.. class:: GlobalReference(position=0, contents='!!! NUL: None')


    A GlobalReference is a type of HumdrumLine that contains
    information about the humdrum document.


    In humdrum it is represented by three exclamation points
    followed by non-whitespace followed by a colon.  Examples::

        !!!COM: Stravinsky, Igor Fyodorovich
        !!!CDT: 1882/6/17/-1971/4/6
        !!!ODT: 1911//-1913//; 1947//
        !!!OPT@@RUS: Vesna svyashchennaya
        !!!OPT@FRE: Le sacre du printemps

    The GlobalReference object takes two inputs::

        position   line number in the humdrum file
        contents   string of contents


    And stores them as three attributes::

        position: as above
        code:     non-whitespace code (usually three letters)
        contents: string of contents




    >>> from music21 import *
    >>> gr = music21.humdrum.spineParser.GlobalReference(
    ...        position = 20, contents = "!!!COM: Stravinsky, Igor Fyodorovich\n")
    >>> gr.position
    20
    >>> gr.code
    'COM'
    >>> gr.value
    'Stravinsky, Igor Fyodorovich'


    TODO: add parsing of three-digit Kern comment codes into fuller metadata



    **GlobalReference** **attributes**

        Attributes without Documentation: `contents`, `isComment`, `isGlobal`, `isReference`, `isSpineLine`, `numSpines`, `position`, `code`, `value`


HumdrumDataCollection
---------------------



.. class:: HumdrumDataCollection(dataStream=[])


    A HumdrumDataCollection takes in a mandatory list where each element
    is a line of humdrum data.  Together this list represents a collection
    of spines.  Essentially it's the contents of a humdrum file.


    Usually you will probably want to use HumdrumFile which can read
    in a file directly.  This class exists in case you have your Humdrum
    data in another format (database, from the web, etc.) and already
    have it as a string.


    You are probably better off running humdrum.parseFile("filename")
    which returns a humdrum.SpineCollection directly, or even better,
    converter.parse("file.krn") which will just give you a stream.Score
    instead.



    LIMITATIONS:
    (1) Spines cannot change definition (\*\*exclusive interpretations) mid-spine.

        So if you start off with \*\*kern, the rest of the spine needs to be
        \*\*kern (actually, the first exclusive interpretation for a spine is
        used throughout)

        Note that, even though changing exclusive interpretations mid-spine
        seems to be legal by the humdrum definition, it looks like none of the
        conventional humdrum parsing tools allow for changing
        definitions mid-spine, so I don't think this limitation is a problem.
        (Craig Stuart Sapp confirmed this to me)

        The Aarden/Miller Palestrina dataset uses `\*-` followed by `\*\*kern`
        at the changes of sections thus some parsing of multiple exclusive
        interpretations in a protospine may be necessary.

    (2) Split spines are assumed to be voices in a single spine staff.





    **HumdrumDataCollection** **attributes**

        .. attribute:: spineCollection


            A SpineCollection is a set of HumdrumSpines with relationships to each
            other and where their position attributes indicate
            simultaneous onsets.


            When you iterate over a SpineCollection, it goes from right to
            left, since that's the order that humdrum expects.



        Attributes without Documentation: `parsedLines`, `dataStream`, `eventList`, `maxSpines`, `parsePositionInStream`, `protoSpines`, `eventCollections`, `fileLength`

    **HumdrumDataCollection** **properties**

        .. attribute:: stream

            No documentation.


    **HumdrumDataCollection** **methods**

        .. method:: createHumdrumSpines(protoSpines=None, eventCollections=None)


            Takes the data from the object's protoSpines and eventCollections
            and returns a :class:`~music21.humdrum.spineParser.SpineCollection`
            object that contains HumdrumSpine() objects.


            A HumdrumSpine object differs from a ProtoSpine in that it follows
            spinePathData -- a ProtoSpine records all data in a given tab
            position, and thus might consist of data from several
            spines that move around.  HumdrumSpines are smart enough not to
            have this limitation.


            When we check for spinePathData we look for the following spine
            path indicators (from HumdrumDoc)::


                *+    add a new spine (to the right of the current spine)
                *-    terminate a current spine
                *^    split a spine (into two)
                *v    join (two or more) spines into one
                *x    exchange the position of two spines
                *     do nothing





        .. method:: parseEventListFromDataStream(dataStream=None)


            Sets self.eventList from a dataStream (that is, a
            list of lines).  It sets self.maxSpines to the
            largest number of spine events found on any line
            in the file.


            It sets self.fileLength to the number of lines (excluding
            totally blank lines) in the file.


            The difference between the dataStream and self.eventList
            are the following:

                * Blank lines are skipped.
                * !!! lines become :class:`~music21.humdrum.spineParser.GlobalReference` objects
                * !! lines become :class:`~music21.humdrum.spineParser.GlobalComment` objects
                * all other lines become :class:`~music21.humdrum.spineParser.SpineLine` objects


            Returns eventList in addition to setting it as self.eventList.




            >>> from music21 import *
            >>> eventString = "!!! COM: Beethoven, Ludwig van\n" + \
            ...               "!! Not really a piece by Beethoven\n" + \
            ...               "**kern\t**dynam\n" + \
            ...               "C4\tpp\n" + \
            ...               "D8\t.\n"
            >>> hdc = music21.humdrum.spineParser.HumdrumDataCollection(eventString)
            >>> eList = hdc.parseEventListFromDataStream()
            >>> eList is hdc.eventList
            True
            >>> for e in eList:
            ...     print e
            <music21.humdrum.spineParser.GlobalReference object at 0x...>
            <music21.humdrum.spineParser.GlobalComment object at 0x...>
            <music21.humdrum.spineParser.SpineLine object at 0x...>
            <music21.humdrum.spineParser.SpineLine object at 0x...>
            <music21.humdrum.spineParser.SpineLine object at 0x...>
            >>> print eList[0].value
            Beethoven, Ludwig van
            >>> print eList[3].spineData
            ['C4', 'pp']



        .. method:: parseLines(dataStream=None)


            Parse a list (dataStream) of lines into a HumdrumSpineCollection
            (which contains HumdrumSpines)
            and set it in self.spineCollection


            if dataStream is None, look for it in self.dataStream.  If that's None too,
            return an exception.




        .. method:: parseProtoSpinesAndEventCollections()


            Run after :meth:`~music21.humdrum.spineParser.HumdrumDataCollection.parseEventListFromDataStream()`
            to take self.eventList and slice it horizontally
            to get self.eventCollections, which is a list of
            EventCollection objects, or things that happen simultaneously.


            And, more importantly, this method slices self.eventList
            vertically to get self.protoSpines which is a list
            of ProtoSpines, that is a vertical slice of everything that
            happens in a column, regardless of spine-path indicators.


            EventCollection objects store global events at the position.
            ProtoSpines do not.


            So self.eventCollections and self.protoSpines can each be
            thought of as a two-dimensional sheet of cells, but where
            the first index of the former is the vertical position in
            the dataStream and the first index of the later is the
            horizontal position in the dataStream.  The contents of
            each cell is a SpineEvent object or None (if there's no
            data at that point).  Even '.' (continuation events) get
            translated into SpineEvent objects.


            Calls :meth:`~music21.humdrum.spineParser.parseEventListFromDataStream`
            if it hasn't already been called.


            returns a tuple of protoSpines and eventCollections in addition to
            setting it in the calling object.




            >>> from music21 import *
            >>> eventString = "!!! COM: Beethoven, Ludwig van\n" + \
            ...               "!! Not really a piece by Beethoven\n" + \
            ...               "**kern\t**dynam\n" + \
            ...               "C4\tpp\n" + \
            ...               "D8\t.\n"
            >>> hdc = music21.humdrum.spineParser.HumdrumDataCollection(eventString)
            >>> protoSpines, eventCollections = hdc.parseProtoSpinesAndEventCollections()
            >>> protoSpines is hdc.protoSpines
            True
            >>> eventCollections is hdc.eventCollections
            True


            Looking at individual slices is unlikely to tell you much.




            >>> for thisSlice in eventCollections:
            ...    print thisSlice
            <music21.humdrum.spineParser.EventCollection object at 0x...>
            <music21.humdrum.spineParser.EventCollection object at 0x...>
            <music21.humdrum.spineParser.EventCollection object at 0x...>
            <music21.humdrum.spineParser.EventCollection object at 0x...>
            <music21.humdrum.spineParser.EventCollection object at 0x...>
            ⁠ 
            >>> for thisSlice in protoSpines:
            ...    print thisSlice
            <music21.humdrum.spineParser.ProtoSpine object at 0x...>
            <music21.humdrum.spineParser.ProtoSpine object at 0x...>


            But looking at the individual slices is revealing:




            >>> eventCollections[4].getAllOccurring()
            [<music21.humdrum.spineParser.SpineEvent D8>, <music21.humdrum.spineParser.SpineEvent pp>]







HumdrumFile
-----------

Inherits from: :class:`~music21.humdrum.spineParser.HumdrumDataCollection`

.. class:: HumdrumFile(filename=None)


    A HumdrumFile is a HumdrumDataCollection which takes
    as a mandatory argument a filename to be opened and read.



    **HumdrumFile** **attributes**

        Attributes inherited from :class:`~music21.humdrum.spineParser.HumdrumDataCollection`: :attr:`~music21.humdrum.spineParser.HumdrumDataCollection.parsedLines`

    **HumdrumFile** **properties**

        Properties inherited from :class:`~music21.humdrum.spineParser.HumdrumDataCollection`: :attr:`~music21.humdrum.spineParser.HumdrumDataCollection.stream`

    **HumdrumFile** **methods**

        .. method:: parseFH(fileHandle)


            parseFH takes a fileHandle and returns a HumdrumCollection



        Methods inherited from :class:`~music21.humdrum.spineParser.HumdrumDataCollection`: :meth:`~music21.humdrum.spineParser.HumdrumDataCollection.createHumdrumSpines`, :meth:`~music21.humdrum.spineParser.HumdrumDataCollection.parseEventListFromDataStream`, :meth:`~music21.humdrum.spineParser.HumdrumDataCollection.parseLines`, :meth:`~music21.humdrum.spineParser.HumdrumDataCollection.parseProtoSpinesAndEventCollections`


HumdrumLine
-----------



.. class:: HumdrumLine


    HumdrumLine is a dummy class for subclassing
    :class:`~music21.humdrum.spineParser.SpineLine`,
    :class:`~music21.humdrum.spineParser.GlobalComment`, and
    :class:`~music21.humdrum.spineParser.GlobalReference` classes
    all of which represent one horizontal line of
    text in a :class:`~music21.humdrum.spineParser.HumdrumDataCollection`
    that is aware of its
    position in the file.


    See the documentation for the specific classes mentioned above
    for more details.



    **HumdrumLine** **attributes**

        Attributes without Documentation: `isComment`, `isGlobal`, `isReference`, `position`


HumdrumSpine
------------



.. class:: HumdrumSpine(id=0, eventList=None, streamClass=<class 'music21.stream.Stream'>)


    A HumdrumSpine is a representation of a generic HumdrumSpine
    regardless of \*\*definition after spine path indicators have
    been simplified.


    A HumdrumSpine is a collection of events arranged vertically that have a
    connection to each other.
    Each HumdrumSpine MUST have an id (numeric or string) attached to it.




    >>> from music21 import *
    >>> SE = music21.humdrum.spineParser.SpineEvent
    >>> spineEvents = [SE('**kern'),SE('c,4'), SE('d#8')]
    >>> spine1Id = 5
    >>> spine1 = music21.humdrum.spineParser.HumdrumSpine(spine1Id, spineEvents)
    >>> spine1.insertPoint = 5
    >>> spine1.endingPosition = 6
    >>> spine1.parentSpine = 3  # spine 3 is the previous spine leading to this one
    >>> spine1.childSpines = [7,8] # the spine ends by being split into spines 7 and 8


    we keep weak references to the spineCollection so that we
    don't have circular references




    >>> spineCollection1 = music21.humdrum.spineParser.SpineCollection()
    >>> spine1.spineCollection = spineCollection1


    The spineType property searches the EventList or parentSpine to
    figure out the spineType




    >>> spine1.spineType
    'kern'


    Spines can be iterated through:




    >>> for e in spine1:
    ...    print e
    **kern
    c,4
    d#8


    If you'd eventually like this spine to be converted to a class
    other than :class:`~music21.stream.Stream`, pass its classname in
    as the streamClass argument:




    >>> spine2 = music21.humdrum.spineParser.HumdrumSpine(
    ...              streamClass = music21.stream.Part)
    >>> spine2.stream
    <music21.stream.Part ...>




    **HumdrumSpine** **attributes**

        .. attribute:: stream


            This is the fundamental container for Music21Objects;
            objects may be ordered and/or placed in time based on
            offsets from the start of this container.

            As a subclass of Music21Object, Streams have offsets,
            priority, id, and groups.

            Streams may be embedded within other Streams. As each Stream can have its own offset, when Streams are embedded the offset of an element is relatively only to its parent Stream. The :attr:`~music21.stream.Stream.flat` property provides access to a flat representation of all embedded Streams, with offsets relative to the top-level Stream.

            The Stream :attr:`~music21.stream.Stream.elements` attribute provides the contents of the Stream as a list. Direct access to, and manipulation of, the elements list is not recommended. Instead, use the host of high-level methods available.

            The Stream, like all Music21Objects, has a :class:`music21.duration.Duration` that is usually the
            "release" time of the chronologically last element in the Stream (that is,
            the highest onset plus the duration of any element in the Stream).
            The duration, however, can be "unlinked" and explicitly set independent of the Stream's contents.

            The first element passed to the Stream is an optional list,
            tuple, or other Stream of music21 objects which is used to
            populate the Stream by inserting each object at its :attr:`~music21.base.Music21Object.offset`
            property. Other arguments and keywords are ignored, but are
            allowed so that subclassing the Stream is easier.




            >>> from music21 import *
            >>> s1 = stream.Stream()
            >>> s1.append(note.HalfNote('C#4'))
            >>> s1.append(note.QuarterNote('D5'))
            >>> s1.duration.quarterLength
            3.0
            >>> for thisNote in s1.notes:
            ...     print thisNote.octave
            4
            5


            This is a demonstration of creating a Stream with other elements,
            including embedded Streams (in this case, :class:`music21.stream.Part`,
            a Stream subclass):




            >>> c1 = clef.TrebleClef()
            >>> c1.offset = 0.0
            >>> n1 = note.EighthNote("E-6")
            >>> n1.offset = 1.0
            >>> p1 = stream.Part()
            >>> p1.offset = 0.0
            >>> p1.id = 'embeddedPart'
            >>> p1.append(note.Rest()) # quarter rest
            >>> s2 = stream.Stream([c1, n1, p1])
            >>> s2.duration.quarterLength
            1.5
            >>> s2.show('text')
            {0.0} <music21.clef.TrebleClef>
            {0.0} <music21.stream.Part embeddedPart>
                {0.0} <music21.note.Rest rest>
            {1.0} <music21.note.Note E->





        Attributes without Documentation: `insertPoint`, `childSpines`, `parentSpine`, `measuresMoved`, `parsed`, `eventList`, `childSpineInsertPoints`, `insertionsDone`, `endingPosition`, `id`, `isLastSpine`

    **HumdrumSpine** **properties**

        .. attribute:: spineCollection

            No documentation.


        .. attribute:: spineType


            searches the current and parent spineType for a search



    **HumdrumSpine** **methods**

        .. method:: append(event)


            add an item to this Spine



        .. method:: moveElementsIntoMeasures(streamIn)


            takes a parsed stream and moves the elements inside the
            measures.  Works with pickup measures, etc. Does not
            automatically create ties, etc...

            Why not just use Stream.makeMeasures()? because
            humdrum measures contain extra information about barlines
            etc.



            >>> from music21 import *
            >>> s1 = stream.Stream()
            >>> s1.append(meter.TimeSignature('2/4'))
            >>> m1 = stream.Measure()
            >>> m1.number = 1
            >>> s1.append(m1)
            >>> s1.append(note.HalfNote('C4'))
            >>> m2 = stream.Measure()
            >>> m2.number = 2
            >>> s1.append(m2)
            >>> s1.append(note.HalfNote('D4'))
            >>> s1.show('text')
            {0.0} <music21.meter.TimeSignature 2/4>
            {0.0} <music21.stream.Measure 1 offset=0.0>
            <BLANKLINE>
            {0.0} <music21.note.Note C>
            {2.0} <music21.stream.Measure 2 offset=2.0>
            <BLANKLINE>
            {2.0} <music21.note.Note D>
            ⁠ 
            >>> hds = humdrum.spineParser.HumdrumSpine()
            >>> s2 = hds.moveElementsIntoMeasures(s1)
            >>> s2.show('text')
            {0.0} <music21.stream.Measure 1 offset=0.0>
                {0.0} <music21.meter.TimeSignature 2/4>
                {0.0} <music21.note.Note C>
            {2.0} <music21.stream.Measure 2 offset=2.0>
                {0.0} <music21.note.Note D>



        .. method:: next()

            Returns the current event and increments the iteration index.


        .. method:: parse()


            Dummy method that pushes all these objects to HumdrumSpine.stream
            as ElementWrappers.  Should be overridden in
            specific Spine subclasses.




KernSpine
---------

Inherits from: :class:`~music21.humdrum.spineParser.HumdrumSpine`

.. class:: KernSpine(id=0, eventList=None, streamClass=<class 'music21.stream.Stream'>)


    A KernSpine is a type of humdrum spine with the \*\*kern
    attribute set and thus events are processed as if they
    are kern notes




MiscTandam
----------

Inherits from: :class:`~music21.base.Music21Object`, :class:`~music21.base.JSONSerializer`

.. class:: MiscTandam(tandam='')


    **MiscTandam** **attributes**

        Attributes without Documentation: `tandam`

        Attributes inherited from :class:`~music21.base.Music21Object`: :attr:`~music21.base.Music21Object.classSortOrder`, :attr:`~music21.base.Music21Object.isSpanner`, :attr:`~music21.base.Music21Object.isStream`, :attr:`~music21.base.Music21Object.isVariant`, :attr:`~music21.base.Music21Object.hideObjectOnPrint`, :attr:`~music21.base.Music21Object.groups`, :attr:`~music21.base.Music21Object.id`

    **MiscTandam** **properties**

        Properties inherited from :class:`~music21.base.Music21Object`: :attr:`~music21.base.Music21Object.activeSite`, :attr:`~music21.base.Music21Object.beat`, :attr:`~music21.base.Music21Object.beatDuration`, :attr:`~music21.base.Music21Object.beatStr`, :attr:`~music21.base.Music21Object.beatStrength`, :attr:`~music21.base.Music21Object.classes`, :attr:`~music21.base.Music21Object.derivationHierarchy`, :attr:`~music21.base.Music21Object.duration`, :attr:`~music21.base.Music21Object.isGrace`, :attr:`~music21.base.Music21Object.measureNumber`, :attr:`~music21.base.Music21Object.offset`, :attr:`~music21.base.Music21Object.priority`, :attr:`~music21.base.Music21Object.seconds`

        Properties inherited from :class:`~music21.base.JSONSerializer`: :attr:`~music21.base.JSONSerializer.json`

    **MiscTandam** **methods**

        Methods inherited from :class:`~music21.base.Music21Object`: :meth:`~music21.base.Music21Object.searchActiveSiteByAttr`, :meth:`~music21.base.Music21Object.getContextAttr`, :meth:`~music21.base.Music21Object.setContextAttr`, :meth:`~music21.base.Music21Object.addContext`, :meth:`~music21.base.Music21Object.addLocation`, :meth:`~music21.base.Music21Object.addLocationAndActiveSite`, :meth:`~music21.base.Music21Object.freezeIds`, :meth:`~music21.base.Music21Object.getAllContextsByClass`, :meth:`~music21.base.Music21Object.getCommonSiteIds`, :meth:`~music21.base.Music21Object.getCommonSites`, :meth:`~music21.base.Music21Object.getContextByClass`, :meth:`~music21.base.Music21Object.getOffsetBySite`, :meth:`~music21.base.Music21Object.getSiteIds`, :meth:`~music21.base.Music21Object.getSites`, :meth:`~music21.base.Music21Object.getSpannerSites`, :meth:`~music21.base.Music21Object.hasContext`, :meth:`~music21.base.Music21Object.hasSite`, :meth:`~music21.base.Music21Object.hasSpannerSite`, :meth:`~music21.base.Music21Object.hasVariantSite`, :meth:`~music21.base.Music21Object.isClassOrSubclass`, :meth:`~music21.base.Music21Object.mergeAttributes`, :meth:`~music21.base.Music21Object.next`, :meth:`~music21.base.Music21Object.previous`, :meth:`~music21.base.Music21Object.purgeLocations`, :meth:`~music21.base.Music21Object.purgeOrphans`, :meth:`~music21.base.Music21Object.purgeUndeclaredIds`, :meth:`~music21.base.Music21Object.removeLocationBySite`, :meth:`~music21.base.Music21Object.removeLocationBySiteId`, :meth:`~music21.base.Music21Object.setOffsetBySite`, :meth:`~music21.base.Music21Object.show`, :meth:`~music21.base.Music21Object.splitAtDurations`, :meth:`~music21.base.Music21Object.splitAtQuarterLength`, :meth:`~music21.base.Music21Object.splitByQuarterLengths`, :meth:`~music21.base.Music21Object.unfreezeIds`, :meth:`~music21.base.Music21Object.unwrapWeakref`, :meth:`~music21.base.Music21Object.wrapWeakref`, :meth:`~music21.base.Music21Object.write`

        Methods inherited from :class:`~music21.base.JSONSerializer`: :meth:`~music21.base.JSONSerializer.jsonAttributes`, :meth:`~music21.base.JSONSerializer.jsonComponentFactory`, :meth:`~music21.base.JSONSerializer.jsonPrint`, :meth:`~music21.base.JSONSerializer.jsonRead`, :meth:`~music21.base.JSONSerializer.jsonWrite`


ProtoSpine
----------



.. class:: ProtoSpine(eventList=None)


    A ProtoSpine is a collection of events arranged vertically.
    It differs from a HumdrumSpine in that spine paths are not followed.
    So ProtoSpine(1) would be everything in the 2nd column
    of a Humdrum file regardless of whether the 2nd column
    was at some point an independent Spine
    or if it later became a split from the first spine.


    See :meth:`~music21.humdrum.spineParser.parseProtoSpinesAndEventCollections`
    for more details on how ProtoSpine objects are created.



    **ProtoSpine** **attributes**

        Attributes without Documentation: `eventList`


SpineCollection
---------------



.. class:: SpineCollection()


    A SpineCollection is a set of HumdrumSpines with relationships to each
    other and where their position attributes indicate
    simultaneous onsets.


    When you iterate over a SpineCollection, it goes from right to
    left, since that's the order that humdrum expects.



    **SpineCollection** **attributes**

        Attributes without Documentation: `spines`, `nextFreeId`, `spineReclassDone`

    **SpineCollection** **methods**

        .. method:: addSpine(streamClass=<class 'music21.stream.Part'>)


            creates a new spine in the collection and returns it.


            By default, the underlying music21 class of the spine is
            :class:`~music21.stream.Part`.  This can be overridden
            by passing in a different streamClass.


            Automatically sets the id of the Spine.




            >>> from music21 import *
            >>> hsc = music21.humdrum.spineParser.SpineCollection()
            >>> newSpine = hsc.addSpine()
            >>> newSpine.id
            0
            >>> newSpine.stream
            <music21.stream.Part ...>
            >>> newSpine2 = hsc.addSpine(streamClass = music21.stream.Stream)
            >>> newSpine2.id
            1
            >>> newSpine2
            Spine: 1
            >>> newSpine2.stream
            <music21.stream.Stream ...>





        .. method:: appendSpine(spine)


            appendSpine(spine) -- appends an already existing HumdrumSpine
            to the SpineCollection.  Returns void



        .. method:: createMusic21Streams()

            No documentation.


        .. method:: getOffsetsAndPrioritiesByPosition()


            iterates through the spines by location
            and records the offset and priority for each

            NOT IMPLEMENTED



        .. method:: getSpineById(id)


            returns the HumdrumSpine with the given id.

            raises a HumdrumException if the spine with a given id is not found



        .. method:: makeVoices()


            make voices for each kernSpine -- why not just run
            stream.makeVoices() ? because we have more information
            here that lets us make voices more intelligently

            Should be done after measures have been made.



        .. method:: moveDynamicsAndLyricsToStreams()


            move :samp:`**dynam` and :samp:`**lyrics/**text` information to the appropriate staff.

            Assumes that :samp:`*staff` is consistent through the spine.



        .. method:: moveObjectsToMeasures()


            run moveElementsIntoMeasures for each HumdrumSpine
            that is not a subspine



        .. method:: next()

            Returns the current spine and decrements the iteration index.


        .. method:: parseMusic21()


            runs spine.parse() for each Spine.
            thus populating the spine.stream for each Spine



        .. method:: performInsertions()


            take a parsed spineCollection as music21 objects and take
            subspines and put them in their proper location



        .. method:: reclassSpines()


            changes the classes of HumdrumSpines to more specific types
            (KernSpine, DynamicSpine)
            according to their spineType (e.g., \*\*kern, \*\*dynam)



        .. method:: removeSpineById(id)


            deletes a spine from the SpineCollection (after inserting, integrating, etc.)



            >>> hsc = music21.humdrum.spineParser.SpineCollection()
            >>> newSpine = hsc.addSpine()
            >>> newSpine.id
            0
            >>> newSpine2 = hsc.addSpine()
            >>> newSpine2.id
            1
            >>> hsc.spines
            [Spine: 0, Spine: 1]
            >>> hsc.removeSpineById(newSpine.id)
            >>> hsc.spines
            [Spine: 1]

            raises a HumdrumException if the spine with a given id is not found




SpineEvent
----------



.. class:: SpineEvent(contents=None, position=0)


    A SpineEvent is an event in a HumdrumSpine or ProtoSpine.


    It's .contents property contains the contents of the spine or
    it could be '.', in which case it means that a
    particular event appears after the last event in a different spine.
    It could also be "None" indicating that there is no event at all
    at this moment in the humdrum file.  Happens if no ProtoSpine exists
    at this point in the file in this tab position.



    Should be initialized with its contents and position in file.



    These attributes are optional but likely to be very helpful::

        position -- event position in the file
        protoSpineId -- ProtoSpine id (0 to N)
        spineId -- id of HumdrumSpine actually attached to (after SpinePaths are parsed)


    The `toNote()` method converts the contents into a music21 note as
    if it's kern -- useful to have in all spine types.




    >>> from music21 import *
    >>> se1 = music21.humdrum.spineParser.SpineEvent('EEE-8')
    >>> se1.position = 40
    >>> se1.contents
    'EEE-8'
    >>> se1
    <music21.humdrum.spineParser.SpineEvent EEE-8>
    >>> n = se1.toNote()
    >>> n
    <music21.note.Note E->




    **SpineEvent** **attributes**

        Attributes without Documentation: `protoSpineId`, `spineId`, `position`, `contents`

    **SpineEvent** **methods**

        .. method:: toNote()


            parse the object as a \*\*kern note and return the a
            :class:`~music21.note.Note` object (or Rest, or Chord)




            >>> from music21 import *
            >>> se = music21.humdrum.spineParser.SpineEvent('CC#4')
            >>> n = se.toNote()
            >>> n
            <music21.note.Note C#>
            >>> n.octave
            2
            >>> n.duration.type
            'quarter'




SpineLine
---------

Inherits from: :class:`~music21.humdrum.spineParser.HumdrumLine`

.. class:: SpineLine(position=0, contents='')


    A SpineLine is any horizontal line of a Humdrum file that
    contains one or more spine elements (separated by tabs)
    and not Global elements.


    Takes in a position (line number in file, excluding blank lines)
    and a string of contents.




    >>> from music21 import *
    >>> hsl = music21.humdrum.spineParser.SpineLine(
    ...         position = 7, contents="C4\t!local comment\t*M[4/4]\t.\n")
    >>> hsl.position
    7
    >>> hsl.numSpines
    4
    >>> hsl.spineData
    ['C4', '!local comment', '*M[4/4]', '.']




    **SpineLine** **attributes**

        Attributes without Documentation: `contents`, `isSpineLine`, `numSpines`, `position`, `spineData`

        Attributes inherited from :class:`~music21.humdrum.spineParser.HumdrumLine`: :attr:`~music21.humdrum.spineParser.HumdrumLine.isComment`, :attr:`~music21.humdrum.spineParser.HumdrumLine.isGlobal`, :attr:`~music21.humdrum.spineParser.HumdrumLine.isReference`


