
    rh                      S r SSKJr  SSKJr  SSKrSSKrSSKrSSK	r	SSK
Jr  SSK
Jr  SSK
Jr  SSK
Jr  SS	K
Jr  SS
K
Jr  SSK
Jr  SSK
Jr  SSK
Jr  SSKJr  \R,                  " S5      r " S S\R0                  5      r " S S\R4                  5      rS/SS.S jjrS/SS.S jjrS/SS.S jjrSS.S jr S0S jr    S1     S2S jjr!SS.S jr"SS.S jr#S r$ S3S jr%S  r&S! r'SSS".S# jr(S4S$ jr)   S5S% jr*S4S& jr+S6S' jr,S( r-S) r. " S* S+\	R^                  5      r0 " S, S-\	R^                  5      r1\2S.:X  a  SSK
r
\
Rf                  " \05        gg)7a$  
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.
    )annotations)SequenceN)base)clef)common)environment)exceptions21)meter)note)search)stream)GivenElementsBehaviorvariantc                      \ rS rSrSrg)VariantException1    N)__name__
__module____qualname____firstlineno____static_attributes__r       I/home/james-whalen/.local/lib/python3.13/site-packages/music21/variant.pyr   r   1   s    r   r   c                  f  ^  \ rS rSrSr\R                  R                  S-
  rSS\R                  4     SU 4S jjjr
SS jrSS jrS rS	 rS
 rS rS rS rS r\S 5       r\S 5       rS S jr\S 5       r\S 5       r\S 5       rS rS r\" \\SS9r\S 5       r  S!S jrS S jr Sr!U =r"$ )"Variant5   ar  
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 cases 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.

>>> v = variant.Variant()
>>> v.repeatAppend(note.Note(), 8)
>>> len(v.notes)
8
>>> v.highestTime
0.0
>>> v.containedHighestTime
8.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')
{0.0} <music21.variant.Variant object of length 8.0>
{0.0} <music21.note.Note C>
>>> s.flatten().show('t')
{0.0} <music21.variant.Variant object of length 8.0>
{0.0} <music21.note.Note C>
   Nc                   > [         TU ]  " S0 UD6  SU l        [        R                  " UUS9U l        S U l        Ub  U R                  R                  U5        g g )NF)givenElementsgivenElementsBehaviorr   )	super__init__
exposeTimer   VariantStorage_stream_replacementDurationgroupsappend)selfr    namer!   music21ObjectKeywords	__class__s        r   r#   Variant.__init___   s\     	101,,=CXZ %)!KKt$ r   c                x    U R                   R                  U5        [        R                  R                  X5        g N)r&   purgeOrphansr   Music21Object)r*   excludeStorageStreamss     r   r1   Variant.purgeOrphansw   s)    !!"78''Dr   c                p    U R                   R                  US9  [        R                  R                  XS9  g )N)rescanIsDead)r&   purgeLocationsr   r2   )r*   r6   s     r   r7   Variant.purgeLocations{   s.    ###>))$)Jr   c                2    S[        U R                  5      -   $ )Nzobject of length )strcontainedHighestTimer*   s    r   _reprInternalVariant._reprInternal   s    "S)B)B%CCCr   c                    US;   a  [         eUS:w  a'  [        U S5      (       a  [        U R                  U5      $ [         e)z]
This defers all calls not defined in this Class to calls on the privately contained Stream.
)flatpitchesr&   )AttributeErrorhasattrgetattrr&   )r*   attrs     r   __getattr__Variant.__getattr__   s@     &&   9y!9!94<<..  r   c                8    U R                   R                  U5      $ r0   )r&   __getitem__)r*   keys     r   rI   Variant.__getitem__   s    ||'',,r   c                ,    [        U R                  5      $ r0   )lenr&   r<   s    r   __len__Variant.__len__   s    4<<  r   c                6    U R                   R                  5       $ r0   )r&   __iter__r<   s    r   rQ   Variant.__iter__   s    ||$$&&r   c                    SU R                   ;  d  U R                   S   c=  U R                  R                   Vs/ s H  n[        U5      PM     snU R                   S'   U R                   S   $ s  snf )N
elementIds)_cacher&   	_elementsid)r*   cs     r   getElementIdsVariant.getElementIds   s^    t{{*dkk,.G.O8<8N8N(O8N1A8N(ODKK%{{<(( )Ps   A-c                    Uc  g[         R                  " U5      (       a:  U R                  R                  U5      nUb  U R                  R	                  X2SS9  ggU R                  R	                  XSS9  g)a.  
When copying a Variant, we need to update the Variant with new
references for copied elements. Given the old element,
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 replaceSpannedElement method on Spanner.
NF)
allDerived)r   isNumr&   coreGetElementByMemoryLocationreplace)r*   oldnewes       r   replaceElementVariant.replaceElement   si     ;<<;;C@A}$$Q$>  LL  e <r   c                R    U R                   (       a  U R                  R                  $ g)z
This property masks calls to Stream.highestTime. Assuming `exposeTime`
is False, this always returns zero, making the Variant always take zero time.

>>> v = variant.Variant()
>>> v.append(note.Note(quarterLength=4))
>>> v.highestTime
0.0
        )r$   r&   highestTimer<   s    r   rg   Variant.highestTime   s     ??<<+++r   c                R    U R                   (       a  U R                  R                  $ g)z
This property masks calls to Stream.highestOffset. Assuming `exposeTime`
is False, this always returns zero, making the Variant always take zero time.

>>> v = variant.Variant()
>>> v.append(note.Note(quarterLength=4))
>>> v.highestOffset
0.0
rf   )r$   r&   highestOffsetr<   s    r   rj   Variant.highestOffset   s     ??<<---r   c                6    U R                   R                  XS9  g)a  
Call show() on the Stream contained by this Variant.

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


>>> v = variant.Variant()
>>> v.repeatAppend(note.Note(quarterLength=0.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>
)fmtappN)r&   show)r*   rm   rn   s      r   ro   Variant.show   s    & 	c+r   c                .    U R                   R                  $ )z
This property calls the contained Stream.highestTime.

>>> v = variant.Variant()
>>> v.append(note.Note(quarterLength=4))
>>> v.containedHighestTime
4.0
)r&   rg   r<   s    r   r;   Variant.containedHighestTime   s     ||'''r   c                .    U R                   R                  $ )z
This property calls the contained Stream.highestOffset.

>>> v = variant.Variant()
>>> v.append(note.Note(quarterLength=4))
>>> v.append(note.Note())
>>> v.containedHighestOffset
4.0
)r&   rj   r<   s    r   containedHighestOffsetVariant.containedHighestOffset   s     ||)))r   c                    U R                   $ )z.
Return the Stream contained in this Variant.
)r&   r<   s    r   containedSiteVariant.containedSite  s    
 ||r   c                t    U R                   c   U R                  R                  R                  $ U R                   $ r0   )r'   r&   durationquarterLengthr<   s    r   _getReplacementDurationVariant._getReplacementDuration  s0    $$,<<((666,,,r   c                    Xl         g r0   )r'   )r*   values     r   _setReplacementDurationVariant._setReplacementDuration  s    $)!r   a  
        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.
        )docc                R    U R                   U R                  -
  nUS:  a  gUS:  a  gg)z
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.
rf   deletion
elongationreplacement)replacementDurationr;   )r*   lengthDifferences     r   
lengthTypeVariant.lengthType$  s4      33d6O6OOc!# r   c           	     ^   S nUcC  U R                   nUc4  [        R                  S5        U R                  S5      nUc  [	        S5      eXR                  U R                  5      ;  a  [	        SU 35      eU R                  U5      nUSL aQ  U R                  [        R                  5      R                  U5      R                  5       R                  R                  nOSnU R                  S;   az  X`R                  -   U-   n/ n	U R                    H!  n
U	R#                  U
R$                  S	   5        M#     Ub  U	R'                  U5        UR)                  XhS
S
SU	S9R+                  5       nOU R                  S:X  a  X`R,                  -   nX`R                  -   n/ n	U R                    H!  n
U	R#                  U
R$                  S	   5        M#     Ub  U	R'                  U5        UR)                  XlS
S
SU	S9R+                  5       nUR)                  XS
S
SS9R+                  5       nUnUR                    H+  n
U
R                  U5      nUR/                  X-
  U-   U
5        M-     O[	        S5      eX;   a  UR1                  U 5        US
L a,  U H&  n
U
R3                  XR                  U5      U-
  5        M(     U$ )aH  
Returns a Stream containing the elements which this variant replaces in a
given context stream.
This Stream will have length self.replacementDuration.

In regions that are strictly replaced, only elements that share a class with
an element in the variant
are captured. Elsewhere, all elements are captured.

>>> s = converter.parse("tinynotation: 4/4 d4 e4 f4 g4   a2 b-4 a4    g4 a8 g8 f4 e4    d2 a2                  d4 e4 f4 g4    a2 b-4 a4    g4 a8 b-8 c'4 c4    f1", makeNotation=False)
>>> s.makeMeasures(inPlace=True)
>>> v1stream = converter.parse("tinynotation: 4/4        a2. b-8 a8", makeNotation=False)
>>> v2stream1 = converter.parse("tinynotation: 4/4                                       d4 f4 a2", makeNotation=False)
>>> v2stream2 = converter.parse("tinynotation: 4/4                                                  d4 f4 AA2", makeNotation=False)

>>> v1 = variant.Variant()
>>> v1measure = stream.Measure()
>>> v1.insert(0.0, v1measure)
>>> for e in v1stream.notesAndRests:
...    v1measure.insert(e.offset, e)

>>> v2 = variant.Variant()
>>> v2measure1 = stream.Measure()
>>> v2measure2 = stream.Measure()
>>> v2.insert(0.0, v2measure1)
>>> v2.insert(4.0, v2measure2)
>>> for e in v2stream1.notesAndRests:
...    v2measure1.insert(e.offset, e)
>>> for e in v2stream2.notesAndRests:
...    v2measure2.insert(e.offset, e)

>>> v3 = variant.Variant()
>>> v2.replacementDuration = 4.0
>>> v3.replacementDuration = 4.0

>>> s.insert(4.0, v1)    # replacement variant
>>> s.insert(12.0, v2)  # insertion variant (2 bars replace 1 bar)
>>> s.insert(20.0, v3)  # deletion variant (0 bars replace 1 bar)

>>> v1.replacedElements(s).show('text')
{0.0} <music21.stream.Measure 2 offset=0.0>
    {0.0} <music21.note.Note A>
    {2.0} <music21.note.Note B->
    {3.0} <music21.note.Note A>

>>> v2.replacedElements(s).show('text')
{0.0} <music21.stream.Measure 4 offset=0.0>
    {0.0} <music21.note.Note D>
    {2.0} <music21.note.Note A>

>>> v3.replacedElements(s).show('text')
{0.0} <music21.stream.Measure 6 offset=0.0>
    {0.0} <music21.note.Note A>
    {2.0} <music21.note.Note B->
    {3.0} <music21.note.Note A>

>>> v3.replacedElements(s, keepOriginalOffsets=True).show('text')
{20.0} <music21.stream.Measure 6 offset=20.0>
    {0.0} <music21.note.Note A>
    {2.0} <music21.note.Note B->
    {3.0} <music21.note.Note A>


A second example:


>>> 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 = 4.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)

>>> v.replacedElements(s).show('t')
{0.0} <music21.stream.Measure 0 offset=0.0>
    {0.0} <music21.note.Note B>
    {0.5} <music21.note.Note C>
    {1.5} <music21.note.Note A>
    {2.0} <music21.note.Note A>
    {3.0} <music21.note.Note B>
c                T    U R                   =(       a    U R                  R                  $ r0   )hasStyleInformationstylehideObjectOnPrint)rs    r   <lambda>*Variant.replacedElements.<locals>.<lambda>  s    !6!6!T177;T;T!Tr   zLNo contextStream or activeSite, finding most recently added site (dangerous)Stream-Cannot find a Stream context for this object.Variant not found in stream Trf   )r   r   r   F)includeEndBoundarymustFinishInSpanmustBeginInSpan	classListr   )r   r   r   z7lengthType must be replacement, elongation, or deletion)
activeSiteenvironLocal
printDebuggetContextByClassr   getElementsByClassr-   getOffsetBySiter   Rest	addFilterfirstrz   r{   r   r   elementsr)   classesextendgetElementsByOffsetr   r;   insertremovesetOffsetBySite)r*   contextStreamr   keepOriginalOffsetsincludeSpacersspacerFiltervStartspacerDurationvEndr   rb   returnStreamvMiddlereturnPart1returnPart2oInParts                   r   replacedElementsVariant.replacedElements3  s   Z U  OOM$''bd $ 6 6x @ (*+Z[[77GG"%A-#QRR%%m4T!"11$))<(y6$uwxx 
 !N ??;;444~EDG]]qyy|, #$y)(<<V#(!& $!	 = # $*68	  __
*888G444DG]]qyy|, #$y)';;F#(!& $!	 < # $*68	 
 (;;G#(!& $ < & '-fh 
 'L ))++K8##G$4w$>B * ##\]]% %'!!!,0A0A,0ORX0XY " r   c                >   UcC  U R                   nUc4  [        R                  S5        U R                  S5      nUc  [	        S5      eXR                  U R                  5      ;  a  [	        SU 35      eU R                  X5      nU H  nUR                  U5        M     g)a  
remove replaced elements from a referenceStream or activeSite


>>> 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 = 4.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)

>>> v.removeReplacedElementsFromStream(s)
>>> s.show('t')
{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.variant.Variant object of length 8.0>
{8.0} <music21.stream.Measure 0 offset=8.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>
{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>
NzNNo referenceStream or activeSite, finding most recently added site (dangerous)r   r   r   )	r   r   r   r   r   r   r-   r   r   )r*   referenceStreamr   r   els        r    removeReplacedElementsFromStream(Variant.removeReplacedElementsFromStream  s    n ""ooO&'' )Y Z"&"8"8"B"**+Z[[99$..II"%A/AR#STT00L"B""2& #r   )r'   r&   r$   )r    z?t.Union[None, base.Music21Object, Sequence[base.Music21Object]]r+   z
str | Noner!   r   )T)F)NN)NNFF)#r   r   r   r   __doc__r   r   classSortOrderr   OFFSETSr#   r1   r7   r=   rF   rI   rN   rQ   rY   rc   propertyrg   rj   ro   r;   rt   rw   r|   r   r   r   r   r   r   __classcell__)r-   s   @r   r   r   5   sF   $L ]]11A5N @D7L7T7T%=%
 %  5% %0EK
D!$-!')
=.    ,0 	( 	( 
* 
*  -* ##:<S Z  ! ! >BCHwrD' D'r   r   FinPlacec               `   U R                   nSU;   a
  [        XX#S9$ U R                  [        R                  5      (       a
  [        XX#S9$ U R                  5       R                  (       a;  U R                  R                  UR                  R                  :X  a  [        X/U/US9$ [        S5      e)a  
Takes two streams objects or their derivatives (Score, Part, Measure, etc.) which
should be variant versions of the same stream,
and merges them (determines differences and stores those differences as variant objects
in streamX) via the appropriate merge
function for their type. This will not know how to deal with scores meant for
mergePartAsOssia(). If this is the intention, use
that function instead.

>>> streamX = converter.parse('tinynotation: 4/4 a4 b  c d', makeNotation=False)
>>> streamY = converter.parse('tinynotation: 4/4 a4 b- c e', makeNotation=False)

>>> mergedStream = variant.mergeVariants(streamX, streamY,
...                                      variantName='docVariant', inPlace=False)
>>> mergedStream.show('text')
{0.0} <music21.meter.TimeSignature 4/4>
{0.0} <music21.note.Note A>
{1.0} <music21.variant.Variant object of length 1.0>
{1.0} <music21.note.Note B>
{2.0} <music21.note.Note C>
{3.0} <music21.variant.Variant object of length 1.0>
{3.0} <music21.note.Note D>

>>> v0 = mergedStream.getElementsByClass(variant.Variant).first()
>>> v0
<music21.variant.Variant object of length 1.0>
>>> v0.first()
<music21.note.Note B->

>>> streamZ = converter.parse('tinynotation: 4/4 a4 b c d e f g a', makeNotation=False)
>>> variant.mergeVariants(streamX, streamZ, variantName='docVariant', inPlace=False)
Traceback (most recent call last):
music21.variant.VariantException: Could not determine what merging method to use.
        Try using a more specific merging function.


Example: Create a main score (aScore) and a variant score (vScore), each with
two parts (ap1/vp1
and ap2/vp2) and some small variants between ap1/vp1 and ap2/vp2, marked with * below.

>>> aScore = stream.Score()
>>> vScore = stream.Score()

>>> #                                                 *
>>> ap1 = converter.parse('tinynotation: 4/4   a4 b c d    e2 f   g2 f4 g ')
>>> vp1 = converter.parse('tinynotation: 4/4   a4 b c e    e2 f   g2 f4 a ')

>>> #                                                         *    *    *
>>> ap2 = converter.parse('tinynotation: 4/4   a4 g f e    f2 e   d2 g4 f ')
>>> vp2 = converter.parse('tinynotation: 4/4   a4 g f e    f2 g   f2 g4 d ')

>>> ap1.id = 'aPart1'
>>> ap2.id = 'aPart2'

>>> aScore.insert(0.0, ap1)
>>> aScore.insert(0.0, ap2)
>>> vScore.insert(0.0, vp1)
>>> vScore.insert(0.0, vp2)

Create one merged score where everything different in vScore from aScore is called a variant.

>>> mergedScore = variant.mergeVariants(aScore, vScore, variantName='docVariant', inPlace=False)
>>> mergedScore.show('text')
{0.0} <music21.stream.Part aPart1>
    {0.0} <music21.variant.Variant object of length 4.0>
    {0.0} <music21.stream.Measure 1 offset=0.0>
        {0.0} <music21.clef.TrebleClef>
        {0.0} <music21.meter.TimeSignature 4/4>
        {0.0} <music21.note.Note A>
        {1.0} <music21.note.Note B>
        {2.0} <music21.note.Note C>
        {3.0} <music21.note.Note D>
    {4.0} <music21.stream.Measure 2 offset=4.0>
        {0.0} <music21.note.Note E>
        {2.0} <music21.note.Note F>
    {8.0} <music21.variant.Variant object of length 4.0>
    {8.0} <music21.stream.Measure 3 offset=8.0>
        {0.0} <music21.note.Note G>
        {2.0} <music21.note.Note F>
        {3.0} <music21.note.Note G>
        {4.0} <music21.bar.Barline type=final>
{0.0} <music21.stream.Part aPart2>
    {0.0} <music21.stream.Measure 1 offset=0.0>
        {0.0} <music21.clef.TrebleClef>
        {0.0} <music21.meter.TimeSignature 4/4>
        {0.0} <music21.note.Note A>
        {1.0} <music21.note.Note G>
        {2.0} <music21.note.Note F>
        {3.0} <music21.note.Note E>
    {4.0} <music21.variant.Variant object of length 8.0>
    {4.0} <music21.stream.Measure 2 offset=4.0>
        {0.0} <music21.note.Note F>
        {2.0} <music21.note.Note E>
    {8.0} <music21.stream.Measure 3 offset=8.0>
        {0.0} <music21.note.Note D>
        {2.0} <music21.note.Note G>
        {3.0} <music21.note.Note F>
        {4.0} <music21.bar.Barline type=final>


>>> mergedPart = variant.mergeVariants(ap2, vp2, variantName='docVariant', inPlace=False)
>>> mergedPart.show('text')
{0.0} <music21.stream.Measure 1 offset=0.0>
...
{4.0} <music21.variant.Variant object of length 8.0>
{4.0} <music21.stream.Measure 2 offset=4.0>
...
    {4.0} <music21.bar.Barline type=final>
Scorer   z[Could not determine what merging method to use. Try using a more specific merging function.)r   mergeVariantScoresr   r   MeasuremergeVariantMeasureStreamsiternotesAndRestsrz   r{   mergeVariantsEqualDurationr   )streamXstreamYvariantNamer   classesXs        r   mergeVariantsr   5  s    ^ H(!'KQQ		#	#FNN	3	3)'KYY
,,.
&
&  ..'2B2B2P2PP)7*<{mU\]]<= 	=r   c               R   [        U R                  5       R                  5      [        UR                  5       R                  5      :w  a  [        S5      eUSL a  U nOU R	                  S5      n[        UR                  UR                  5       H  u  pV[        XVUSS9  M     USL a  U$ g)a  
Takes two scores and merges them with mergeVariantMeasureStreams, part-by-part.

>>> aScore, vScore = stream.Score(), stream.Score()

>>> ap1 = converter.parse('tinynotation: 4/4   a4 b c d    e2 f2   g2 f4 g4 ')
>>> vp1 = converter.parse('tinynotation: 4/4   a4 b c e    e2 f2   g2 f4 a4 ')

>>> ap2 = converter.parse('tinynotation: 4/4   a4 g f e    f2 e2   d2 g4 f4 ')
>>> vp2 = converter.parse('tinynotation: 4/4   a4 g f e    f2 g2   f2 g4 d4 ')

>>> aScore.insert(0.0, ap1)
>>> aScore.insert(0.0, ap2)
>>> vScore.insert(0.0, vp1)
>>> vScore.insert(0.0, vp2)

>>> mergedScores = variant.mergeVariantScores(aScore, vScore,
...                                           variantName='docVariant', inPlace=False)
>>> mergedScores.show('text')
{0.0} <music21.stream.Part ...>
    {0.0} <music21.variant.Variant object of length 4.0>
    {0.0} <music21.stream.Measure 1 offset=0.0>
        {0.0} <music21.clef.TrebleClef>
        {0.0} <music21.meter.TimeSignature 4/4>
        {0.0} <music21.note.Note A>
        {1.0} <music21.note.Note B>
        {2.0} <music21.note.Note C>
        {3.0} <music21.note.Note D>
    {4.0} <music21.stream.Measure 2 offset=4.0>
        {0.0} <music21.note.Note E>
        {2.0} <music21.note.Note F>
    {8.0} <music21.variant.Variant object of length 4.0>
    {8.0} <music21.stream.Measure 3 offset=8.0>
        {0.0} <music21.note.Note G>
        {2.0} <music21.note.Note F>
        {3.0} <music21.note.Note G>
        {4.0} <music21.bar.Barline type=final>
{0.0} <music21.stream.Part ...>
    {0.0} <music21.stream.Measure 1 offset=0.0>
        {0.0} <music21.clef.TrebleClef>
        {0.0} <music21.meter.TimeSignature 4/4>
        {0.0} <music21.note.Note A>
        {1.0} <music21.note.Note G>
        {2.0} <music21.note.Note F>
        {3.0} <music21.note.Note E>
    {4.0} <music21.variant.Variant object of length 8.0>
    {4.0} <music21.stream.Measure 2 offset=4.0>
        {0.0} <music21.note.Note F>
        {2.0} <music21.note.Note E>
    {8.0} <music21.stream.Measure 3 offset=8.0>
        {0.0} <music21.note.Note D>
        {2.0} <music21.note.Note G>
        {3.0} <music21.note.Note F>
        {4.0} <music21.bar.Barline type=final>
zGThese scores do not have the same number of parts and cannot be merged.Tr   r   FN)rM   r   partsr   coreCopyAsDerivationzipr   )aScorevScorer   r   	returnObj
returnPartvParts          r   r   r     s    r 6;;=3v{{}':':#;;UW 	W $	//0DE	 &,,?
":k4P @ % r   c          	        USL a  U nOU R                  S5      n[        XA5      nU GH-  u  pgnpU[        UR                  [        R
                  5      5      :  a  UR                  R                  nO#UR                  US-   5      R                  U5      nSnSnUS:X  a  Mz  US:X  aA  UR                  US-   U5      nUR                  R                  nUR                  U	S-   U
5      nOaUS:X  a.  UR                  US-   U5      nUR                  R                  nSnO-US	:X  a  UR                  U	S-   U
5      nSnO[        S
U< 35      e[        XKUX-S9  GM0     USL a  gU$ )a  
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 mergeVariantsEqualDuration 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.


>>> 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)
>>> #_DOCS_SHOW stream1.show()


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

>>> #_DOCS_SHOW stream2.show()


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

>>> mergedStream = variant.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 of length 0.0>
{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 of length 4.0>
{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 of length 8.0>

>>> mergedStream[variant.Variant][0].replacementDuration
4.0
>>> mergedStream[variant.Variant][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 of length 4.0>
{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 of length 0.0>
{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 of length 0.0>
{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[variant.Variant][0].replacementDuration
0.0
>>> parisStream[variant.Variant][1].replacementDuration
4.0
>>> parisStream[variant.Variant][2].replacementDuration
8.0
Tr      Nrf   equalr_   deleter   Unknown regionType )r   r   )r   _getRegionsFromStreamsrM   r   r   r   rz   r{   measurer   measuresr   
addVariant)r   r   r   r   r   regions
regionTypexRegionStartMeasurexRegionEndMeasureyRegionStartMeasureyRegionEndMeasurestartOffsetyRegionr   xRegions                  r   r   r     s   n $	001MN	$Y8G7>	4*; #i&B&B6>>&R"SS#,,::K $++,?!,CDTTU^_K! 9$(()<q)@BSTG")"2"2"@"@&&':Q'>@QRG8#(()<q)@BSTG")"2"2"@"@G8#&&':Q'>@QRG"%"%8#GHH97*	U; 8?@ $r   c          
        USL a  U S   nOU S   R                  S5      nUR                  SS5        [        U 5      [        U5      :  a+  UR                  S5        [        U 5      [        U5      :  a  M+  [        U 5      [        U5      :  a*  UR	                  5         [        U 5      [        U5      :  a  M*  [        [        X5      5      nUSS  GHs  u  pVUR                  UR                  :w  a  [        S5      eUR                  [        R                  5      nU(       a  UR                  [        R                  5      n[        U5       H}  u  pX   nU
R                  [        R                  5      nU(       aC  [        U5       H2  u  pUR                  [        R                  5      U   n[        XUSS9  M4     Mr  [        XUSS9  M     M  UR                  [        R                  5      nU(       aD  [        U5       H2  u  pUR                  [        R                  5      U   n[        XUSS9  M4     GMh  [        X5USS9  GMv     U$ )a!  
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.


>>> 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 = variant.mergeVariantsEqualDuration(
...       [stream1, stream2paris, stream3london], ['paris', 'london'])
>>> mergedStreams.show('t')
{0.0} <music21.note.Note A>
{1.0} <music21.variant.Variant object of length 1.0>
{1.0} <music21.note.Note B>
{1.5} <music21.note.Note C>
{2.0} <music21.note.Note A>
{3.0} <music21.variant.Variant object of length 1.0>
{3.0} <music21.note.Note A>
{4.0} <music21.note.Note B>
{4.5} <music21.variant.Variant object of length 1.5>
{4.5} <music21.note.Note C>
{5.0} <music21.note.Note A>
{6.0} <music21.note.Note A>
{7.0} <music21.variant.Variant object of length 1.0>
{7.0} <music21.note.Note B>
{8.0} <music21.note.Note C>
{9.0} <music21.variant.Variant object of length 2.0>
{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 of length 1.0>
{1.0} <music21.note.Note B>
{1.5} <music21.note.Note C>
{2.0} <music21.note.Note A>
{3.0} <music21.variant.Variant object of length 1.0>
{3.0} <music21.note.Note A>
{4.0} <music21.note.Note B>
{4.5} <music21.variant.Variant object of length 1.5>
{4.5} <music21.note.Note C>
{5.0} <music21.note.Note A>
{6.0} <music21.note.Note A>
{7.0} <music21.variant.Variant object of length 1.0>
{7.0} <music21.note.Note C>
{8.0} <music21.note.Note C>
{9.0} <music21.variant.Variant object of length 2.0>
{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 = variant.mergeVariantsEqualDuration([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 of length 1.0>
        {1.0} <music21.note.Note B>
        {1.5} <music21.note.Note C>
        {2.0} <music21.note.Note A>
        {3.0} <music21.variant.Variant object of length 1.0>
        {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 of length 1.5>
        {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 of length 3.0>
        {1.0} <music21.note.Note D>
        {2.0} <music21.note.Note E>
        {3.0} <music21.note.Note E>
>>> #_DOCS_SHOW mergedStreams.show()


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


>>> for p in mergedStreams.getElementsByClass(stream.Part):
...    for m in p.getElementsByClass(stream.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 of length 1.0>
        {1.0} <music21.note.Note B>
        {2.0} <music21.note.Note A>
        {3.0} <music21.variant.Variant object of length 1.0>
        {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 of length 1.5>
        {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 of length 3.0>
        {1.0} <music21.note.Note B>
        {2.0} <music21.note.Note A>
        {3.0} <music21.note.Note A>
>>> #_DOCS_SHOW 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 = variant.mergeVariantsEqualDuration(
...                 [stream1, streamDifferentMeasures], ['paris'])
Traceback (most recent call last):
music21.variant.VariantException: _mergeVariants cannot merge streams
    which are of different lengths
Tr   r   Nr   z)cannot merge streams of different lengthsr   r   )r   r   rM   r)   poplistr   rg   r   r   r   Part	enumerater   _mergeVariants)streamsvariantNamesr   r   zippedsr   returnObjPartssPartsireturnObjPartsPartreturnObjMeasuresjreturnObjMeasuresMeasures                   r   r   r     s   ` $AJ	AJ334PQ	 4 
g,\*
*D! g,\*
*
g,\*
* g,\*
* #g,-F *  AMM1"#NOO"55fkkB))&++6F$-n$= 	$1$D$DV^^$T!$/89J/K+#(#;#;FNN#KA#N&,KY]_ 0L #=[Z^_ %> !* < <V^^ L +45F+G'A 33FNNCAFH"#3/:DJ ,H
 ydS9 %< r   c           
        USL a  U nOU R                  S5      nUSL a  UR                  [        R                  5       Hf  nUR                  (       d  M  UR
                  nUR                  U5      n	USL a  [        X/U/SS9  MG  U	R                  U5      n
[        UU
UUSSS9  Mh     OUR                  [        R                  5       H  nUR                  (       d  M  UR                  U5      n
USL aK  UR                  U
5      R                  [        R                  5      R                  5       n	[        X/U/SS9  Mw  [        XjUUSSS9  M     USL a  gU$ )a  
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.

Note that this method has no way of knowing if a variant is supposed to be a
different duration than the segment of stream which it replaces
because that information is not contained in the format of score this method is
designed to deal with.


>>> mainStream = converter.parse('tinynotation: 4/4   A4 B4 C4 D4   E1    F2 E2     E8 F8 F4 G2   G2 G4 F4   F4 F4 F4 F4   G1      ')
>>> ossiaStream = converter.parse('tinynotation: 4/4  r1            r1    r1        E4 E4 F4 G4   r1         F2    F2      r1      ')
>>> mainStream.makeMeasures(inPlace=True)
>>> ossiaStream.makeMeasures(inPlace=True)

>>> 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)
>>> #_DOCS_SHOW 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 of length 3.0>
    {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 of length 4.0>
    {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 of length 4.0>
{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 of length 4.0>
{20.0} <music21.stream.Measure 6 offset=20.0>
    {0.0} <music21.note.Note F>
    {2.0} <music21.note.Note F>
...

TmergePartAsOssiar   N)r   variantGroupsr   )r   r   r   r   notesnumberr   r   r   r   r   r   )mainPart	ossiaPart	ossiaNamer   compareByMeasureNumberrecurseInMeasuresr   ossiaMeasureossiaNumberreturnMeasureossiaOffsets              r   r  r    s`   R $	112DE	%%88HL!!!*11 ) 1 1+ >$,.&5" $ #0"?"?	"JKy*++4-137! I( &88HL!!!*::9E$,$-$A$A#%((8 " /&5" $ y|+4D^bd I  $r   c                   [        5       nUb  XFl        Ub  UR                  R                  U5        XVl        Uc  O[	        U[
        R                  5      (       a  UR                  U5        OoUR                  [
        R                  5      nU(       d/  U H(  nUR                  U5      U-   n	UR                  X5        M*     OU H  n
UR                  U
5        M     U R                  X5        g)a*
  
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.


>>> 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')]
>>> data1 = [data1M1, data1M2, data1M3]
>>> tempPart = stream.Part()
>>> stream1 = 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)

>>> data2M2 = [('b', 'eighth'), ('c', 'quarter'), ('a', 'eighth'),
...            ('a', 'quarter'), ('b', 'quarter')]
>>> stream2 = stream.Stream()
>>> m = stream.Measure()
>>> for pitchName, durType in data2M2:
...    n = note.Note(pitchName)
...    n.duration.type = durType
...    m.append(n)
>>> stream2.append(m)
>>> variant.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 of length 4.0>
{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
>>> variant.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 of length 6.0>
{3.0} <music21.note.Note E>
{4.0} <music21.note.Note E>
{5.0} <music21.note.Note E>
N)
r   r(   r)   r   
isinstancer   r   r   r   r   )r   r   sVariantr   r  r   tempVariantsVariantMeasuresrb   offsetms              r   r   r   Y  s    f )K *!!+.&9#h//x('::6>>J#!A..x8;FF&&v1 " *A&&q) * HH[&r   c          	        XR                  [        5      ;  a  [        U SU  S35      eUSL a  U nUnOPU R                  [        5      R                  U5      nU R	                  S5      nUR                  [        5      " U5      nUR
                  nUR                  nUR                  U 5      nUR                  U5      n	[        [        [        U	5      5      5      n
0 n0 n[        U	UUU5      u  p[        R                  " 5       nUR                  X5        UR!                  5       nU GH  u  nnnnnU	U   R                  U	5      nSnUS:X  a9  U	R#                  US-   U5      nUR#                  US-   U5      n[%        UU/USS9  M_  US	:X  aA  U	R#                  US-   U5      nUR&                  R(                  nUR#                  US-   U5      nOaUS
:X  a.  U	R#                  US-   U5      nUR&                  R(                  nSnO-US:X  a  UR#                  US-   U5      nSnO[        SU< 35      e[+        U	UUUUS9  GM     UR-                  U5        U(       a  gU$ )aG  
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 these 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.


>>> 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)

>>> variant.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 of length 1.5>
    {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 of length 3.0>
    {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>

z not found in stream .TrefineVariantNr   r   r   r_   r   r   rf   r   r  r   )r   r   r   indexr   r(   r   r   r   r   rangerM   _getBestListAndScoredifflibSequenceMatcherset_seqsget_opcodesr   r   rz   r{   r   r   )r   r  r   returnObjectvariantRegionsVariantIndexr  r   r   returnRegionreturnRegionMeasureListbadnessDictlistDictvariantMeasureListunused_badnesssmr   r   returnStart	returnEndvariantStart
variantEndvariantSubRegionreturnSubRegions                           r   r  r    s   ` ++G44(+@1EFF$ ,,W5;;HE--o>$77@O OOM"66**1-K !11,?L #5\):#;<KH)=l>K>I>F*H& 
	 	 	"BKK'<nnG IPD
KL*";/??M   *33K!OYOO,55lQ6F
S& "23
 9$*33K!OYOO"1":":"H"H,55lQ6F
S8#*33K!OYOO"1":":"H"H#8#,55lQ6F
S"%"%8#GHH<#!.':		9 IPJ &r   c          	     J   USL a  U nUnO,[         R                  " U 5      n[         R                  " U5      n[        [        [	        UR                  [        R                  5      5      5      5      n0 n0 n[        UR                  [        R                  5      UR                  [        R                  5      UU5      u  p[        R                  " 5       nUR                  Xi5        UR                  5       nU GH  u  pnnnUR                  US-   5      R                  U5      nUS:X  a8  UR                  US-   U5      nUR                  US-   U5      n[!        UUUSS9  Mj  US:X  aA  UR                  US-   U5      nUR"                  R$                  nUR                  US-   U5      nO`US:X  a.  UR                  US-   U5      nUR"                  R$                  nSnO,US:X  a  UR                  US-   U5      nS	nO['        S
U 35      e[)        UUUU/US9  GM"     U(       d  U$ g)z}
There seem to be some problems with this function, and it isn't well tested.
It is not recommended to use it at this time.

Tr   r   r   r_   r   Nr   rf   zUnknown regionType: r  )copydeepcopyr   r  rM   r   r   r   r  r  r  r  r  r   r   r   r   rz   r{   r   r   )r   r   r   r   r   variantObjectreturnObjectMeasureListr%  r&  variantObjectMeasureListr(  r)  r   r   r*  r+  r,  r-  r   r/  r.  r   s                         r   $_mergeVariantMeasureStreamsCarefullyr6  o  s,    $}}W-g. #5\-L-LV^^-\)]#^_KH/C''7((8	0, 
	 	 	"BKK'BnnG IPD
L*"**;?;KKLY *33K!OYOO,55lQ6F
S& 	 9$*33K!OYOO"1":":"H"H,55lQ6F
S8#*33K!OYOO"1":":"H"H#8#,55lQ6F
S"%"%9*#FGG 	&- 3	
7 IPF  r   c                R   / n[        U [        5      (       a:  U  H2  nUR                  [        R                  " UR
                  5      5        M4     U$ U R                  [        R                  5       H2  nUR                  [        R                  " UR
                  5      5        M4     U$ )aL  
Takes in a stream containing measures and returns a list of hashes,
one for each measure. This is currently implemented
with search.translateStreamToString()

>>> s = converter.parse("tinynotation: 2/4 c4 d8. e16 FF4 a'4 b-2")
>>> sm = s.makeMeasures()
>>> hashes = variant.getMeasureHashes(sm)
>>> hashes
['<P>K@<', ')PQP', 'FZ']
)	r  r   r)   r   translateStreamToStringr   r   r   r   )r   hashesr  s      r   getMeasureHashesr:    sy     F!TAMM&88IJ %%fnn5AMM&88IJ 6r   c                   SnSn/ n	U[        U5      :  a  / X5Xd4'   SX%Xd4'   / S4$ XVU4U;   a  X%Xd4   n
X5Xd4   n	X4$ US:X  a	  US:X  a  SnOU(       a  SnO[        X   X   5      n[        XX#SXVS-   S9u  pUc  / nU(       a  U[        U5      -  nOSnX::  a  UnUnUn	[        US-   [        U 5      5       H?  n[        XUUSXS-   S9u  pUc  / nU(       a  U[        U5      -  nOSnX::  d  M9  UnUnUn	MA     [        R
                  " U	5      nU(       a  UR                  SS	5        OUS:X  a  OUR                  SU5        X{-   n
XXVU4'   UX5Xd4'   UU
4$ )
a
  
This is a recursive function which makes a map between two related streams of measures.
It is designed for streams of measures that contain few if any measures that are actually
identical and that have a different number of measures (within reason). For example,
if one stream has 10 bars of eighth notes and the second stream has the same ten bars
of eighth notes except with some dotted rhythms mixed in and the fifth bar is repeated.
The first, streamX, is the reference stream. This function returns a list of
integers with length len(streamY) which maps each measure of StreamY to the measure
in streamX it is most likely associated with. For example, if the returned list is
[0, 2, 3, 'addedBar', 4]. This indicates that streamY is most similar to streamX
after the second bar of streamX has been removed and a new bar inserted between
bars 4 and 5. Note that this list has measures 0-indexed. This function generates this map by
minimizing the difference or 'badness' for the sequence of measures on the whole as determined
by the helper function _simScore which compares measures for similarity. 'addedBar' appears
in the list where this function has determined that the bar appearing
in streamY does not have a counterpart in streamX anywhere and is an insertion.


>>> badnessDict = {}
>>> listDict = {}
>>> 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'), ('c', 'quarter'), ('g#', 'quarter')]
>>> data2M2 = [('b', 'eighth'), ('c', 'quarter'), ('a', 'eighth'),
...            ('a', 'quarter'), ('b', 'quarter')]
>>> data2M3 = [('c', 'quarter'), ('b', 'quarter'), ('a', 'quarter'), ('a', 'quarter')]
>>> data2M4 = [('c', 'quarter'), ('b', 'quarter'), ('a', 'quarter'), ('a', 'quarter')]
>>> data1 = [data1M1, data1M2, data1M3]
>>> data2 = [data2M1, data2M2, data2M3, data2M4]
>>> 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)
>>> for d in data2:
...    m = stream.Measure()
...    for pitchName, durType in d:
...        n = note.Note(pitchName)
...        n.duration.type = durType
...        m.append(n)
...    stream2.append(m)
>>> kList, kBadness = variant._getBestListAndScore(stream1, stream2,
...                                                badnessDict, listDict, isNone=False)
>>> kList
[0, 1, 2, 'addedBar']
r   rf   r   g      ?T)isNonestreamXIndexstreamYIndexFaddedBar)rM   
_diffScorer  r  r1  r2  r   )r   r   r%  r&  r=  r>  r?  	bestScorebestNormalizedScorebestListbadnesssimScorekListkBadnessnormalizedBadnessk
returnLists                    r   r  r    s   v IH s7|#9;56<?<891u 	F+{:\BC<@A   rlb0	g3W5JK +7[#'l`aQacOE}$s5z1/	/ <!#S\2.w/7<=[\L\^ =E (3u: 5 !3 I"3H 3" x(J!Z(		!\*"G8?V455?HL12wr   c                    [        X/5      nUS   US   :X  a  SnOSnU R                  UR                  -
  n[        U5      S-  nX5-   $ )a  
Helper function for _getBestListAndScore which compares two measures and returns a value
associated with their similarity. The higher the normalized (0, 1) value the poorer the match.
This should be calibrated such that the value that appears in _getBestListAndScore for
isNone is true (i.e. testing when a bar does not associate with any existing bars the reference
stream), is well-matched with the similarity scores generated by this function.


>>> m1 = stream.Measure()
>>> m2 = stream.Measure()
>>> m1.append([note.Note('e'), note.Note('f'), note.Note('g'), note.Note('a')])
>>> m2.append([note.Note('e'), note.Note('f'), note.Note('g#'), note.Note('a')])
>>> variant._diffScore(m1, m2)
0.4...

r   r   rf   g?gMbP?)r:  r  float)measureXmeasureYr9  	baseValuenumberDeltadistanceModifiers         r   rA  rA  V  sX    " x23FayF1I		//HOO3K[)E1 ''r   c                    [        U 5      n[        U5      n[        R                  " 5       nUR                  X#5        UR	                  5       nU$ )ab  
Takes in two streams, returns a list of 5-tuples via difflib.get_opcodes()
working on measure differences.


>>> s1 = converter.parse("tinynotation: 2/4 d4 e8. f16 GG4 b'4 b-2 c4 d8. e16 FF4 a'4 b-2")

                                            *0:Eq  *1:Rep        * *3:Eq             *6:In

>>> s2 = converter.parse("tinynotation: 2/4 d4 e8. f16 FF4 b'4 c4 d8. e16 FF4 a'4 b-2 b-2")
>>> s1m = s1.makeMeasures()
>>> s2m = s2.makeMeasures()
>>> regions = variant._getRegionsFromStreams(s1m, s2m)
>>> regions
[('equal', 0, 1, 0, 1),
 ('replace', 1, 3, 1, 2),
 ('equal', 3, 6, 2, 5),
 ('insert', 6, 6, 5, 6)]

)r:  r  r  r  r  )r   r   hashesXhashesYr)  r   s         r   r   r   u  sC    , w'Gw'G		 	 	"BKK!nnGNr   r   c          	     ,   U R                  [        R                  5      (       dl  U R                  [        R                  5      (       dH  UR                  [        R                  5      (       d$  UR                  [        R                  5      (       a  [	        S5      eU R
                  UR
                  :w  a  [	        S5      eUSL a  U nO[        R                  " U 5      nSnSnSnU R                  5       R                  nUR                  5       R                  n	/ n
SnU[        U5      :  Ga  U[        U	5      :  Ga  U[        U5      :X  a  [        U5      S-
  nU[        U	5      :X  a  GO|X   R                  U R                  5       5      X   R                  UR                  5       5      :X  a  X   X   :w  aR  USL a9  X   R                  UR                  5       5      nSn/ n
U
R                  X   5        O>U
R                  X   5        O*USL a#  UR                  U[        U
UUU5      5        Sn/ n
OSnUS-  nUS-  nGM%  X   R                  U R                  5       5      X   R                  UR                  5       5      :  aY  USL a9  X   R                  UR                  5       5      n/ n
U
R                  X   5        SnOU
R                  X   5        US-  nGM  US-  nGM  USL a"  UR                  U[        U
UUU5      5        Sn/ n
USL a  gU$ )	a  
This is a helper function for mergeVariantsEqualDuration which takes two streams
(which cannot contain container
streams like measures and parts) and merges the second into the first via variant objects.
If the first already contains variant objects, containsVariants should be set to true and the
function will compare streamB to the streamA as well as the
variant streams contained in streamA.
Note that variant streams in streamB will be ignored and lost.


>>> stream1 = stream.Stream()
>>> stream2 = 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')]
>>> 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
...    stream2.append(n)
>>> mergedStreams = variant._mergeVariants(stream1, stream2, variantName='paris')
>>> mergedStreams.show('t')
{0.0} <music21.note.Note A>
{1.0} <music21.variant.Variant object of length 1.0>
{1.0} <music21.note.Note B>
{1.5} <music21.note.Note C>
{2.0} <music21.note.Note A>
{3.0} <music21.variant.Variant object of length 1.0>
{3.0} <music21.note.Note A>
{4.0} <music21.note.Note B>
{4.5} <music21.variant.Variant object of length 1.5>
{4.5} <music21.note.Note C>
{5.0} <music21.note.Note A>
{6.0} <music21.note.Note A>
{7.0} <music21.note.Note B>
{8.0} <music21.note.Note C>
{9.0} <music21.variant.Variant object of length 2.0>
{9.0} <music21.note.Note D>
{10.0} <music21.note.Note E>

>>> mergedStreams.activateVariants('paris').show('t')
{0.0} <music21.note.Note A>
{1.0} <music21.variant.Variant object of length 1.0>
{1.0} <music21.note.Note B>
{2.0} <music21.note.Note A>
{3.0} <music21.variant.Variant object of length 1.0>
{3.0} <music21.note.Note G>
{4.0} <music21.note.Note B>
{4.5} <music21.variant.Variant object of length 1.5>
{4.5} <music21.note.Note C>
{5.5} <music21.note.Note A>
{6.0} <music21.note.Note A>
{7.0} <music21.note.Note B>
{8.0} <music21.note.Note C>
{9.0} <music21.variant.Variant object of length 2.0>
{9.0} <music21.note.Note B>
{10.0} <music21.note.Note A>

>>> stream1.append(note.Note('e'))
>>> mergedStreams = variant._mergeVariants(stream1, stream2, variantName=['paris'])
Traceback (most recent call last):
music21.variant.VariantException: _mergeVariants cannot merge streams
    which are of different lengths
zD_mergeVariants cannot merge streams which contain measures or parts.zB_mergeVariants cannot merge streams which are of different lengthsTr   Frf   r   N)r   r   r   r   r   rg   r1  r2  flattenr   rM   r   r)   r   _generateVariant)streamAstreamBr   r   r   r   r   	inVariantstreamANotesstreamBNotes
noteBufferr,  s               r   r   r     s   T 	""6>>22))&++66))&..99))&++66R
 	
 g111P
 	
 $	MM'*		A	AI??$22L??$22LJL
c,
AL(9$9L!!L!A%AL!!O++GOO,=>?227??3DEF ,/1%#/?#B#B7??CT#UL $I!#J%%lo6%%lo6$$$$(&#('	 !&I!#J %IFAFAo--goo.?@//0ABCE!+>>w?PQ
!!,/2 	!!,/2FA FAD		
 	
$r   c                    [        5       nU  H5  nUR                  UR                  UR                  5       5      U-
  U5        M7     Ub  UR                  R                  U5        U$ )a  
Helper function for mergeVariantsEqualDuration which takes a list of
consecutive notes from a stream and returns
a variant object containing the notes from the list at the offsets
derived from their original context.

>>> originStream = stream.Stream()
>>> data = [('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')]
>>> for pitchName, durType in data:
...    n = note.Note(pitchName)
...    n.duration.type = durType
...    originStream.append(n)
>>> noteList = []
>>> for n in originStream.notes[2:5]:
...    noteList.append(n)
>>> start = originStream.notes[2].offset
>>> variantName='paris'
>>> v = variant._generateVariant(noteList, originStream, start, variantName)
>>> v.show('text')
{0.0} <music21.note.Note C>
{0.5} <music21.note.Note A>
{1.5} <music21.note.Note A>

>>> v.groups
['paris']

)r   r   r   rW  r(   r)   )noteListoriginStreamstartr   returnVariantns         r   rX  rX  A  s`    @ IMQ..|/C/C/EFNPQR ##K0r   c                    USL a  U nO[         R                  " U 5      nUSL a   UR                  SS9 H  n[        XQS9  M     O	[        XAS9  USL a  gU$ )af	  
This function takes a stream and a list of variantNames
(default works on all variants), and changes all insertion
(elongations with replacementDuration 0)
and deletion variants (with containedHighestTime 0) into variants with non-zero
replacementDuration and non-null elements
by adding measures on the front of insertions and measures on the end
of deletions. This is designed to make it possible to format all variants in a
readable way as a graphical ossia (via lilypond). If inPlace is True
it will perform this action on the stream itself; otherwise it will return a
modified copy. If recurse is True, this
method will work on variants within container objects within the stream (like parts).

>>> #                                                          *                                            *                                *
>>> s = converter.parse("tinynotation: 4/4       d4 e4 f4 g4   a2 b-4 a4    g4 a8 g8 f4 e4    d2 a2                        d4 e4 f4 g4    a2 b-4 a4    g4 a8 b-8 c'4 c4    f1")
>>> s2 = converter.parse("tinynotation: 4/4      d4 e4 f4 g4   a2. b-8 a8   g4 a8 g8 f4 e4    d2 a2   d4 f4 a2  d4 f4 AA2  d4 e4 f4 g4                 g4 a8 b-8 c'4 c4    f1")
>>> #                                                          replacement                            insertion                            deletion
>>> s.makeMeasures(inPlace=True)
>>> s2.makeMeasures(inPlace=True)
>>> variant.mergeVariants(s, s2, variantName='london', inPlace=True)

>>> newStream = stream.Score(s)

>>> returnStream = variant.makeAllVariantsReplacements(newStream, recurse=False)
>>> for v in returnStream.parts[0][variant.Variant]:
...     (v.offset, v.lengthType, v.replacementDuration)
(4.0, 'replacement', 4.0)
(16.0, 'elongation', 0.0)
(20.0, 'deletion', 4.0)

>>> returnStream = variant.makeAllVariantsReplacements(
...                            newStream, variantNames=['france'], recurse=True)
>>> for v in returnStream.parts[0][variant.Variant]:
...     (v.offset, v.lengthType, v.replacementDuration)
(4.0, 'replacement', 4.0)
(16.0, 'elongation', 0.0)
(20.0, 'deletion', 4.0)

>>> variant.makeAllVariantsReplacements(newStream, recurse=True, inPlace=True)
>>> for v in newStream.parts[0][variant.Variant]:
...     (v.offset, v.lengthType, v.replacementDuration, v.containedHighestTime)
(4.0, 'replacement', 4.0, 4.0)
(12.0, 'elongation', 4.0, 12.0)
(20.0, 'deletion', 8.0, 4.0)

T)streamsOnly)r   N)r1  r2  recurse_doVariantFixingOnStream)streamWithVariantsr   r   rg  r   r   s         r   makeAllVariantsReplacementsrj  j  sc    h $)}}%78$%%$%7A$QB 8 	!I $r   c                T   U R                  [        5       GH  n[        U[        5      (       a.  [	        UR
                  5      (       a  [	        U5      (       d  ME  MG  UR                  nUR                  nUR                  nUS:X  a	  US:X  a  SnOUS:X  a	  US:X  a  SnOM  UR                  U 5      S:X  a  SnSnO?UR                  U 5      UR                  -   U R                  R                  :X  a  SnSnOSnSnUS:X  a  USL d  US:X  a  USL a  [        X5      n	[        U	[        R                  5      (       aU  U	R                   HE  n
[        U
[         R"                  [$        R&                  45      (       d  M4  U	R)                  U
5        MG     UR+                  [,        R.                  " U	5      5        O[1        X5      n	U	R                  U 5      nU	R                  R                  nUR2                   H<  n
U
R                  UR2                  5      nU
R5                  UR2                  X-   5        M>     UR7                  S[,        R.                  " U	5      5        U R)                  U5        U R7                  X5        UR                  nXR                  R                  -   Ul        GM     g)a
  
This is a helper function for makeAllVariantsReplacements.
It iterates through the appropriate variants
and performs the variant changing operation to eliminate strict deletion and insertion variants.

>>> #                                           *                           *                                            *                                *                           *
>>> s = converter.parse("tinynotation: 4/4                    d4 e4 f4 g4   a2 b-4 a4    g4 a8 g8 f4 e4    d2 a2                        d4 e4 f4 g4    a2 b-4 a4    g4 a8 b-8 c'4 c4    f1    ", makeNotation=False)
>>> s2 = converter.parse("tinynotation: 4/4      a4 b c d     d4 e4 f4 g4   a2. b-8 a8   g4 a8 g8 f4 e4    d2 a2   d4 f4 a2  d4 f4 AA2  d4 e4 f4 g4                 g4 a8 b-8 c'4 c4          ", makeNotation=False)
>>> #                                        initial insertion              replacement                            insertion                            deletion                        final deletion
>>> s.makeMeasures(inPlace=True)
>>> s2.makeMeasures(inPlace=True)
>>> variant.mergeVariants(s, s2, variantName='london', inPlace=True)

>>> variant._doVariantFixingOnStream(s, 'london')
>>> s.show('text')
{0.0} <music21.variant.Variant object of length 8.0>
{0.0} <music21.stream.Measure 1 offset=0.0>
...
{4.0} <music21.variant.Variant object of length 4.0>
{4.0} <music21.stream.Measure 2 offset=4.0>
...
{12.0} <music21.variant.Variant object of length 12.0>
{12.0} <music21.stream.Measure 4 offset=12.0>
...
{20.0} <music21.variant.Variant object of length 4.0>
{20.0} <music21.stream.Measure 6 offset=20.0>
...
{24.0} <music21.variant.Variant object of length 4.0>
{24.0} <music21.stream.Measure 7 offset=24.0>
...

>>> for v in s[variant.Variant]:
...     (v.offset, v.lengthType, v.replacementDuration)
(0.0, 'elongation', 4.0)
(4.0, 'replacement', 4.0)
(12.0, 'elongation', 4.0)
(20.0, 'deletion', 8.0)
(24.0, 'deletion', 8.0)


This also works on streams with variants that contain notes and rests rather than measures.

>>> s = converter.parse('tinyNotation: 4/4                     e4 b b b   f4 f f f   g4 a a a       ', makeNotation=False)
>>> v1Stream = converter.parse('tinyNotation: 4/4   a4 a a a                                       ', makeNotation=False)
>>> #                                               initial insertion     deletion
>>> v1 = variant.Variant(v1Stream.notes)
>>> v1.replacementDuration = 0.0
>>> v1.groups = ['london']
>>> s.insert(0.0, v1)

>>> v2 = variant.Variant()
>>> v2.replacementDuration = 4.0
>>> v2.groups = ['london']
>>> s.insert(4.0, v2)

>>> variant._doVariantFixingOnStream(s, 'london')
>>> for v in s[variant.Variant]:
...     (v.offset, v.lengthType, v.replacementDuration, v.containedHighestTime)
(0.0, 'elongation', 1.0, 5.0)
(4.0, 'deletion', 5.0, 1.0)
r   rf   	insertionr   TFN)r   r   r  r   setr(   r   r   r;   r   rz   r{   _getNextElementsr   r   r   r   Clefr
   TimeSignaturer   r)   r1  r2  _getPreviousElementrw   r   r   )r   r   vr   r   rg   variantType	isInitialisFinaltargetElementrb   newVariantOffsetoffsetShift	oldOffsetoldReplacementDurations                  r   rh  rh    s5   @ !!'*lD))188}}S%6%6\\
33,,%*=*D%K:%+*<$KQ3&IGq!A$9$99QZZ=U=UUIGIG K'Y$->:-7e3C,Q2M -77&//A!!dii1D1D%EFF%,,Q/ 0 HHT]]=12 05M,<<Q?'00>>K__--aoo>	!!!//93JK % HHS$--67HHQKHH%) "#!6!6 69O9O9]9] ]{ +r   c           	        UR                  U 5      nUR                  nUS:X  aZ  [        UR                  / SQ5      R	                  5       5      n[        U[        R                  5      (       a  [        R                  nOY[        UR                  / SQ5      R	                  5       5      n[        U[        R                  5      (       a  [        R                  nUS:X  aB  UR                  U 5      nU R                  UU R                  SSSU/S9nUR	                  5       nU$ UR                  n	UR                  U 5      nU R                  Xi-   U R                  SSSU/S9nUR	                  5       nU$ )a  
This is a helper function for makeAllVariantsReplacements() which returns the next element in s
of the type of elements found in the variant v so that it can be added to v.


>>> #                                                   *                       *
>>> s1 = converter.parse('tinyNotation: 4/4             b4 c d e    f4 g a b   d4 e f g   ', makeNotation=False)
>>> s2 = converter.parse('tinyNotation: 4/4 e4 f g a    b4 c d e               d4 e f g   ', makeNotation=False)
>>> #                                       insertion               deletion
>>> s1.makeMeasures(inPlace=True)
>>> s2.makeMeasures(inPlace=True)
>>> mergedStream = variant.mergeVariants(s1, s2, 'london')
>>> for v in mergedStream.getElementsByClass(variant.Variant):
...     returnElement = variant._getNextElements(mergedStream, v)
...     print(returnElement)
<music21.stream.Measure 1 offset=0.0>
<music21.stream.Measure 3 offset=8.0>

This also works on streams with variants that contain notes and rests rather than measures.

>>> s = converter.parse('tinyNotation: 4/4                     e4 b b b   f4 f f f   g4 a a a       ', makeNotation=False)
>>> v1Stream = converter.parse('tinyNotation: 4/4   a4 a a a                                       ', makeNotation=False)
>>> #                                               initial insertion
>>> v1 = variant.Variant(v1Stream.notes)
>>> v1.replacementDuration = 0.0
>>> v1.groups = ['london']
>>> s.insert(0.0, v1)

>>> v2 = variant.Variant()
>>> v2.replacementDuration = 4.0
>>> v2.groups = ['london']
>>> s.insert(4.0, v2)
>>> for v in s[variant.Variant]:
...     returnElement = variant._getNextElements(s, v)
...     print(returnElement)
<music21.note.Note E>
<music21.note.Note G>
r   r   Noter   TF)	offsetEndr   r   r   r   )r   r   typer   r   r  r   GeneralNoter   r   rg   r   )
r   rr  numberOfElementsr   r   vClassvariantOffsetpotentialTargetsreturnElementr   s
             r   rn  rn  0	  sj   P ))!,J\!a**+FGMMOPfd..//%%F&99:UV\\^_fd..//%%F \!))!,00<=MMEICHBF=CH 1 F )..0   33))!,001T<=MMEICHBF=CH 1 F )..0 r   c                   UR                  U 5      nUR                  nSnUS:X  a  UR                  / SQ5      nOUR                  / SQ5      nU(       d  [        S5      e[	        US   5      n[        U[        R                  5      (       a  [        R                  nUR                  U 5      nU R                  SUSSSS	9R                  U5      nUR                  5       nU$ )
a  
This is a helper function for makeAllVariantsReplacements() which returns
the previous element in s
of the type of elements found in the variant v so that it can be added to v.


>>> #                                                   *                       *
>>> s1 = converter.parse('tinyNotation: 4/4 a4 b c d                b4 c d e    f4 g a b    ')
>>> s2 = converter.parse('tinyNotation: 4/4 a4 b c d    e4 f g a    b4 c d e                ')
>>> #                                                   insertion               deletion
>>> s1.makeMeasures(inPlace=True)
>>> s2.makeMeasures(inPlace=True)
>>> mergedStream = variant.mergeVariants(s1, s2, 'london')
>>> for v in mergedStream[variant.Variant]:
...     returnElement = variant._getPreviousElement(mergedStream, v)
...     print(returnElement)
<music21.stream.Measure 1 offset=0.0>
<music21.stream.Measure 2 offset=4.0>

This also works on streams with variants that contain notes and rests rather than measures.

>>> s = converter.parse('tinyNotation: 4/4         b4 b b a            e4 b b b      g4 e e e       ', makeNotation=False)
>>> v1Stream = converter.parse('tinyNotation: 4/4           f4 f f f                                ', makeNotation=False)
>>> #                                                       insertion                final deletion
>>> v1 = variant.Variant(v1Stream.notes)
>>> v1.replacementDuration = 0.0
>>> v1.groups = ['london']
>>> s.insert(4.0, v1)

>>> v2 = variant.Variant()
>>> v2.replacementDuration = 4.0
>>> v2.groups = ['london']
>>> s.insert(8.0, v2)
>>> for v in s[variant.Variant]:
...     returnElement = variant._getPreviousElement(s, v)
...     print(returnElement)
<music21.note.Note A>
<music21.note.Note B>
Nr   r|  z4Cannot find any Measures, Notes, or Rests in variantr   rf   FT)r~  r   r   r   )r   r   r   r   r  r  r   r  r   r   last)	r   rr  r   r   foundStreamr  r  r  r  s	            r   rq  rq  ~	  s    T ))!,JK\!**+FG&99:UVUVV+a.!F&$**++!! %%a(M,,  -     %))+Mr   c           
        SSK Jn  U R                  UR                  5      nU GHb  nU R	                  U5      nUR
                  U-   nU R                  UUSSSUR                  /S9nU GH  nUR
                  nU R	                  U5      U:X  a  M'  U R	                  U5      U-
  n	[        R                  " 5       n
XR                  l
        SU
R                  l        UR                   H<  nUR                  UR                  5      nUR                  R                  XU	-   5        M>     UR!                  5         UR#                  SU
5        Xl        U R%                  U5        U R#                  XG5        UR'                  U5        GM     GMe     g)zJ
Unknown and undocumented.  Used only in lily/translate -- for musicdiff.
r   r   FT)offsetStartr~  r   r   r   r   rf   N)music21r   r   r   elementOffsetr   r   r   r   rz   r{   r   r   r&   r   coreSetElementOffsetcoreElementsChangedr   r   r)   )r   r   variantsToBeDonerr  r   	endOffsetconflictingVariantscVrz  shiftOffsetr   r   ry  s                r   makeVariantBlocksr  	  sS     ++GOO<ooa())K7	33>GGLEJDH?F>O 4 Q &B%'%;%;"r"k1oob1K?IIK+6

(,0)**B " 2 22:: >IJJ33BK8OP % &&(		#q!)?&) ''+# & r   c                  D    \ rS rSrS rS rS rS rS rS r	S r
S	 rS
rg)Testi	  c                2    SSK Jn  U" U [        5       5        g )Nr   )testCopyAll)music21.test.commonTestr  globals)r*   r  s     r   testCopyAndDeepcopyTest.testCopyAndDeepcopy	  s    7D')$r   c                j    SnU H  nU[        U5      S-   -  nM     US[        U5      S-
   nUS-  nU$ )N[z, r   r   ])r:   rM   )r*   listInoutps       r   pitchOutTest.pitchOut	  sE    A3q6D= C !CHqL!s

r   c                   [        5       nUR                  [        R                  " SSS95        UR                  [        R                  " SSS95        U R	                  UR
                  S5        U R	                  UR                  S5        SUl        U R	                  UR
                  S5        U R	                  UR                  S5        g )NG3       @r{   f3r   Tg      @)r   r)   r   r}  assertEqualrj   rg   r$   )r*   os     r   
testBasicATest.testBasicA	  s    I	4s34	4s34!,*#.,r   c                ~   [        5       nUR                  [        R                  " SSS95        UR                  [        R                  " SSS95        U R	                  UR
                  S5        U R	                  UR                  S5        U R	                  [        UR                  5      S5        U R                  UR                  S5      5        UR                  S5        U R	                  UR
                  S5        U R	                  UR                  S5        U R	                  [        UR                  5      S5        g	)
zI
Testing relaying attributes requests to private Stream with __getattr__
r  r  r  r  rf   r   r}  r   N)r   r)   r   r}  r  rj   rg   rM   r  
assertTruehasElementOfClassr   )r*   rr  s     r   
testBasicBTest.testBasicB
  s     I	4s34	4s34#.,QWWq)++F34	a#.,QWWq)r   c                    [        5       nUR                  R                  S5        [        5       nUR                  R                  S5        U R                  SUR                  5        g)z(
Variant groups are used to distinguish
zalt-azalt-bN)r   r(   r)   assertIn)r*   v1s     r   testVariantGroupATest.testVariantGroupA
  sH     Y
		!Y
		!gryy)r   c                @   [         R                  " 5       n[        5       nUR                  U5        U R	                  SUR
                  5        U R                  UR                  [        5      5        U R                  UR                  [         R                  5      5        g )Nr   )	r   r   r   r)   r  r   assertFalser  r  )r*   m1r  s      r   testVariantClassATest.testVariantClassA%
  sf    ^^Y
		"i,--g67,,V^^<=r   c                r   SSK Jn  [        R                  " 5       nUR	                  [
        R                  " S5      S5        [
        R                  " S5      n[
        R                  " S5      nUR                  5       nUR                  SU5        UR                  SU5        [        R                  " U5      nU R                  US   US   5        U R                  US   US   5        U R                  US   U5        U R                  US   U5        UR                  SU5        U R                  U R                  UR                  5      S	5        UR!                  S
S9nU R                  U R                  UR                  5      S5        [        R                  " U5      nU R                  [#        UR%                  UR                  5      5      S5        U R                  U R                  UR                  5      S	5        UR!                  SS9  U R                  U R                  UR                  5      S5        g )Nr   r  G4   F#4A-4r      z [G4, G4, G4, G4, G4, G4, G4, G4]Fr   &[G4, G4, G4, G4, G4, F#4, A-4, G4, G4]T)r  r   r   r   repeatAppendr   r}  r   r   r1  r2  assertIsNotassertIsr  r  rA   activateVariantsrM   r   )	r*   r   r   vn1vn2r  v1CopysvsCopys	            r   testDeepCopyVariantATest.testDeepCopyVariantA/
  s   #MMO	tyy*iiii__
		!S
		!Sr"BqE*BqE*beS!C( 	
Bqyy1.	0.rzz24	6 a U55gooFGKu}}5.	0t,u}}54	6r   c                   SSK Jn  [        R                  " 5       nUR	                  [
        R                  " S5      S5        [
        R                  " S5      n[
        R                  " S5      nUR                  5       nUR                  SU5        UR                  SU5        UR                  SU5        [        R                  " U5      nUR                  SS	9  U R                  U R                  UR                  5      S
5        UR                  S   R!                  SSS	9  U R                  U R                  UR                  5      S5        UR                  SS	9  U R                  U R                  UR                  5      S
5        g )Nr   r  r  r  r  r  r  Tr   r     z&[G4, G4, G4, G4, G4, F#5, A-4, G4, G4])r  r   r   r   r  r   r}  r   r   r1  r2  r  r  r  rA   r  	transpose)r*   r   r   r  r  r  r  s          r   testDeepCopyVariantBTest.testDeepCopyVariantBR
  s(   #MMO	tyy*iiii__
		!S
		!S	B a t,u}}54	6 	A  T 2u}}54	6 	
4(qyy14	6r   r   N)r   r   r   r   r  r  r  r  r  r  r  r  r   r   r   r   r  r  	  s+    %-*(	*>!6F6r   r  c                      \ rS rSrSrS rSrg)TestExternaliq
  Tc                    SSK Jn  UR                  S5      nUR                  S5      n[        X#5      nU R                  (       a  UR	                  S5        g g )Nr   )corpusztrecento/PMFC_06-Jacopo-03aztrecento/PMFC_06-Jacopo-03bzmusicxml.png)r  r  parser   ro   )r*   r  j1j2jMergeds        r   testMergeJacopoVariants$TestExternal.testMergeJacopoVariantst
  sE    "\\78\\78$R,99LL( r   r   N)r   r   r   r   ro   r  r   r   r   r   r  r  q
  s    D)r   r  __main__r  )FFF)NNN)r   zstream.Streamr   zint | floatr  zstream.Stream | Variant)Fr<  r<  r0   )NFF)r   )4r   
__future__r   collections.abcr   r1  r  typingtunittestr  r   r   r   r   r	   r
   r   r   r   music21.stream.enumsr   Environmentr   Music21Exceptionr   r2   r   r   r   r   r   r  r   r  r6  r:  r  rA  r   r   rX  rj  rh  rn  rq  r  TestCaser  r  r   mainTestr   r   r   <module>r     s  " # $               6&&y1	|44 	{'d   {'@z=e z=zF FRASX AH BG |@ UZV~ k'k'k' $k'^ +0 dN TY HV4 FH@F(>< 59% k\%T .2(-(-CL}^@K\DN!,JD68 D6N	)8$$ 	) zT r   