
    rh                       S r SSKJr  SSKJrJr  SSKrSSKrSSKr	SSKJ
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Jr  SSKJr  \	R2                  (       a  SSKJr  SSKJr  \R<                  " S5      r\ \ \RB                  \RB                  4   \ \RB                  \RB                  4   4   r" " S S\RF                  5      r$ " S S\RJ                  5      r& " S S\RJ                  \\&   5      r' " S S\RP                  5      r)\&\'4r*\+S:X  a  SSKr\RX                  " \)5        gg)zU
Object for dealing with vertical simultaneities in a fast way w/o Chord's overhead.
    )annotations)IterableSequenceN)overload)chord)common)environment)exceptions21)note)prebase)tie)OffsetQL
OffsetQLIn)spans)
OffsetTreeVoiceLeadingQuartetztree.verticalityc                      \ rS rSrSrg)VerticalityException1    N__name__
__module____qualname____firstlineno____static_attributes__r       R/home/james-whalen/.local/lib/python3.13/site-packages/music21/tree/verticality.pyr   r   1       r   r   c                     \ rS rSr% SrSrSSSSSS	S.rS
\S'        S'       S(S jjrS r	\
S 5       r\
S 5       rS r\
S 5       r\
S)S j5       r\
S 5       r\
S 5       r\
S 5       r\
S 5       r\
S 5       r\
S*S j5       r S+SSSSSSS.   S,S jjjr\SSSSS.     S-S  jj5       r\SSSSSS!.     S.S" jj5       rSSSSSS!.     S/S# jjrSSS$.     S0S% jjrS&rg)1Verticality5   aQ	  
A collection of information about elements that are sounding at a given
offset or just finished at that offset or are continuing from before, etc..


Create a timespan-stream from a score:

>>> score = corpus.parse('bwv66.6')
>>> scoreTree = tree.fromStream.asTimespans(score, flatten=True,
...        classList=(note.Note, chord.Chord))


Find the verticality at offset 6.5, or beat 2.5 of measure 2 (there's a one
beat pickup)

>>> verticality = scoreTree.getVerticalityAt(6.5)
>>> verticality
<music21.tree.verticality.Verticality 6.5 {E3 D4 G#4 B4}>


The representation of a verticality gives the pitches from lowest to
highest (in sounding notes).


A verticality knows its offset, but because elements might end at
different times, it doesn't know its endTime

>>> verticality.offset
6.5
>>> verticality.endTime
Traceback (most recent call last):
AttributeError: 'Verticality' object has no attribute 'endTime'


However, we can find when the next verticality starts by looking at the nextVerticality

>>> nv = verticality.nextVerticality
>>> nv
<music21.tree.verticality.Verticality 7.0 {A2 C#4 E4 A4}>
>>> nv.offset
7.0

Or more simply:

>>> verticality.nextStartOffset
7.0

(There is also a previousVerticality, but not a previousStartOffset)

What we just demonstrated is actually very powerful: a Verticality keeps a
record of exactly where it is in the timespanTree -- scores can be
recreated with this information.

Getting back to the task at hand, we can find all the PitchedTimespans (and
from there the elements) that start at exactly 6.5.  There's one, it's a
passing tone D in the tenor.  It lasts from offset 6.5 to offset 7.0,
with respect to the beginning of the score, not to the beginning of the
measure.  That is to say, it's an eighth note.

>>> verticality.startTimespans
(<PitchedTimespan (6.5 to 7.0) <music21.note.Note D>>,)

And we can get all the PitchedTimespans that were already sounding at the
moment (that is to say, the non-passing tones):

>>> verticality.overlapTimespans
(<PitchedTimespan (6.0 to 7.0) <music21.note.Note B>>,
 <PitchedTimespan (6.0 to 7.0) <music21.note.Note G#>>,
 <PitchedTimespan (6.0 to 7.0) <music21.note.Note E>>)

And we can get all the things that stop right at this moment.  It's the E
in the tenor preceding the passing tone D:

>>> verticality.stopTimespans
(<PitchedTimespan (6.0 to 6.5) <music21.note.Note E>>,)
)
offsetTreetimespanTreeoverlapTimespansstartTimespansoffsetstopTimespanszB
            Returns the tree initially set else None
            z\
            Returns the tree initially set if it was a TimespanTree, else None
            a%  
            Gets timespans overlapping the start offset of a verticality.

            >>> score = corpus.parse('bwv66.6')
            >>> scoreTree = tree.fromStream.asTimespans(score, flatten=True,
            ...            classList=(note.Note, chord.Chord))
            >>> verticality = scoreTree.getVerticalityAt(0.5)
            >>> verticality
            <music21.tree.verticality.Verticality 0.5 {G#3 B3 E4 B4}>
            >>> verticality.overlapTimespans
            (<PitchedTimespan (0.0 to 1.0) <music21.note.Note E>>,)
            a%  
            Gets the timespans starting at a verticality's start offset.

            >>> score = corpus.parse('bwv66.6')
            >>> scoreTree = tree.fromStream.asTimespans(score, flatten=True,
            ...            classList=(note.Note, chord.Chord))
            >>> verticality = scoreTree.getVerticalityAt(1.0)
            >>> verticality
            <music21.tree.verticality.Verticality 1.0 {F#3 C#4 F#4 A4}>
            >>> for timespan in verticality.startTimespans:
            ...     timespan
            ...
            <PitchedTimespan (1.0 to 2.0) <music21.note.Note A>>
            <PitchedTimespan (1.0 to 2.0) <music21.note.Note F#>>
            <PitchedTimespan (1.0 to 2.0) <music21.note.Note C#>>
            <PitchedTimespan (1.0 to 2.0) <music21.note.Note F#>>
            a  
            Gets the start offset of a verticality.

            >>> score = corpus.parse('bwv66.6')
            >>> scoreTree = tree.fromStream.asTimespans(score, flatten=True,
            ...            classList=(note.Note, chord.Chord))
            >>> verticality = scoreTree.getVerticalityAt(1.0)
            >>> verticality
            <music21.tree.verticality.Verticality 1.0 {F#3 C#4 F#4 A4}>
            >>> verticality.offset
            1.0
            a  
            Gets the timespans stopping at a verticality's start offset.

            >>> score = corpus.parse('bwv66.6')
            >>> scoreTree = tree.fromStream.asTimespans(score, flatten=True,
            ...                classList=(note.Note, chord.Chord))
            >>> verticality = scoreTree.getVerticalityAt(1.0)
            >>> verticality
            <music21.tree.verticality.Verticality 1.0 {F#3 C#4 F#4 A4}>

            Note that none of the elements in the stopTimespans are listed in
            the repr for the Verticality

            >>> for timespan in verticality.stopTimespans:
            ...     timespan
            ...
            <PitchedTimespan (0.0 to 1.0) <music21.note.Note E>>
            <PitchedTimespan (0.5 to 1.0) <music21.note.Note B>>
            <PitchedTimespan (0.5 to 1.0) <music21.note.Note B>>
            <PitchedTimespan (0.5 to 1.0) <music21.note.Note G#>>
            zdict[str, str]	_DOC_ATTRNc                ^   SSK Jn  XPl        S U l        [	        XV5      (       a  XPl        Xl        [	        U[        5      (       d  [        SU< 35      e[	        U[        5      (       d  [        SU< 35      e[	        U[        5      (       d  [        SU< 35      eX0l        X@l	        X l
        g )Nr   )TimespanTreez8startTimespans must be a tuple of ElementTimespans, not z7stopTimespans must be a tuple of ElementTimespans, not z:overlapTimespans must be a tuple of ElementTimespans, not )music21.tree.timespanTreer,   r$   r%   
isinstancer(   tupler   r'   r)   r&   )selfr(   r&   r'   r)   r%   r,   s          r   __init__Verticality.__init__   s     	;-915l11 , &.%00&J>J\]_ _-//&I-IZ[] ]*E22&LM]L`ac c BP@MCSr   c                    [        U R                  5      nSSR                  S U 5       5      -   S-   nU R                   SU 3$ )N{ c              3  8   #    U  H  oR                   v   M     g 7fN)nameWithOctave.0xs     r   	<genexpr>,Verticality._reprInternal.<locals>.<genexpr>   s     &OA'7'7s   })sortedpitchSetjoinr(   )r0   sortedPitchesenclosedNamess      r   _reprInternalVerticality._reprInternal   sD    t}}-chh&O&OOORUU++a//r   c                    SnSnU R                    HK  n[        US5      (       d  M  UR                  nU(       d  M+  [        U5      S   nUc  UnUnXQ::  d  MG  UnUnMM     U$ )a  
Gets the bass timespan in this verticality.

>>> score = corpus.parse('bwv66.6')
>>> scoreTree = tree.fromStream.asTimespans(score, flatten=True,
...            classList=(note.Note, chord.Chord))
>>> verticality = scoreTree.getVerticalityAt(1.0)
>>> verticality
<music21.tree.verticality.Verticality 1.0 {F#3 C#4 F#4 A4}>

>>> verticality.bassTimespan
<PitchedTimespan (1.0 to 2.0) <music21.note.Note F#>>
Npitchesr   )startAndOverlapTimespanshasattrrG   r?   )r0   overallLowestPitchlowestTimespants	tsPitcheslowestPitchs         r   bassTimespanVerticality.bassTimespan   sw     "//B2y))

I +A.K!)%0"!#0%0"!# 0  r   c                n     U R                   S   nUR                  R                  $ ! [         a     gf = f)a1  
Gets the beat strength of a verticality.

>>> score = corpus.parse('bwv66.6')
>>> scoreTree = tree.fromStream.asTimespans(score, flatten=True,
...            classList=(note.Note, chord.Chord))
>>> verticality = scoreTree.getVerticalityAt(1.0)
>>> verticality.beatStrength
1.0


Note that it will return None if there are no startTimespans at this point:

>>> verticality = scoreTree.getVerticalityAt(1.25)
>>> verticality
<music21.tree.verticality.Verticality 1.25 {F#3 C#4 F#4 A4}>
>>> verticality.startTimespans
()
>>> verticality.beatStrength is None
True
r   N)r'   
IndexErrorelementbeatStrength)r0   thisTimespans     r   rT   Verticality.beatStrength"  s?    .	..q1L ##000  		s   ' 
44c                X    [         R                  " [        U R                  5      5      nU$ )a  
Creates a chord.Chord object of default length (1.0 or
the duration of some note object) from the verticality.

Does nothing about ties, etc. -- it's a very dumb chord, but useful
for querying consonance, etc.  See makeElement() for the smart version.

It may be a zero- or one-pitch chord.

>>> score = corpus.parse('bwv66.6')
>>> scoreTree = score.asTimespans()
>>> verticality = scoreTree.getVerticalityAt(4.0)
>>> verticality.toChord()
<music21.chord.Chord G#3 B3 E4 E5>
)r   Chordr?   r@   )r0   cs     r   toChordVerticality.toChord?  s       KKt}}-.r   c                4    U R                   S   R                  $ )a,  
Gets the measure number of the verticality's starting elements.

>>> score = corpus.parse('bwv66.6')
>>> scoreTree = tree.fromStream.asTimespans(score, flatten=True,
...            classList=(note.Note, chord.Chord))
>>> verticality = scoreTree.getVerticalityAt(7.0)
>>> verticality.measureNumber
2
r   )r'   measureNumberr0   s    r   r]   Verticality.measureNumberR  s     ""1%333r   c                \    U R                   nUc  gUR                  U R                  5      nU$ )an  
Gets the next start-offset in the verticality's offset-tree.

>>> score = corpus.parse('bwv66.6')
>>> scoreTree = tree.fromStream.asTimespans(score, flatten=True,
...            classList=(note.Note, chord.Chord))
>>> verticality = scoreTree.getVerticalityAt(1.0)
>>> verticality.nextStartOffset
2.0

If a verticality has no tree attached, then it will return None
N)r$   getPositionAfterr(   r0   treer(   s      r   nextStartOffsetVerticality.nextStartOffset`  s.     <&&t{{3r   c                    U R                   nUc  gUR                  U R                  5      nUc  gUR                  U5      $ )a  
Gets the next verticality after a verticality.

>>> score = corpus.parse('bwv66.6')
>>> scoreTree = tree.fromStream.asTimespans(score, flatten=True,
...            classList=(note.Note, chord.Chord))
>>> verticality = scoreTree.getVerticalityAt(1.0)
>>> print(verticality)
<music21.tree.verticality.Verticality 1.0 {F#3 C#4 F#4 A4}>

>>> nextVerticality = verticality.nextVerticality
>>> print(nextVerticality)
<music21.tree.verticality.Verticality 2.0 {G#3 B3 E4 B4}>

Verticality objects created by an offset-tree hold a reference back to
that offset-tree. This means that they determine their next or previous
verticality dynamically based on the state of the offset-tree only when
asked. Because of this, it is safe to mutate the offset-tree by
inserting or removing timespans while iterating over it.

>>> scoreTree.removeTimespanList(nextVerticality.startTimespans)
>>> verticality.nextVerticality
<music21.tree.verticality.Verticality 3.0 {A3 E4 C#5}>
N)r$   ra   r(   getVerticalityAtrb   s      r   nextVerticalityVerticality.nextVerticalityt  sB    4 <&&t{{3>$$V,,r   c                
   [        5       n[        5       nU R                   H^  n[        US5      (       d  M  UR                   H8  nUR                  nXQ;   a  M  UR                  U5        UR                  U5        M:     M`     U$ )a  
Gets the pitch set of all elements in a verticality.

>>> score = corpus.parse('bwv66.6')
>>> scoreTree = tree.fromStream.asTimespans(score, flatten=True,
...            classList=(note.Note, chord.Chord))
>>> verticality = scoreTree.getVerticalityAt(1.0)
>>> for pitch in sorted(verticality.pitchSet):
...     pitch
...
<music21.pitch.Pitch F#3>
<music21.pitch.Pitch C#4>
<music21.pitch.Pitch F#4>
<music21.pitch.Pitch A4>
rG   )setrH   rI   rG   r8   add)r0   pitchNameSetr@   timespanppNames         r   r@   Verticality.pitchSet  sv    " u555H8Y//%%(((  'Q & 6 r   c                    [        5       n[        5       nU R                   H8  nUR                  nXB;   a  M  UR                  U5        UR                  U5        M:     U$ )a  
Gets a set of all pitches in a verticality with distinct pitchClasses

>>> n1 = note.Note('C4')
>>> n2 = note.Note('B#5')
>>> s = stream.Stream()
>>> s.insert(4.0, n1)
>>> s.insert(4.0, n2)
>>> scoreTree = s.asTimespans()
>>> verticality = scoreTree.getVerticalityAt(4.0)
>>> pitchSet = verticality.pitchSet
>>> list(sorted(pitchSet))
[<music21.pitch.Pitch C4>, <music21.pitch.Pitch B#5>]

PitchClassSet will return only one pitch.  Which of these
is returned is arbitrary.

>>> pitchClassSet = verticality.pitchClassSet
>>> #_DOCS_SHOW list(sorted(pitchClassSet))
>>> print('[<music21.pitch.Pitch B#5>]')  #_DOCS_HIDE
[<music21.pitch.Pitch B#5>]
)rk   r@   
pitchClassrl   )r0   outPitchSetpitchClassSetcurrentPitchrs   s        r   ru   Verticality.pitchClassSet  sV    2 e MML%00J*j)OOL) * r   c                    U R                   nUc  gUR                  U R                  5      nUc  gUR                  U5      $ )a	  
Gets the previous verticality before a verticality.

>>> score = corpus.parse('bwv66.6')
>>> scoreTree = tree.fromStream.asTimespans(score, flatten=True,
...            classList=(note.Note, chord.Chord))
>>> verticality = scoreTree.getVerticalityAt(1.0)
>>> print(verticality)
<music21.tree.verticality.Verticality 1.0 {F#3 C#4 F#4 A4}>

>>> previousVerticality = verticality.previousVerticality
>>> print(previousVerticality)
<music21.tree.verticality.Verticality 0.5 {G#3 B3 E4 B4}>

Continue it:

>>> v = scoreTree.getVerticalityAt(1.0)
>>> while v is not None:
...     print(v)
...     v = v.previousVerticality
<music21.tree.verticality.Verticality 1.0 {F#3 C#4 F#4 A4}>
<music21.tree.verticality.Verticality 0.5 {G#3 B3 E4 B4}>
<music21.tree.verticality.Verticality 0.0 {A3 E4 C#5}>

Verticality objects created by an offset-tree hold a reference back to
that offset-tree. This means that they determine their next or previous
verticality dynamically based on the state of the offset-tree only when
asked. Because of this, it is safe to mutate the offset-tree by
inserting or removing timespans while iterating over it.

>>> scoreTree.removeTimespanList(previousVerticality.startTimespans)
>>> verticality.previousVerticality
<music21.tree.verticality.Verticality 0.0 {A3 E4 C#5}>
N)r$   getPositionBeforer(   rg   rb   s      r   previousVerticalityVerticality.previousVerticality  sC    H <''4>$$V,,r   c                    U R                   c  [        U R                  5      $ [        U R                  SS U R                   SS -   5      $ )a  
Return a tuple adding the start and overlap timespans into one.

>>> n1 = note.Note('C4')
>>> n2 = note.Note('D4')
>>> s = stream.Stream()
>>> s.insert(4.0, n1)
>>> s.insert(4.5, n2)
>>> scoreTree = s.asTimespans()
>>> verticality = scoreTree.getVerticalityAt(4.5)
>>> verticality.startTimespans
(<PitchedTimespan (4.5 to 5.5) <music21.note.Note D>>,)

>>> verticality.overlapTimespans
(<PitchedTimespan (4.0 to 5.0) <music21.note.Note C>>,)

>>> verticality.startAndOverlapTimespans
(<PitchedTimespan (4.5 to 5.5) <music21.note.Note D>>,
 <PitchedTimespan (4.0 to 5.0) <music21.note.Note C>>)

>>> verticality = scoreTree.getVerticalityAt(4.0)
>>> verticality.startAndOverlapTimespans
(<PitchedTimespan (4.0 to 5.0) <music21.note.Note C>>,)
N)r&   r/   r'   r^   s    r   rH   $Verticality.startAndOverlapTimespans  sG    4   (,,--T((+d.C.CA.FFGGr   c                    U R                   nUc$  U R                  c  gU R                  R                  n[        R                  " XR
                  -
  5      $ )z
Returns a float or Fraction of the quarterLength to the next
event (usually the next Verticality, but also to the end of the piece).

Returns None if there is no next event, such as when the verticality
is divorced from its tree.
N)rd   r%   endTimer   opFracr(   )r0   
nextOffsets     r   timeToNextEventVerticality.timeToNextEvent'  sK     ))
  (**22J}}Z++566r   TFsingle)addTiesaddPartIdAsGroupremoveRedundantPitchesgatherArticulationsgatherExpressionscopyPitchesc          	       ^ ^^^^^^^^^^^ Tc  T R                   nUc  SmOUmO[        R                  " T5      mT R                  (       d(  [        R
                  " 5       n	TU	R                  l        U	$ [        R                  " 5       n
TU
R                  l        U
R                  m[        5       m0 mSS1mSmSUUUUU U4S jjmSUUUUUUUU4S jjnT R                   GH  n[        U[        R                  5      (       d  M%  UR                  n[        U[        R                   5      (       Ga  SnU H&  n[        U[        R"                  5      (       d  M$  Un  O   Uc  M  UR$                  (       d  UR&                  (       an  UR(                  n[*        R,                  " U5      nU=R$                  UR$                  -  sl        U=R&                  UR&                  -  sl        T(       d  UUl        U" X5        [/        U5      S:  aA  [1        U5      SS  H,  n[        U[        R"                  5      (       d  M$  U" X5        M.     GMl  GMo  [        U[        R"                  5      (       d  GM  U" X5        GM     [        5       n[        5       n[3        TR5                  5       S	 S
9 GH  nU
R7                  U5        U(       a  UR$                   H  nUR8                  S:X  a)  UR:                  b  UR:                  R<                  S:w  a  M<  UR8                  S:X  a)  UR:                  b  UR:                  R<                  S:w  a  Mu  US:X  a  [=        U5      U;   a  M  U
R$                  R?                  U5        UR7                  [=        U5      5        M     U(       d  M  UR&                   H  nUR8                  S:X  a)  UR:                  b  UR:                  R<                  S:w  a  M<  UR8                  S:X  a)  UR:                  b  UR:                  R<                  S:w  a  Mu  US:X  a  [=        U5      U;   a  M  U
R&                  R?                  U5        UR7                  [=        U5      5        M     GM     U
$ )ah  
Makes a Chord or Rest from this verticality and quarterLength.

>>> score = tree.makeExampleScore()
>>> scoreTree = tree.fromStream.asTimespans(score, flatten=True,
...            classList=(note.Note, chord.Chord))
>>> verticality = scoreTree.getVerticalityAt(4.0)
>>> verticality
<music21.tree.verticality.Verticality 4.0 {E#3 G3}>
>>> verticality.startTimespans
(<PitchedTimespan (4.0 to 5.0) <music21.note.Note G>>,
 <PitchedTimespan (4.0 to 6.0) <music21.note.Note E#>>)

>>> el = verticality.makeElement(2.0)
>>> el
<music21.chord.Chord E#3 G3>
>>> el.duration.quarterLength
2.0
>>> el.duration.type
'half'

If there is nothing there, then a Rest is created

>>> verticality = scoreTree.getVerticalityAt(400.0)
>>> verticality
<music21.tree.verticality.Verticality 400.0 {}>
>>> el = verticality.makeElement(1/3)
>>> el
<music21.note.Rest 1/3ql>
>>> el.duration.fullName
'Eighth Triplet (1/3 QL)'


>>> n1 = note.Note('C4')
>>> n2 = note.Note('C4')
>>> s = stream.Score()
>>> s.insert(0, n1)
>>> s.insert(0.5, n2)
>>> scoreTree = s.asTimespans()
>>> verticality = scoreTree.getVerticalityAt(0.5)
>>> c = verticality.makeElement(0.5)
>>> c
<music21.chord.Chord C4>

>>> c = verticality.makeElement(0.5, removeRedundantPitches=False)
>>> c
<music21.chord.Chord C4 C4>

Generally the pitches of the new element are not connected to the original pitch:

>>> c[0].pitch.name = 'E'
>>> c[1].pitch.name = 'F'
>>> (n1.name, n2.name)
('C', 'C')

But if `copyPitches` is False then the original pitch will be used:

>>> n1.name = 'D'
>>> n2.name = 'E'
>>> c = verticality.makeElement(0.5, removeRedundantPitches=False, copyPitches=False)
>>> c
<music21.chord.Chord D4 E4>

>>> c[0].pitch.name = 'F'
>>> c[1].pitch.name = 'G'
>>> (n1.name, n2.name)
('F', 'G')


gatherArticulations and gatherExpressions can be True, False, or (default) 'single'.

* If False, no articulations (or expressions) are transferred to the chord.
* If True, all articulations are transferred to the chord.
* If 'single', then no more than one articulation of each class
  (chosen from the lowest note) will be added.
  This way, the chord does not get 4 fermatas, etc.

>>> n1 = note.Note('C4')
>>> n2 = note.Note('D4')
>>> s = stream.Stream()
>>> s.insert(0, n1)
>>> s.insert(0.5, n2)

>>> class AllAttachArticulation(articulations.Articulation):
...     def __init__(self):
...         super().__init__()
...         self.tieAttach = 'all'

>>> class OtherAllAttachArticulation(articulations.Articulation):
...     def __init__(self):
...         super().__init__()
...         self.tieAttach = 'all'


>>> n1.articulations.append(articulations.Accent())
>>> n1.articulations.append(AllAttachArticulation())
>>> n1.expressions.append(expressions.Fermata())

>>> n2.articulations.append(articulations.Staccato())
>>> n2.articulations.append(AllAttachArticulation())
>>> n2.articulations.append(OtherAllAttachArticulation())
>>> n2.expressions.append(expressions.Fermata())

>>> scoreTree = s.asTimespans()

>>> verticality = scoreTree.getVerticalityAt(0.0)
>>> c = verticality.makeElement(1.0)
>>> c.expressions
[<music21.expressions.Fermata>]
>>> c.articulations
[<music21.articulations.Accent>, <...AllAttachArticulation>]

>>> verticality = scoreTree.getVerticalityAt(0.5)


Here there will be no expressions, because there is no note ending
at 0.75 and Fermatas attach to the last note:

>>> c = verticality.makeElement(0.25)
>>> c.expressions
[]

>>> c = verticality.makeElement(0.5)
>>> c.expressions
[<music21.expressions.Fermata>]

Only two articulations, since accent attaches to beginning
and staccato attaches to last
and we are beginning after the start of the first note (with an accent)
and cutting right through the second note (with a staccato)

>>> c.articulations
[<...AllAttachArticulation>,
 <...OtherAllAttachArticulation>]

>>> c = verticality.makeElement(0.5, gatherArticulations=True)
>>> c.articulations
[<...AllAttachArticulation>,
 <...AllAttachArticulation>,
 <...OtherAllAttachArticulation>]

>>> c = verticality.makeElement(0.5, gatherArticulations=False)
>>> c.articulations
[]

>>> verticality = scoreTree.getVerticalityAt(1.0)
>>> c = verticality.makeElement(0.5)
>>> c.expressions
[<music21.expressions.Fermata>]
>>> c.articulations
[<music21.articulations.Staccato>,
 <...AllAttachArticulation>,
 <...OtherAllAttachArticulation>]

* New in v6.3: copyPitches option

OMIT_FROM_DOCS

Test that copyPitches works with expressions:

>>> c = verticality.makeElement(0.5, copyPitches=False)
>>> c
<music21.chord.Chord D4>
>>> c.pitches[0].accidental = pitch.Accidental('sharp')
>>> n2
<music21.note.Note D#>

* Changed in v7.3: if quarterLength is not given, the duration
  to the next quarterLength is used.
Ng      ?startstopr   c                  > [         R                  " U5      nTUl        T(       d  UR                  Ul        UR                  S:w  a  SUl        T(       d  U$ [
        R                  " T
R                  U R                  -
  5      n[        R                  (       a  T	c   e[
        R                  " U R                  T
R                  T	-   -
  5      n[        R                  (       a  Uc   eUS:X  a	  US::  a  SnO)US:  a  US:  a  SnOSnOUS:  a  SnO[        SX4U T
5      eUR                  b/  UR                  R                  U1T:X  a  SUR                  l        U$ UR                  b-  UR                  R                  S:X  a  SUR                  l        U$ Uc   UR                  b  SUR                  l        U$ U(       a  [        R                  " U5      Ul        U$ )	z1
Make a copy of the note and clear some settings
noStemunspecifiedNr   continuer   r   zWhat possibility was missed?)copydeepcopydurationpitchstemDirectionr   r   r(   tTYPE_CHECKINGr   r   r   type	placementTie)rL   nnNewoffsetDifferenceendTimeDifferenceaddTier   r   durquarterLengthr0   startStopSets         r   newNote(Verticality.makeElement.<locals>.newNote
  s    ==#DDMWW
!!X-%2"%}}T[[299-DE$000 &bjjDKK-<W.X Y(444  1$):a)?!A%$q('F#F"Q& *+I+;PRTXZ Z xx#(?<(O * K %$((--:*E%)" K DHH$8%)"
 K 776?Kr   c                  > SSK Jn  UR                  nUR                  nSnT(       a  UR	                  UR
                  5      nUbg  [        UR                  5      nUR                  SS5      nUR                  R                  R                  U5        UR                  R                  U5        UT;  a  TR                  U5        T" X5      TU'   gT(       d  T" X5      TU[        T5      -   '   TS-  mgT(       aI  UbF  TU   R                  R                  U5        TU   R                  R                  R                  U5        T(       d  gTU   R                  nUb  UR                  S:X  a  gT" X5      n	TU   R                  U	l	        U	R                  c  gUc  U	TU'   gUR                  U	R                  R                  1T:X  a  TU   R                  n
U
b  SU
l        ggU	R                  R                  S:X  a  U	TU'   gU	R                  R                  UR                  :X  a  g[        SU	R                  U5      e)	z
Add an element only if it is not already in the chord.

If it has more tie information than the previously
added note, then remove the previously added note and add it
r   )streamNr5   _   r   zDid I miss one? )music21r   r   r8   getContextByClassPartstridreplacegroupsappendrl   r   r   r   )rL   r   r   ro   pitchKey
pitchGrouppartContextpidStr
oldNoteTiepossibleNewNoteother_tr   r   r   
notesToAdd	pitchBustr   seenPitchesr   s              r   conditionalAdd/Verticality.makeElement.<locals>.conditionalAdd<  s    ' A''HJ11&++>* 0F!'S!9JGGNN))*5HHOOJ/{*)'.r~
8$+8?
8c)n45Q	!j&<8$++22:>8$**1188D $H-11J%*//Z*G%bnO%/%9%@%@O"""*!'6
8$//?#6#6#;#;<L$X.22&#-GL ' $$))Z7'6
8$ $$))Z__<*+=?R?RT^__r   r   c                .    U R                   R                  $ r7   )r   ps)r;   s    r   <lambda>)Verticality.makeElement.<locals>.<lambda>  s    177::r   )keyfirstlastr   )rL   spans.PitchedTimespanr   	note.Notereturnr   )rL   r   r   r   r   None) r   r   r   r@   r   Restr   r   r   rX   rk   rH   r.   r   PitchedTimespanrS   	ChordBaseNotearticulationsexpressionsr   r   r   lenlistr?   valuesrl   	tieAttachr   r   r   )r0   r   r   r   r   r   r   r   event_durationrrY   r   timeSpanelfirstNoteElementsubEloriginalPitchseenArticulationsseenExpressionsr   artexpr   r   r   r   r   r   s   `````  `              @@@@@@r   makeElementVerticality.makeElement9  sg   l  !11N% # ."MM-8M}}		A'4AJJ$H KKM#0

 jje
(	/	 /	d;	` ;	`z 55Hh(=(=>>!!B"eoo..59 E!%33+0(  
 $+##r~~ %5$:$:M'+}}5E'F$$22b6F6FF2$00BNNB0&1>(.x:r7Q;!%b!"%eTYY77*8; ".  B		**x,= 6@  E%
))+1EFAEE!H"??C}}/AEE4E!%%**X_J_ }}.1553DW]I] *h649HY;Y OO**3/%))$s)4 + ! ==C}}/AEE4E!%%**X_J_ }}.1553DW]I] (H4co9U MM((-#''S	2 ) G2 r   )includeRestsincludeObliqueincludeNoMotionpartPairNumbersc                   g r7   r   r0   r   r   r   returnObjectsr   s         r   getAllVoiceLeadingQuartets&Verticality.getAllVoiceLeadingQuartets       	r   )r   r   r   r   r   c                   g r7   r   r   s         r   r   r     r   r   c                  U R                   (       d  [        S5      eSSKJn  U R	                  UUS9n[
        R                  " US5      n/ n	/ n
U R                   R                  R                  nU GH  n[        US   S   S5      (       d  M  USL aN  US   S   R                  US   S   R                  :X  a(  US   S   R                  US   S   R                  :X  a  Mp  Ubj  SnU HY  nUS   S   R                  nUS   S   R                  nXS      U:X  d  XS      U:X  d  M?  XS      U:X  d  XS      U:X  d  MW  S	n  O   U(       d  M  USL a  U	R                  U5        M  US   S   R                  nUS   S   R                  nUS   S   R                  nUS   S   R                  n[        U[        R                   5      (       d  GM_  [        U[        R                   5      (       d  GM  [        U[        R                   5      (       d  GM  [        U[        R                   5      (       d  GM  U" UUUU5      nU
R                  U5        GM     U(       a  U
$ U	$ )
a^	  
>>> c = corpus.parse('luca/gloria').measures(1, 8)
>>> tsCol = tree.fromStream.asTimespans(c, flatten=True,
...            classList=(note.Note, chord.Chord))
>>> verticality22 = tsCol.getVerticalityAt(22.0)

>>> from pprint import pprint as pp
>>> for vlq in verticality22.getAllVoiceLeadingQuartets():
...     pp(vlq)
<music21.voiceLeading.VoiceLeadingQuartet
    v1n1=G4, v1n2=C4, v2n1=E4, v2n2=F4>
<music21.voiceLeading.VoiceLeadingQuartet
    v1n1=G4, v1n2=C4, v2n1=A3, v2n2=A3>
<music21.voiceLeading.VoiceLeadingQuartet
    v1n1=E4, v1n2=F4, v2n1=A3, v2n2=A3>

>>> for vlq in verticality22.getAllVoiceLeadingQuartets(includeRests=False):
...     pp(vlq)
<music21.voiceLeading.VoiceLeadingQuartet
    v1n1=E4, v1n2=F4, v2n1=A3, v2n2=A3>
>>> for vlq in verticality22.getAllVoiceLeadingQuartets(includeOblique=False):
...     pp(vlq)
<music21.voiceLeading.VoiceLeadingQuartet
    v1n1=G4, v1n2=C4, v2n1=E4, v2n2=F4>
>>> verticality22.getAllVoiceLeadingQuartets(includeOblique=False, includeRests=False)
[]


Raw output, returns a 2-element tuple of 2-element tuples of PitchedTimespans

>>> for vlqRaw in verticality22.getAllVoiceLeadingQuartets(returnObjects=False):
...     pp(vlqRaw)
((<PitchedTimespan (19.5 to 21.0) <music21.note.Note G>>,
  <PitchedTimespan (22.0 to 22.5) <music21.note.Note C>>),
 (<PitchedTimespan (21.0 to 22.0) <music21.note.Note E>>,
  <PitchedTimespan (22.0 to 23.0) <music21.note.Note F>>))
((<PitchedTimespan (19.5 to 21.0) <music21.note.Note G>>,
  <PitchedTimespan (22.0 to 22.5) <music21.note.Note C>>),
 (<PitchedTimespan (21.5 to 22.5) <music21.note.Note A>>,
  <PitchedTimespan (21.5 to 22.5) <music21.note.Note A>>))
((<PitchedTimespan (21.0 to 22.0) <music21.note.Note E>>,
  <PitchedTimespan (22.0 to 23.0) <music21.note.Note F>>),
 (<PitchedTimespan (21.5 to 22.5) <music21.note.Note A>>,
  <PitchedTimespan (21.5 to 22.5) <music21.note.Note A>>))

>>> for vlq in verticality22.getAllVoiceLeadingQuartets(partPairNumbers=[(0, 1)]):
...     pp(vlq)
<music21.voiceLeading.VoiceLeadingQuartet
    v1n1=G4, v1n2=C4, v2n1=E4, v2n2=F4>

>>> for vlq in verticality22.getAllVoiceLeadingQuartets(partPairNumbers=[(0, 2), (1, 2)]):
...     pp(vlq)
<music21.voiceLeading.VoiceLeadingQuartet
    v1n1=G4, v1n2=C4, v2n1=A3, v2n2=A3>
<music21.voiceLeading.VoiceLeadingQuartet
    v1n1=E4, v1n2=F4, v2n1=A3, v2n2=A3>

* Changed in v8: all parameters are keyword only.
z,Cannot iterate without .timespanTree definedr   r   r   r      rG   Fr   T)r%   r   music21.voiceLeadingr   getPairedMotion	itertoolscombinationssourcepartsrI   rG   partr   rS   r.   r   r   )r0   r   r   r   r   r   r   pairedMotionListallPairedMotionfilteredListfilteredQuartetverticalityStreamPartspairedMotionisAppropriateppthisQuartetTopPartthisQuartetBottomPartn11n12n21n22vlqs                         r   r   r     s\   J   &'UVV<   %) ! 
 	 $001A1E5757!%!2!2!9!9!?!? ,L<?1-y99%' OA&..,q/!2D2L2LL(OA.66,q/!:L:T:TT* %)B)5a);)@)@&,8OA,>,C,C)/16:LL5e<@UU3qE:>PP5e<@UU(, * %%##L1"1oa(00"1oa(00"1oa(00"1oa(00 sDII..&sDII66&sDII66&sDII66-c3SAC#**3/K ,N ""r   r   c               R   U R                   (       d  / $ U R                  nU R                  nU R                  n/ nU H  n[	        U[
        R                  5      (       d  M$  U R                   R                  U5      nUb  [	        U[
        R                  5      (       d  Mc  USL a  X;  a  Mo  USL a  UR                  UR                  :X  a  M  X4n	UR                  U	5        M     USL a>  U H8  n
[	        U
[
        R                  5      (       d  M$  X4n	UR                  U	5        M:     U$ )a  
Get a list of two-element tuples that are in the same part
[TODO: or containing stream??]
and which move at this verticality.

>>> c = corpus.parse('luca/gloria').measures(1, 8)
>>> tsCol = tree.fromStream.asTimespans(c, flatten=True,
...            classList=(note.Note, chord.Chord))
>>> verticality22 = tsCol.getVerticalityAt(22.0)
>>> for pm in verticality22.getPairedMotion():
...     print(pm)
(<PitchedTimespan (19.5 to 21.0) <music21.note.Note G>>,
 <PitchedTimespan (22.0 to 22.5) <music21.note.Note C>>)
(<PitchedTimespan (21.0 to 22.0) <music21.note.Note E>>,
 <PitchedTimespan (22.0 to 23.0) <music21.note.Note F>>)
(<PitchedTimespan (21.5 to 22.5) <music21.note.Note A>>,
 <PitchedTimespan (21.5 to 22.5) <music21.note.Note A>>)

Note that the second pair contains a one-beat rest at 21.0-22.0;
so `includeRests=False` will
get rid of that:

>>> for pm in verticality22.getPairedMotion(includeRests=False):
...     print(pm)
(<PitchedTimespan (21.0 to 22.0) <music21.note.Note E>>,
 <PitchedTimespan (22.0 to 23.0) <music21.note.Note F>>)
(<PitchedTimespan (21.5 to 22.5) <music21.note.Note A>>,
 <PitchedTimespan (21.5 to 22.5) <music21.note.Note A>>)


Oblique here means a pair that does not move (it could be called noMotion,
because there's no motion
here in a two-note pair, but we still call it includeOblique so it's consistent with
getAllVoiceLeadingQuartets).

>>> for pm in verticality22.getPairedMotion(includeOblique=False):
...     print(pm)
(<PitchedTimespan (19.5 to 21.0) <music21.note.Note G>>,
 <PitchedTimespan (22.0 to 22.5) <music21.note.Note C>>)
(<PitchedTimespan (21.0 to 22.0) <music21.note.Note E>>,
 <PitchedTimespan (22.0 to 23.0) <music21.note.Note F>>)

>>> for pm in verticality22.getPairedMotion(includeOblique=False, includeRests=False):
...     print(pm)
(<PitchedTimespan (21.0 to 22.0) <music21.note.Note E>>,
 <PitchedTimespan (22.0 to 23.0) <music21.note.Note F>>)

Changed in v9.3 -- arguments are keyword only
FT)
r%   r)   r'   r&   r.   r   r   .findPreviousPitchedTimespanInSameStreamByClassrG   r   )r0   r   r   stopTssstartTss
overlapTssallPairedMotions
startingTs
previousTstsTuple	overlapTss              r   r   Verticality.getPairedMotionQ  s   n   I$$&&**
VX"Jj%*?*?@@**YYJ!J@U@U)V)Vu$,&:+=+=ASAS+S!.G##G, #  T!'	!)U-B-BCC$0 ''0	 (  r   )r(   r$   r&   r'   r)   r%   )g        r   r   r   N)r(   r   r&   !tuple[spans.ElementTimespan, ...]r'   r  r)   r  )r   zfloat | None)r   zOffsetQL | Noner7   )r   zOffsetQLIn | Noner   znote.Rest | chord.Chord)r   zt.Literal[False]r   list[tuple[int, int]] | Noner   zlist[PitchedTimespanQuartet])r   zt.Literal[True]r   r  r   zlist[VoiceLeadingQuartet])r   boolr   r  r   z8list[VoiceLeadingQuartet] | list[PitchedTimespanQuartet])r   r  r   r  r   z9list[tuple[spans.PitchedTimespan, spans.PitchedTimespan]])r   r   r   r   __doc__	__slots__r*   __annotations__r1   rD   propertyrO   rT   rZ   r]   rd   rh   r@   ru   rz   rH   r   r   r   r   r   r   r   r   r   r"   r"   5   s   K^I"aE!I~ EV >@<>;=TT <T :	T
 9T@0 ! !F 1 18& 4 4  & - -B  @ " "H )- )-V H H< 7 7& *.| #$"|&| 
|~  8<	 (	 6	 
&	 	  )-8<	 '	 6	 
#	 	 "8<  6 
BH "#	V  V  	V 
 
CV  V r   r"   c                  :    \ rS rSrSrS
S jrS rS rS rS r	Sr
g	)VerticalitySequencei  z
A segment of verticalities.
c                $    [        U5      U l        g r7   )r/   _verticalities)r0   verticalitiess     r   r1   VerticalitySequence.__init__  s    #M2r   c                     U R                   U   $ r7   r  )r0   items     r   __getitem__VerticalitySequence.__getitem__  s    ""4((r   c                ,    [        U R                  5      $ r7   )r   r  r^   s    r   __len__VerticalitySequence.__len__  s    4&&''r   c                B    SR                  S U  5       5      nSU S3nU$ )Nz,
	c              3  N   #    U  H  nS UR                  5       -   S-   v   M     g7f)()N)rD   r9   s     r   r<   4VerticalitySequence._reprInternal.<locals>.<genexpr>  s!     #P4aC!//*;$;c$A4s   #%z[
	z
	])rA   )r0   internalReprouts      r   rD   !VerticalitySequence._reprInternal  s)    ||#P4#PPl^5)
r   c                T   SSK Jn  0 nU S   R                   H>  nUR                  U;  a  / X#R                  '   X#R                     R	                  U5        M@     U S   R
                   H>  nUR                  U;  a  / X#R                  '   X#R                     R	                  U5        M@     U SS   HQ  nUR
                   H>  nUR                  U;  a  / X#R                  '   X#R                     R	                  U5        M@     MS     UR                  5        H  u  pVU" US9nXrU'   M     U$ )Nr   )Horizontalityr   )	timespans)music21.tree.analysisr-  r&   r   r   r'   items)r0   r-  	unwrappedrn   verticalityr   r.  horizontalitys           r   unwrapVerticalitySequence.unwrap  s   7	Q00H}}I-+-	--(mm$++H5 1 Q..H}}I-+-	--(mm$++H5 /  8K'66==	1/1Imm,--(//9 7 $
  )0OD)I>M+dO  1 r   r  N)r  zIterable[Verticality])r   r   r   r   r  r1   r  r"  rD   r4  r   r   r   r   r  r    s     3
)(r   r  c                      \ rS rSrSrg)Testi  r   Nr   r   r   r   r7  r7    r    r   r7  __main__)-r  
__future__r   collections.abcr   r   r   r   typingr   r   unittestr   r   r   r	   r
   r   r   r   music21.common.typesr   r   music21.treer   r   music21.tree.treesr   r   r   EnvironmentenvironLocalr/   r   PitchedTimespanQuartetTreeExceptionr   ProtoM21Objectr"   r  TestCaser7  
_DOC_ORDERr   mainTestr   r   r   <module>rH     s   # .              6 ??-8&&'9:	%

!6!6
67	%

!6!6
679 	<55 	r '(( r p#.'00(;2G .f	8 	 ./
 zT r   