.. _moduleVariant:

music21.variant
===============

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

.. module:: music21.variant


Contains :class:`~music21.variant.Variant` and its subclasses, as well as functions for merging
and showing different variant streams. These functions and the variant class should only be
used when variants of a score are the same length and contain the same measure structure at
this time.




.. function:: addVariant(s, startOffset, sVariant, variantName=None, variantGroups=None, replacementDuration=None)


    Takes a stream, the location of the variant to be added to that stream (startOffset), the content of the
    variant to be added (sVariant), and the duration of the section of the stream which the variant
    replaces (replacementDuration). If replacementDuration is 0, this is an insertion. If sVariant is
    None, this is a deletion.



    >>> from music21 import *
    >>> data1M1 = [('a', 'quarter'), ('b', 'eighth'), ('c', 'eighth'), ('a', 'quarter'), ('a', 'quarter')]
    >>> data1M3 = [('c', 'quarter'), ('d', 'quarter'), ('e', 'quarter'), ('e', 'quarter')]
    >>> data1M2 = [('b', 'eighth'), ('c', 'eighth'), ('a', 'quarter'), ('a', 'quarter'),('b', 'quarter')]
    >>> data2M2 = [('b', 'eighth'), ('c', 'quarter'), ('a', 'eighth'), ('a', 'quarter'), ('b', 'quarter')]
    >>> data1 = [data1M1, data1M2, data1M3]
    >>> tempPart = stream.Part()
    >>> stream1 = stream.Stream()
    >>> stream2 = stream.Stream()
    >>> for d in data1:
    ...    m = stream.Measure()
    ...    for pitchName,durType in d:
    ...        n = note.Note(pitchName)
    ...        n.duration.type = durType
    ...        m.append(n)
    ...    stream1.append(m)
    >>> m = stream.Measure()
    >>> for pitchName,durType in data2M2:
    ...    n = note.Note(pitchName)
    ...    n.duration.type = durType
    ...    m.append(n)
    >>> stream2.append(m)
    >>> addVariant(stream1, 4.0, stream2, variantName = 'rhythmic switch', replacementDuration = 4.0)
    >>> stream1.show('text')
    {0.0} <music21.stream.Measure 0 offset=0.0>
        {0.0} <music21.note.Note A>
        {1.0} <music21.note.Note B>
        {1.5} <music21.note.Note C>
        {2.0} <music21.note.Note A>
        {3.0} <music21.note.Note A>
    {4.0} <music21.variant.Variant object at ...>
    {4.0} <music21.stream.Measure 0 offset=4.0>
        {0.0} <music21.note.Note B>
        {0.5} <music21.note.Note C>
        {1.0} <music21.note.Note A>
        {2.0} <music21.note.Note A>
        {3.0} <music21.note.Note B>
    {8.0} <music21.stream.Measure 0 offset=8.0>
        {0.0} <music21.note.Note C>
        {1.0} <music21.note.Note D>
        {2.0} <music21.note.Note E>
        {3.0} <music21.note.Note E>
    ⁠ 
    >>> stream1 = stream.Stream()
    >>> stream1.repeatAppend(note.Note('e'), 6)
    >>> variant1 = variant.Variant()
    >>> variant1.repeatAppend(note.Note('f'), 3)
    >>> startOffset = 3.0
    >>> addVariant(stream1, startOffset, variant1, variantName = 'paris', replacementDuration = 3.0)
    >>> stream1.show('text')
    {0.0} <music21.note.Note E>
    {1.0} <music21.note.Note E>
    {2.0} <music21.note.Note E>
    {3.0} <music21.variant.Variant object at ...>
    {3.0} <music21.note.Note E>
    {4.0} <music21.note.Note E>
    {5.0} <music21.note.Note E>



.. function:: getMeasureHashes(s)


    Takes in a stream containing measures and returns a list of hashes, one for each measure. Currently
    implemented with search.translateStreamToString()



    >>> from music21 import *
    >>> s = converter.parse("c4 d8. e16 FF4 a'4 b-2", "2/4")
    >>> sm = s.makeMeasures()
    >>> hashes = getMeasureHashes(sm)
    >>> hashes
    ['<P>K@<', ')PQP', 'FZ']



.. function:: mergePartAsOssia(mainpart, ossiapart, ossiaName, inPlace=False, compareByMeasureNumber=False, recurseInMeasures=False)


    Some MusicXML files are generated with full parts that have only a few non-rest measures instead of ossia parts, such as those
    created by Sibelius 7. This function
    takes two streams (mainpart and ossiapart), the second interpreted as an ossia. It outputs a stream with the ossia part merged into the stream as a
    group of variants.

    If compareByMeasureNumber is True, then the ossia measures will be paired with the measures in the mainpart that have the
    same measure.number. Otherwise, they will be paired by offset. In most cases these should have the same result.



    >>> from music21 import *
    >>> mainstream = converter.parse("  A4 B4 C4 D4   E1    F2 E2     E8 F8 F4 G2   G2 G4 F4   F4 F4 F4 F4   G1      ", "4/4")
    >>> ossiastream = converter.parse(" r1            r1    r1        E4 E4 F4 G4   r1         F2    F2      r1      ", "4/4")
    >>> mainstream.makeMeasures(inPlace = True)
    >>> ossiastream.makeMeasures(inPlace = True)
    ⁠ 
    >>> # mainstream.__class__ = stream.Part
    >>> mainpart = stream.Part()
    >>> for m in mainstream:
    ...    mainpart.insert(m.offset, m)
    >>> ossiapart = stream.Part()
    >>> for m in ossiastream:
    ...    ossiapart.insert(m.offset, m)



    >>> s = stream.Stream()
    >>> s.insert(0.0, ossiapart)
    >>> s.insert(0.0, mainpart)
    >>> s.show()
    ⁠ 
    >>> mainpartWithOssiaVariantsFT = variant.mergePartAsOssia(mainpart, ossiapart,
    ...                                                            ossiaName = 'Parisian Variant',
    ...                                                            inPlace = False,
    ...                                                            compareByMeasureNumber = False,
    ...                                                            recurseInMeasures = True)
    >>> mainpartWithOssiaVariantsTT = variant.mergePartAsOssia(mainpart, ossiapart,
    ...                                                            ossiaName = 'Parisian Variant',
    ...                                                            inPlace = False,
    ...                                                            compareByMeasureNumber = True,
    ...                                                            recurseInMeasures = True)
    >>> mainpartWithOssiaVariantsFF = variant.mergePartAsOssia(mainpart, ossiapart,
    ...                                                            ossiaName = 'Parisian Variant',
    ...                                                            inPlace = False,
    ...                                                            compareByMeasureNumber = False,
    ...                                                            recurseInMeasures = False)
    >>> mainpartWithOssiaVariantsTF = variant.mergePartAsOssia(mainpart, ossiapart,
    ...                                                            ossiaName = 'Parisian Variant',
    ...                                                            inPlace = False,
    ...                                                            compareByMeasureNumber = True,
    ...                                                            recurseInMeasures = False)



    >>> mainpartWithOssiaVariantsFT.show('text') == mainpartWithOssiaVariantsTT.show('text')
    {0.0} <music21.stream.Measure ...
    True
    ⁠ 
    >>> mainpartWithOssiaVariantsFF.show('text') == mainpartWithOssiaVariantsFT.show('text')
    {0.0} <music21.stream.Measure ...
    True



    >>> mainpartWithOssiaVariantsFT.show('text')
    {0.0} <music21.stream.Measure 1 offset=0.0>
    ...
    {12.0} <music21.stream.Measure 4 offset=12.0>
        {0.0} <music21.variant.Variant object at ...>
        {0.0} <music21.note.Note E>
        {0.5} <music21.note.Note F>
        {1.0} <music21.note.Note F>
        {2.0} <music21.note.Note G>
    {16.0} <music21.stream.Measure 5 offset=16.0>
    ...
    {20.0} <music21.stream.Measure 6 offset=20.0>
        {0.0} <music21.variant.Variant object at ...>
        {0.0} <music21.note.Note F>
        {1.0} <music21.note.Note F>
        {2.0} <music21.note.Note F>
        {3.0} <music21.note.Note F>
    ...
    ⁠ 
    >>> mainpartWithOssiaVariantsFF.activateVariants('Parisian Variant').show('text')
    {0.0} <music21.stream.Measure 1 offset=0.0>
    ...
    {12.0} <music21.variant.Variant object at ...>
    {12.0} <music21.stream.Measure 4 offset=12.0>
        {0.0} <music21.note.Note E>
        {1.0} <music21.note.Note E>
        {2.0} <music21.note.Note F>
        {3.0} <music21.note.Note G>
    {16.0} <music21.stream.Measure 5 offset=16.0>
    ...
    {20.0} <music21.variant.Variant object at ...>
    {20.0} <music21.stream.Measure 6 offset=20.0>
        {0.0} <music21.note.Note F>
        {2.0} <music21.note.Note F>
    ...




.. function:: mergeVariantMeasureStreams(streamX, streamY, variantName, inPlace=False)


    Takes two streams of measures and returns a stream (new if inPlace is False) with the second
    merged with the first as variants. This function differs from mergeVariantStreams by
    dealing with streams that are of different length. This function matches measures that are
    exactly equal and creates variant objects for regions of measures that differ at all. If more
    refined variants are sought (with variation within the bar considered and related but different
    bars associated with each other), use variant.refineVariant().

    In this example, the second bar has been deleted in the second version, a new bar has been inserted between the
    original third and fourth bars, and two bars have been added at the end.



    >>> from music21 import *
    >>> data1M1 = [('a', 'quarter'), ('b', 'eighth'), ('c', 'eighth'), ('a', 'quarter'), ('a', 'quarter')]
    >>> data1M2 = [('b', 'eighth'), ('c', 'eighth'), ('a', 'quarter'), ('a', 'quarter'),('b', 'quarter')]
    >>> data1M3 = [('c', 'quarter'), ('d', 'quarter'), ('e', 'quarter'), ('e', 'quarter')]
    >>> data1M4 = [('d', 'quarter'), ('g', 'eighth'), ('g', 'eighth'), ('a', 'quarter'), ('b', 'quarter')]
    ⁠ 
    >>> data2M1 = [('a', 'quarter'), ('b', 'eighth'), ('c', 'eighth'), ('a', 'quarter'), ('a', 'quarter')]
    >>> data2M2 = [('c', 'quarter'), ('d', 'quarter'), ('e', 'quarter'), ('e', 'quarter')]
    >>> data2M3 = [('e', 'quarter'), ('g', 'eighth'), ('g', 'eighth'), ('a', 'quarter'), ('b', 'quarter')]
    >>> data2M4 = [('d', 'quarter'), ('g', 'eighth'), ('g', 'eighth'), ('a', 'quarter'), ('b', 'quarter')]
    >>> data2M5 = [('f', 'eighth'), ('c', 'quarter'), ('a', 'eighth'), ('a', 'quarter'), ('b', 'quarter')]
    >>> data2M6 = [('g', 'quarter'), ('d', 'quarter'), ('e', 'quarter'), ('e', 'quarter')]



    >>> data1 = [data1M1, data1M2, data1M3, data1M4]
    >>> data2 = [data2M1, data2M2, data2M3, data2M4, data2M5, data2M6]
    >>> stream1 = stream.Stream()
    >>> stream2 = stream.Stream()
    >>> mNumber = 1
    >>> for d in data1:
    ...    m = stream.Measure()
    ...    m.number = mNumber
    ...    mNumber += 1
    ...    for pitchName,durType in d:
    ...        n = note.Note(pitchName)
    ...        n.duration.type = durType
    ...        m.append(n)
    ...    stream1.append(m)
    >>> mNumber = 1
    >>> for d in data2:
    ...    m = stream.Measure()
    ...    m.number = mNumber
    ...    mNumber += 1
    ...    for pitchName,durType in d:
    ...        n = note.Note(pitchName)
    ...        n.duration.type = durType
    ...        m.append(n)
    ...    stream2.append(m)
    >>> stream1.show()





    .. image:: images/variant_measuresStreamMergeStream1.*
            :width: 600




    >>> stream2.show()





    .. image:: images/variant_measuresStreamMergeStream2.*
            :width: 600




    >>> mergedStream = mergeVariantMeasureStreams(stream1, stream2, 'paris', inPlace = False)
    >>> mergedStream.show('text')
    {0.0} <music21.stream.Measure 1 offset=0.0>
        {0.0} <music21.note.Note A>
        {1.0} <music21.note.Note B>
        {1.5} <music21.note.Note C>
        {2.0} <music21.note.Note A>
        {3.0} <music21.note.Note A>
    {4.0} <music21.variant.Variant object at ...>
    {4.0} <music21.stream.Measure 2 offset=4.0>
        {0.0} <music21.note.Note B>
        {0.5} <music21.note.Note C>
        {1.0} <music21.note.Note A>
        {2.0} <music21.note.Note A>
        {3.0} <music21.note.Note B>
    {8.0} <music21.stream.Measure 3 offset=8.0>
        {0.0} <music21.note.Note C>
        {1.0} <music21.note.Note D>
        {2.0} <music21.note.Note E>
        {3.0} <music21.note.Note E>
    {12.0} <music21.variant.Variant object at ...>
    {12.0} <music21.stream.Measure 4 offset=12.0>
        {0.0} <music21.note.Note D>
        {1.0} <music21.note.Note G>
        {1.5} <music21.note.Note G>
        {2.0} <music21.note.Note A>
        {3.0} <music21.note.Note B>
    {16.0} <music21.variant.Variant object at ...>
    ⁠ 
    >>> mergedStream.variants[0].replacementDuration
    4.0
    >>> mergedStream.variants[1].replacementDuration
    0.0



    >>> parisStream = mergedStream.activateVariants('paris', inPlace = False)
    >>> parisStream.show('text')
    {0.0} <music21.stream.Measure 1 offset=0.0>
        {0.0} <music21.note.Note A>
        {1.0} <music21.note.Note B>
        {1.5} <music21.note.Note C>
        {2.0} <music21.note.Note A>
        {3.0} <music21.note.Note A>
    {4.0} <music21.variant.Variant object at ...>
    {4.0} <music21.stream.Measure 2 offset=4.0>
        {0.0} <music21.note.Note C>
        {1.0} <music21.note.Note D>
        {2.0} <music21.note.Note E>
        {3.0} <music21.note.Note E>
    {8.0} <music21.variant.Variant object at ...>
    {8.0} <music21.stream.Measure 3 offset=8.0>
        {0.0} <music21.note.Note E>
        {1.0} <music21.note.Note G>
        {1.5} <music21.note.Note G>
        {2.0} <music21.note.Note A>
        {3.0} <music21.note.Note B>
    {12.0} <music21.stream.Measure 4 offset=12.0>
        {0.0} <music21.note.Note D>
        {1.0} <music21.note.Note G>
        {1.5} <music21.note.Note G>
        {2.0} <music21.note.Note A>
        {3.0} <music21.note.Note B>
    {16.0} <music21.variant.Variant object at ...>
    {16.0} <music21.stream.Measure 5 offset=16.0>
        {0.0} <music21.note.Note F>
        {0.5} <music21.note.Note C>
        {1.5} <music21.note.Note A>
        {2.0} <music21.note.Note A>
        {3.0} <music21.note.Note B>
    {20.0} <music21.stream.Measure 6 offset=20.0>
        {0.0} <music21.note.Note G>
        {1.0} <music21.note.Note D>
        {2.0} <music21.note.Note E>
        {3.0} <music21.note.Note E>
    ⁠ 
    >>> parisStream.variants[0].replacementDuration
    0.0
    >>> parisStream.variants[1].replacementDuration
    4.0
    >>> parisStream.variants[2].replacementDuration
    8.0



.. function:: mergeVariantStreams(streams, variantNames, inPlace=False)


    Pass this function a list of streams (they must be of the same length or a VariantException will be raised).
    It will return a stream which merges the differences between the streams into variant objects keeping the
    first stream in the list as the default. If inPlace is True, the first stream in the list will be modified,
    otherwise a new stream will be returned. Pass a list of names to associate variants with their sources, if this list
    does not contain an entry for each non-default variant, naming may not behave properly. Variants that have the
    same differences from the default will be saved as separate variant objects (i.e. more than once under different names).
    Also, note that a streams with bars of differing lengths will not behave properly.



    >>> from music21 import *
    >>> stream1 = stream.Stream()
    >>> stream2paris = stream.Stream()
    >>> stream3london = stream.Stream()
    >>> data1 = [('a', 'quarter'), ('b', 'eighth'), ('c', 'eighth'), ('a', 'quarter'), ('a', 'quarter'),
    ...    ('b', 'eighth'), ('c', 'eighth'), ('a', 'quarter'), ('a', 'quarter'),
    ...    ('b', 'quarter'), ('c', 'quarter'), ('d', 'quarter'), ('e', 'quarter')]
    >>> data2 = [('a', 'quarter'), ('b', 'quarter'), ('a', 'quarter'), ('g', 'quarter'),
    ...    ('b', 'eighth'), ('c', 'quarter'), ('a', 'eighth'), ('a', 'quarter'),
    ...    ('b', 'quarter'), ('c', 'quarter'), ('b', 'quarter'), ('a', 'quarter')]
    >>> data3 = [('a', 'quarter'), ('b', 'eighth'), ('c', 'eighth'), ('a', 'quarter'), ('a', 'quarter'),
    ...    ('b', 'eighth'), ('c', 'eighth'), ('a', 'quarter'), ('a', 'quarter'),
    ...    ('c', 'quarter'), ('c', 'quarter'), ('d', 'quarter'), ('e', 'quarter')]
    >>> for pitchName,durType in data1:
    ...    n = note.Note(pitchName)
    ...    n.duration.type = durType
    ...    stream1.append(n)
    >>> for pitchName,durType in data2:
    ...    n = note.Note(pitchName)
    ...    n.duration.type = durType
    ...    stream2paris.append(n)
    >>> for pitchName,durType in data3:
    ...    n = note.Note(pitchName)
    ...    n.duration.type = durType
    ...    stream3london.append(n)
    >>> mergedStreams = mergeVariantStreams([stream1, stream2paris, stream3london], ['paris', 'london'])
    >>> mergedStreams.show('t')
    {0.0} <music21.note.Note A>
    {1.0} <music21.variant.Variant object at ...>
    {1.0} <music21.note.Note B>
    {1.5} <music21.note.Note C>
    {2.0} <music21.note.Note A>
    {3.0} <music21.variant.Variant object at ...>
    {3.0} <music21.note.Note A>
    {4.0} <music21.note.Note B>
    {4.5} <music21.variant.Variant object at ...>
    {4.5} <music21.note.Note C>
    {5.0} <music21.note.Note A>
    {6.0} <music21.note.Note A>
    {7.0} <music21.variant.Variant object at ...>
    {7.0} <music21.note.Note B>
    {8.0} <music21.note.Note C>
    {9.0} <music21.variant.Variant object at ...>
    {9.0} <music21.note.Note D>
    {10.0} <music21.note.Note E>
    ⁠ 
    >>> mergedStreams.activateVariants('london').show('t')
    {0.0} <music21.note.Note A>
    {1.0} <music21.variant.Variant object at ...>
    {1.0} <music21.note.Note B>
    {1.5} <music21.note.Note C>
    {2.0} <music21.note.Note A>
    {3.0} <music21.variant.Variant object at ...>
    {3.0} <music21.note.Note A>
    {4.0} <music21.note.Note B>
    {4.5} <music21.variant.Variant object at ...>
    {4.5} <music21.note.Note C>
    {5.0} <music21.note.Note A>
    {6.0} <music21.note.Note A>
    {7.0} <music21.variant.Variant object at ...>
    {7.0} <music21.note.Note C>
    {8.0} <music21.note.Note C>
    {9.0} <music21.variant.Variant object at ...>
    {9.0} <music21.note.Note D>
    {10.0} <music21.note.Note E>

    If the streams contain parts and measures, the merge function will iterate through them and determine
    and store variant differences within each measure/part.



    >>> stream1 = stream.Stream()
    >>> stream2 = stream.Stream()
    >>> data1M1 = [('a', 'quarter'), ('b', 'eighth'), ('c', 'eighth'), ('a', 'quarter'), ('a', 'quarter')]
    >>> data1M2 = [('b', 'eighth'), ('c', 'eighth'), ('a', 'quarter'), ('a', 'quarter'),('b', 'quarter')]
    >>> data1M3 = [('c', 'quarter'), ('d', 'quarter'), ('e', 'quarter'), ('e', 'quarter')]
    >>> data2M1 = [('a', 'quarter'), ('b', 'quarter'), ('a', 'quarter'), ('g', 'quarter')]
    >>> data2M2 = [('b', 'eighth'), ('c', 'quarter'), ('a', 'eighth'), ('a', 'quarter'), ('b', 'quarter')]
    >>> data2M3 = [('c', 'quarter'), ('b', 'quarter'), ('a', 'quarter'), ('a', 'quarter')]
    >>> data1 = [data1M1, data1M2, data1M3]
    >>> data2 = [data2M1, data2M2, data2M3]
    >>> tempPart = stream.Part()
    >>> for d in data1:
    ...    m = stream.Measure()
    ...    for pitchName,durType in d:
    ...        n = note.Note(pitchName)
    ...        n.duration.type = durType
    ...        m.append(n)
    ...    tempPart.append(m)
    >>> stream1.append(tempPart)
    >>> tempPart = stream.Part()
    >>> for d in data2:
    ...    m = stream.Measure()
    ...    for pitchName,durType in d:
    ...        n = note.Note(pitchName)
    ...        n.duration.type = durType
    ...        m.append(n)
    ...    tempPart.append(m)
    >>> stream2.append(tempPart)
    >>> mergedStreams = mergeVariantStreams([stream1, stream2], ['paris'])
    >>> mergedStreams.show('t')
    {0.0} <music21.stream.Part ...>
        {0.0} <music21.stream.Measure 0 offset=0.0>
            {0.0} <music21.note.Note A>
            {1.0} <music21.variant.Variant object at ...>
            {1.0} <music21.note.Note B>
            {1.5} <music21.note.Note C>
            {2.0} <music21.note.Note A>
            {3.0} <music21.variant.Variant object at ...>
            {3.0} <music21.note.Note A>
        {4.0} <music21.stream.Measure 0 offset=4.0>
            {0.0} <music21.note.Note B>
            {0.5} <music21.variant.Variant object at ...>
            {0.5} <music21.note.Note C>
            {1.0} <music21.note.Note A>
            {2.0} <music21.note.Note A>
            {3.0} <music21.note.Note B>
        {8.0} <music21.stream.Measure 0 offset=8.0>
            {0.0} <music21.note.Note C>
            {1.0} <music21.variant.Variant object at ...>
            {1.0} <music21.note.Note D>
            {2.0} <music21.note.Note E>
            {3.0} <music21.note.Note E>
    >>> mergedStreams.show()





    .. image:: images/variant_measuresAndParts.*
            :width: 600





    >>> for p in mergedStreams.getElementsByClass('Part'):
    ...    for m in p.getElementsByClass('Measure'):
    ...        m.activateVariants('paris', inPlace = True)
    >>> mergedStreams.show('t')
    {0.0} <music21.stream.Part ...>
        {0.0} <music21.stream.Measure 0 offset=0.0>
            {0.0} <music21.note.Note A>
            {1.0} <music21.variant.Variant object at ...>
            {1.0} <music21.note.Note B>
            {2.0} <music21.note.Note A>
            {3.0} <music21.variant.Variant object at ...>
            {3.0} <music21.note.Note G>
        {4.0} <music21.stream.Measure 0 offset=4.0>
            {0.0} <music21.note.Note B>
            {0.5} <music21.variant.Variant object at ...>
            {0.5} <music21.note.Note C>
            {1.5} <music21.note.Note A>
            {2.0} <music21.note.Note A>
            {3.0} <music21.note.Note B>
        {8.0} <music21.stream.Measure 0 offset=8.0>
            {0.0} <music21.note.Note C>
            {1.0} <music21.variant.Variant object at ...>
            {1.0} <music21.note.Note B>
            {2.0} <music21.note.Note A>
            {3.0} <music21.note.Note A>
    >>> mergedStreams.show()





    .. image:: images/variant_measuresAndParts2.*
            :width: 600


    If barlines do not match up, an exception will be thrown. Here two streams that are identical
    are merged, except one is in 3/4, the other in 4/4. This throws an exception.



    >>> streamDifferentMeasures = stream.Stream()
    >>> dataDiffM1 = [('a', 'quarter'), ('b', 'eighth'), ('c', 'eighth'), ('a', 'quarter')]
    >>> dataDiffM2 = [ ('a', 'quarter'), ('b', 'eighth'), ('c', 'eighth'), ('a', 'quarter')]
    >>> dataDiffM3 = [('a', 'quarter'), ('b', 'quarter'), ('c', 'quarter')]
    >>> dataDiffM4 = [('d', 'quarter'), ('e', 'quarter'), ('e', 'quarter')]
    >>> dataDiff = [dataDiffM1, dataDiffM2, dataDiffM3, dataDiffM4]
    >>> streamDifferentMeasures.insert(0.0, meter.TimeSignature('3/4'))
    >>> tempPart = stream.Part()
    >>> for d in dataDiff:
    ...    m = stream.Measure()
    ...    for pitchName,durType in d:
    ...        n = note.Note(pitchName)
    ...        n.duration.type = durType
    ...        m.append(n)
    ...    tempPart.append(m)
    >>> streamDifferentMeasures.append(tempPart)
    >>> mergedStreams = mergeVariantStreams([stream1, streamDifferentMeasures], ['paris'])
    Traceback (most recent call last):
    ...
    VariantException: _mergeVariants cannot merge streams which are of different lengths



.. function:: refineVariant(s, sVariant, inPlace=False)


    Given a stream and variant contained in that stream, returns a stream with that variant 'refined.'
    It is refined in the sense that, (with the best estimates) measures which have been determined
    to be related are merged within the measure. Suppose a four-bar phrase in a piece is a slightly
    different five-bar phrase in a variant. In the variant, every F# has been replaced by an F,
    and the last bar is repeated. Given this streams, mergeVariantMeasureStreams would return
    the first stream with a single variant object containing the entire 5 bars of the variant.
    Calling refineVariant on this stream and that variant object would result in a variant object
    in the measures for each F#/F pair, and a variant object containing the added bar at the end.
    For a more detailed explanation of how similar measures are properly associated with each other
    look at the documentation for _getBestListandScore

    Note that this code does not work properly yet.



    >>> from music21 import *
    >>> v = variant.Variant()
    >>> variantDataM1 = [('b', 'eighth'), ('c', 'eighth'), ('a', 'quarter'), ('a', 'quarter'),('b', 'quarter')]
    >>> variantDataM2 = [('c', 'quarter'), ('d', 'quarter'), ('e', 'quarter'), ('e', 'quarter')]
    >>> variantData = [variantDataM1, variantDataM2]
    >>> for d in variantData:
    ...    m = stream.Measure()
    ...    for pitchName,durType in d:
    ...        n = note.Note(pitchName)
    ...        n.duration.type = durType
    ...        m.append(n)
    ...    v.append(m)
    >>> v.groups = ['paris']
    >>> v.replacementDuration = 8.0
    ⁠ 
    >>> s = stream.Stream()
    >>> streamDataM1 = [('a', 'quarter'), ('b', 'quarter'), ('a', 'quarter'), ('g', 'quarter')]
    >>> streamDataM2 = [('b', 'eighth'), ('c', 'quarter'), ('a', 'eighth'), ('a', 'quarter'), ('b', 'quarter')]
    >>> streamDataM3 = [('c', 'quarter'), ('b', 'quarter'), ('a', 'quarter'), ('a', 'quarter')]
    >>> streamDataM4 = [('c', 'quarter'), ('b', 'quarter'), ('a', 'quarter'), ('a', 'quarter')]
    >>> streamData = [streamDataM1, streamDataM2, streamDataM3, streamDataM4]
    >>> for d in streamData:
    ...    m = stream.Measure()
    ...    for pitchName,durType in d:
    ...        n = note.Note(pitchName)
    ...        n.duration.type = durType
    ...        m.append(n)
    ...    s.append(m)
    >>> s.insert(4.0, v)



    >>> refineVariant(s, v, inPlace = True)
    >>> s.show('text')
    {0.0} <music21.stream.Measure 0 offset=0.0>
        {0.0} <music21.note.Note A>
        {1.0} <music21.note.Note B>
        {2.0} <music21.note.Note A>
        {3.0} <music21.note.Note G>
    {4.0} <music21.stream.Measure 0 offset=4.0>
        {0.0} <music21.note.Note B>
        {0.5} <music21.variant.Variant object at ...>
        {0.5} <music21.note.Note C>
        {1.5} <music21.note.Note A>
        {2.0} <music21.note.Note A>
        {3.0} <music21.note.Note B>
    {8.0} <music21.stream.Measure 0 offset=8.0>
        {0.0} <music21.note.Note C>
        {1.0} <music21.variant.Variant object at ...>
        {1.0} <music21.note.Note B>
        {2.0} <music21.note.Note A>
        {3.0} <music21.note.Note A>
    {12.0} <music21.stream.Measure 0 offset=12.0>
        {0.0} <music21.note.Note C>
        {1.0} <music21.note.Note B>
        {2.0} <music21.note.Note A>
        {3.0} <music21.note.Note A>




Variant
-------

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

.. class:: Variant(givenElements=None, *args, **keywords)

    A Music21Object that stores elements like a Stream, but does not represent itself externally to a Stream; i.e., the contents of a Variant are not flattened.

    This is accomplished not by subclassing, but by object composition: similar to the Spanner, the Variant contains a Stream as a private attribute. Calls to this Stream, for the Variant, are automatically delegated by use of the __getattr__ method. Special casses are overridden or managed as necessary: e.g., the Duration of a Variant is generally always zero.

    To use Variants from a Stream, see the :func:`~music21.stream.Stream.activateVariants` method.



    >>> from music21 import *
    >>> v = variant.Variant()
    >>> v.repeatAppend(note.Note(), 8)
    >>> len(v.notes)
    8
    >>> v.highestTime
    0.0
    >>> v.duration # handled by Music21Object
    <music21.duration.Duration 0.0>
    >>> v.isStream
    False
    ⁠ 
    >>> s = stream.Stream()
    >>> s.append(v)
    >>> s.append(note.Note())
    >>> s.highestTime
    1.0
    >>> s.show('t') # doctest: +ELLIPSIS
    {0.0} <music21.variant.Variant object at ...>
    {0.0} <music21.note.Note C>
    >>> s.flat.show('t') # doctest: +ELLIPSIS
    {0.0} <music21.variant.Variant object at ...>
    {0.0} <music21.note.Note C>



    **Variant** **attributes**

        .. attribute:: 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



            >>> from music21 import *
            >>> 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



        Attributes without Documentation: `isVariant`, `exposeTime`

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

    **Variant** **properties**

        .. attribute:: containedHighestOffset


            This property calls the contained Stream.highestOffset.



            >>> from music21 import *
            >>> v = variant.Variant()
            >>> v.append(note.Note(quarterLength=4))
            >>> v.append(note.Note())
            >>> v.containedHighestOffset
            4.0




        .. attribute:: containedHighestTime


            This property calls the contained Stream.highestTime.



            >>> from music21 import *
            >>> v = variant.Variant()
            >>> v.append(note.Note(quarterLength=4))
            >>> v.containedHighestTime
            4.0



        .. attribute:: containedSite


            Return a reference to the Stream contained in this Variant.



        .. attribute:: highestOffset


            This property masks calls to Stream.highestOffset. Assuming `exposeTime` is False, this always returns zero, making the Variant always take zero time.



            >>> from music21 import *
            >>> v = variant.Variant()
            >>> v.append(note.Note(quarterLength=4))
            >>> v.highestOffset
            0.0




        .. attribute:: highestTime


            This property masks calls to Stream.highestTime. Assuming `exposeTime` is False, this always returns zero, making the Variant always take zero time.



            >>> from music21 import *
            >>> v = variant.Variant()
            >>> v.append(note.Note(quarterLength=4))
            >>> v.highestTime
            0.0




        .. attribute:: lengthType


            Returns 'deletion' if variant is shorter than the region it replaces, 'elongation'
            if the variant is longer than the region it replaces, and 'replacement' if it is
            the same length.



        .. attribute:: replacementDuration


            Set or Return the quarterLength duration in the main stream which this variant
            object replaces in the variant version of the stream. If replacementDuration is
            not set, it is assumed to be the same length as the variant. If, it is set to 0,
            the variant should be interpreted as an insertion. Setting replacementDuration
            to None will return the value to the default which is the duration of the variant
            itself.



        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`

    **Variant** **methods**

        .. method:: freezeIds()

            No documentation.


        .. method:: getElementIds()

            No documentation.


        .. method:: purgeLocations(rescanIsDead=False)

            No documentation.


        .. method:: purgeOrphans()

            No documentation.


        .. method:: replaceElement(old, new)

            When copying a Variant, we need to update the Variant with new references for copied elements. Given the old component, this method will replace the old with the new.

            The `old` parameter can be either an object or object id.

            This method is very similar to the replaceComponent method on Spanner.



            >>> from music21 import *
            >>> n1 = note.Note('g')
            >>> n2 = note.Note('f#')
            >>> c1 = clef.AltoClef()
            >>> c2 = clef.BassClef()
            >>> sl = spanner.Spanner(n1, n2, c1)
            >>> sl.replaceComponent(c1, c2)
            >>> sl[-1] == c2
            True



        .. method:: show(fmt=None, app=None)


            Call show() on the Stream contained by this Variant.

            This method must be overridden, otherwise Music21Object.show() is called.



            >>> from music21 import *
            >>> v = variant.Variant()
            >>> v.repeatAppend(note.Note(quarterLength=.25), 8)
            >>> v.show('t')
            {0.0} <music21.note.Note C>
            {0.25} <music21.note.Note C>
            {0.5} <music21.note.Note C>
            {0.75} <music21.note.Note C>
            {1.0} <music21.note.Note C>
            {1.25} <music21.note.Note C>
            {1.5} <music21.note.Note C>
            {1.75} <music21.note.Note C>



        .. method:: unfreezeIds()

            No documentation.


        .. method:: unwrapWeakref()

            Overridden method for unwrapping all Weakrefs.



        .. method:: wrapWeakref()

            Overridden method for unwrapping all Weakrefs.



        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.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.purgeUndeclaredIds`, :meth:`~music21.base.Music21Object.removeLocationBySite`, :meth:`~music21.base.Music21Object.removeLocationBySiteId`, :meth:`~music21.base.Music21Object.setOffsetBySite`, :meth:`~music21.base.Music21Object.splitAtDurations`, :meth:`~music21.base.Music21Object.splitAtQuarterLength`, :meth:`~music21.base.Music21Object.splitByQuarterLengths`, :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`


