
    rhY              
         S r SSKJr  SSKJ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  \R                   (       a  SSKJr  \R$                  " S5      r " S S\	R(                  5      r\
R,                  S   \
R,                  S   \
R,                  S   \
R,                  S   \
R,                  S   \
R,                  S   \
R,                  S   \
R,                  S   \
R,                  S   4	r " S S\R0                  \\R2                  5      r " S S\R0                  \5      r " S S\R8                  5      r\\/r\S:X  a  SSKr\R@                  " \5        gg)a  
The module defines Beam and Beams (note plural) objects.

The Beams object holds multiple Beam objects (e.g., a 32nd note might have
three Beam objects in its Beam object).

The Beams object is stored in :class:`~music21.note.Note` and
:class:`~music21.chord.Chord` objects as their :attr:`~music21.note.Note.beams`
attributes.  Beams objects can largely be treated as a list.

See `meter.TimeSignature`. :meth:`~music21.meter.TimeSignature.getBeams` for a
way of getting beam information for a measure given the meter.  The
`meter.TimeSignature`. :attr:`~music21.meter.TimeSignature.beamSequence`
attribute holds information about how to beam given the TimeSignature

Run `Stream`. :meth:`~music21.stream.Stream.makeBeams` to set beaming
information automatically given the current meter.

Suppose you had a measure of two eighths and a quarter and wanted to explicitly
beam the two eighth notes.  You could do this:

>>> m = stream.Measure()
>>> n1 = note.Note('C4', quarterLength=0.5)
>>> n2 = note.Note('D4', quarterLength=0.5)
>>> n3 = note.Note('E4', quarterLength=1.0)
>>> m.append(n1)
>>> m.append(n2)
>>> m.append(n3)
>>> n1.beams.fill('eighth', type='start')
>>> n2.beams.fill('eighth', type='stop')
>>> n1.beams
<music21.beam.Beams <music21.beam.Beam 1/start>>

>>> n2.beams
<music21.beam.Beams <music21.beam.Beam 1/stop>>

But suppose you wanted something harder: two 16ths, an 8th, a quarter, with the
first 3 notes beamed?  The first note and 3rd are easy to do, using the method
above:

>>> m = stream.Measure()
>>> n1 = note.Note('C4', quarterLength=0.25)
>>> n2 = note.Note('D4', quarterLength=0.25)
>>> n3 = note.Note('E4', quarterLength=0.5)
>>> n4 = note.Note('F4', quarterLength=1.0)
>>> for n in [n1, n2, n3, n4]:
...     m.append(n)
>>> n1.beams.fill('16th', type='start')
>>> n3.beams.fill('eighth', type='stop')

but the second note has an 8th beam that continues and a 16th beam that stops.
So you will need to set them separately:

>>> n2.beams.append('continue')
>>> n2.beams.append('stop')
>>> n2.beams
<music21.beam.Beams <music21.beam.Beam 1/continue>/<music21.beam.Beam 2/stop>>

To get rid of beams on a note do:

>>> n2.beams.beamsList = []
    )annotations)IterableN)exceptions21)duration)environment)prebase)style)EqualSlottedObjectMixin)basebeamc                      \ rS rSrSrg)BeamException_    N)__name__
__module____qualname____firstlineno____static_attributes__r       F/home/james-whalen/.local/lib/python3.13/site-packages/music21/beam.pyr   r   _   s    r   r             @                  c                  :   ^  \ rS rSrSrSrSU 4S jjrS rSrU =r	$ )Beaml   a  
A Beam is an object representation of one single beam, that is, one
horizontal line connecting two notes together (or less commonly a note to a
rest).  Thus, it takes two separate Beam objects to represent the beaming of
a 16th note.

The Beams object (note the plural) is the object that handles groups of
Beam objects; it is defined later on.

Here are two ways to define the start of a beam

>>> b1 = beam.Beam(type='start')
>>> b2 = beam.Beam('start')

Here is a partial beam (that is, one that does not connect to any other
note, such as the second beam of a dotted eighth, sixteenth group)

Two ways of doing the same thing

>>> b3 = beam.Beam(number=1, type='partial', direction='left')
>>> b3
<music21.beam.Beam 1/partial/left>

>>> b4 = beam.Beam('partial', 'left')
>>> b4.number = 1
>>> b4
<music21.beam.Beam 1/partial/left>

All attributes must be the same for equality:

>>> b3 == b4
True

>>> b2
<music21.beam.Beam None/start>
>>> b2 == b3
False
)	directionidindependentAnglenumbertypec                t   > [         TU ]  5         Xl        X l        S U l        X0l        [        U 5      U l        g N)super__init__r(   r$   r&   r'   r%   )selfr(   r$   r'   	__class__s       r   r,   Beam.__init__   s4    	" $  T(r   c                z    U R                    SU R                   3nU R                  b  USU R                   3-  nU$ N/)r'   r(   r$   )r-   outs     r   _reprInternalBeam._reprInternal   s?    Qtyyk*>>%Qt~~&''C
r   )NNN)
r   r   r   r   __doc__	__slots__r,   r4   r   __classcell__)r.   s   @r   r"   r"   l   s    %RI
 r   r"   c                      \ rS rSr% SrSrSS0rS\S'   S rS	 r	S
 r
S rS rS r\SS j5       r\SS j5       r\S 5       r\SS j5       rSS jrSS jrS rS rS rS rSS jrSS jrSrg) Beams   a  
The Beams object stores in it attribute beamsList (a list) all the Beam
objects defined above.  Thus, len(beam.Beams) tells you how many beams the
note currently has on it, and iterating over a Beams object gives you each
Beam.

>>> n = note.Note(type='16th')
>>> isinstance(n.beams, beam.Beams)
True

>>> n.beams.fill(2, 'start')
>>> len(n.beams)
2

>>> for thisBeam in n.beams:
...     thisBeam.type
'start'
'start'

>>> print(n.beams)
<music21.beam.Beams <music21.beam.Beam 1/start>/<music21.beam.Beam 2/start>>
	beamsList	featheredr%   r>   zg
            Boolean determining if this is a feathered beam or not
            (does nothing for now).zdict[str, str]	_DOC_ATTRc                @    / U l         SU l        [        U 5      U l        g )NFr<   r-   s    r   r,   Beams.__init__   s     T(r   c                ,    [        U R                  5      $ r*   )iterr=   rA   s    r   __iter__Beams.__iter__   s    DNN##r   c                ,    [        U R                  5      $ r*   )lenr=   rA   s    r   __len__Beams.__len__   s    4>>""r   c                h    [        XR                  5      =(       a    [        U 5      [        U5      :H  $ r*   )
isinstancer.   repr)r-   others     r   __eq__Beams.__eq__   s#    %0NT$Z4;5NNr   c                    [        U 5      S-	  $ )N   )r%   rA   s    r   __hash__Beams.__hash__   s    $x1}r   c                    / nU R                    H  nUR                  [        U5      5        M     SR                  U5      $ r1   )r=   appendstrjoin)r-   msgr   s      r   r4   Beams._reprInternal   s3    NNDJJs4y! #xx}r   c                D   / nU  H  nUR                   R                  [        ;  a  UR                  S5        M4  SUR                  ;  a  UR                  S5        MW  [        5       nUR                  UR                   R                  5        UR                  U5        M     U$ )a  
Given a list or iterator of elements, return a list of None or Beams for
each element: None if the element is a quarter or larger or
if the element is a Rest, and the fullest possible set of beams
for the duration if it is a beamable.  Each beam object has type of None

staticmethod, does not need instance:

>>> durList = [0, -1, -2, -3]
>>> srcList = [note.Note(quarterLength=2 ** x) for x in durList]
>>> srcList.append(note.Rest(type='32nd'))
>>> beam.Beams.naiveBeams(srcList)
[None,
 <music21.beam.Beams <music21.beam.Beam 1/None>>,
 <music21.beam.Beams <music21.beam.Beam 1/None>/<music21.beam.Beam 2/None>>,
 <music21.beam.Beams <music21.beam.Beam 1/None>/<music21.beam.Beam
             2/None>/<music21.beam.Beam 3/None>>,
 None]
NNotRest)r   r(   beamableDurationTypesrV   classSetr:   fill)srcListr=   elbs       r   
naiveBeamsBeams.naiveBeams   s    , ')	B {{'<<  &"++-  & G r{{''(  #  r   c                    Sn[        [        U 5      5       H-  nU[        U 5      S-
  :w  a  XS-      nOSnUc  Uc  SX'   X   nM/     U $ )a  
Go through the naiveBeamsList and remove beams from objects surrounded
by None objects -- you can't beam to nothing!

Modifies beamsList in place

>>> N = note.Note
>>> R = note.Rest
>>> e = 'eighth'
>>> nList = [N(type=e), R(type=e), N(type=e), N(type=e),
...          R(type=e), N(type=e), R(type=e), N(type=e)]
>>> beamsList = beam.Beams.naiveBeams(nList)
>>> beamsList
[<music21.beam.Beams <music21.beam.Beam 1/None>>,
 None,
 <music21.beam.Beams <music21.beam.Beam 1/None>>,
 <music21.beam.Beams <music21.beam.Beam 1/None>>,
 None,
 <music21.beam.Beams <music21.beam.Beam 1/None>>,
 None,
 <music21.beam.Beams <music21.beam.Beam 1/None>>]

>>> beamsList2 = beam.Beams.removeSandwichedUnbeamables(beamsList)
>>> beamsList2 is beamsList
True
>>> beamsList2
[None,
 None,
 <music21.beam.Beams <music21.beam.Beam 1/None>>,
 <music21.beam.Beams <music21.beam.Beam 1/None>>,
 None,
 None,
 None,
 None]
N   )rangerH   )r=   beamLastibeamNexts       r   removeSandwichedUnbeamables!Beams.removeSandwichedUnbeamables$  s`    L s9~&AC	NQ&&$U+H$4#	 |H ' r   c           
     B   [        [        U SS U SS 5      5       GH1  u  nu  p#U(       a  U(       d  M  UR                  5       nU(       d  M2  U H  nUR                  U5      nUR                  S:w  d  UR
                  S:w  a  M6  XSR                  5       ;  a  MK  UR                  U5      nUR                  S:X  a  UR
                  S:X  a  M~  UR                  S;   a'  [        R                  SR                  X#X5      5        M  SUl        SUl        UR                  S:X  a  S	Ul        OUR                  S:X  a  S
Ul        SUl        M     GM4     [        U SS U SS 5       H  u  p(U(       a  U(       d  M  UR                  5       nU(       d  M.  U H  nUR                  U5      nUR                  S:w  d  UR
                  S:w  a  M6  XXR                  5       ;  a  MK  UR                  U5      n	U	R                  S	:w  a  Mn  S	Ul        SUl        S
U	l        M     M     U $ )z
Partial-right followed by partial-left must also be connected, even if otherwise
over a archetypeSpan, such as 16th notes 2 and 3 in a quarter note span where
16ths are not beamed by default.
Nrf   partialright)continuestopz6Found a messed up beam pair {}, {}, at index {} of 
{}startrr   rq   left)		enumeratezip
getNumbersgetByNumberr(   r$   environLocalwarnformat)
r=   ri   bThisbNextbThisNumthisNumthisBeamnextBeambPrevprevBeams
             r   mergeConnectingPartialBeams!Beams.mergeConnectingPartialBeamsV  s    "+3y"~y}+M!NA~'')H# ,,W5==I-1C1Cw1N"2"2"44 ,,W5==I-(2D2D2O==$88 %%QXX!!89  '%)"==I-$*HM]]g-$.HM%)"1 $ "OF  	!"y"~>LE'')H# ,,W5==I-1C1Cv1M"2"2"44 ,,W5==F* &%)" * $ ?0 r   c                   [        U 5       H  u  pUc  M
  UR                  5       nSU;  a  SU;  a  SU;  a  SX'   M2  SnSnUR                   H  nUR                  S:X  a  SnM  UR                  S:X  a  SnM+  U(       a)  UR                  S:X  a  UR                  S:X  a	  S	Ul        M[  U(       d  Md  UR                  S:X  d  Mv  UR                  S	:X  d  M  SUl        M     M     U $ )
a  
It is possible at a late stage to have beams that only consist of partials
or beams with a 'start' followed by 'partial/left' or possibly 'stop' followed
by 'partial/right'; beams entirely consisting of partials are removed
and the direction of irrational partials is fixed.
Nrs   rr   rq   FTro   rt   rp   )ru   getTypesr=   r(   r$   )r=   ri   beamsObjallTypeshasStarthasStoprb   s          r   sanitizePartialBeamsBeams.sanitizePartialBeams  s     %Y/KA((*Hh&6+AjX`F`#	 HG''66W$#H66V#"G) 3v8M")AKW9!49O"(AK ( 04 r   Nc                    [        U[        5      (       a)  [        X5      n[        U R                  5      S-   Ul        OUnU R                  R                  U5        g)a  
Append a new Beam object to this Beams object, automatically creating the Beam
object and incrementing the number count.

>>> beams = beam.Beams()
>>> beams.append('start')
>>> beams.beamsList
[<music21.beam.Beam 1/start>]

>>> beams.append('partial', 'right')
>>> beams.beamsList
[<music21.beam.Beam 1/start>, <music21.beam.Beam 2/partial/right>]


A beam object can also be specified:

>>> beams = beam.Beams()
>>> beam1 = beam.Beam(type='start', number=1)
>>> beams.append(beam1)
>>> beams.beamsList
[<music21.beam.Beam 1/start>]
rf   N)rL   rW   r"   rH   r=   r'   rV   )r-   r(   r$   objs       r   rV   Beams.append  sG    . dC  t'CT^^,q0CJCc"r   c                   / U l         USS[        R                  S   4;   a  SnOUS[        R                  S   4;   a  SnOUS[        R                  S   4;   a  SnOUS[        R                  S	   4;   a  SnOUS
[        R                  S   4;   a  S
nO~US[        R                  S   4;   a  SnObUS[        R                  S   4;   a  SnOFUS[        R                  S   4;   a  SnO*US[        R                  S   4;   a  SnO[        SU 35      e[	        SUS-   5       H.  n[        5       nXEl        U R                   R                  U5        M0     Ub  U R                  U5        gg)a  
A quick way of setting the beams list for a particular duration, for
instance, `fill('16th')` will clear the current list of beams in the
Beams object and add two beams.  `fill(2)` will do the same (though note
that that is an int, not a string).

It does not do anything to the direction that the beams are going in,
or by default.  Either set type here or call `setAll()` on the Beams
object afterwards.

Both "eighth" and "8th" work.  Adding more than nine beams (i.e. things
like 4096th notes) raises an error.

>>> a = beam.Beams()
>>> a.fill('16th')
>>> len(a)
2

>>> a.fill('32nd', type='start')
>>> len(a)
3

>>> a.beamsList[2]
<music21.beam.Beam 3/start>

>>> a.beamsList[2].type
'start'

Filling a smaller number wipes larger numbers of beams:

>>> a.fill('eighth', type='start')
>>> len(a)
1

OMIT_FROM_DOCS

>>> a.fill(4)
>>> len(a)
4

>>> a.fill('128th')
>>> len(a)
5

>>> a.fill('256th')
>>> len(a)
6

>>> a.fill(12)
Traceback (most recent call last):
music21.beam.BeamException: cannot fill beams for level 12
rf   8thr      r      r   rR   r      r      r      r   r   	   r    zcannot fill beams for level N)	r=   r   typeFromNumDictr   rg   r"   r'   rV   setAll)r-   levelr(   countri   r   s         r   r_   
Beams.fill  sr   j Qx77:;;Eq(222677Eq(222677Eq(222677Eq(223788Eq(223788Eq(223788Eq(224899Eq(224899E">ug FGGq%!)$A&CJNN!!#& % KK r   c                    XR                  5       ;  a  [        SU S35      eU R                   H  nUR                  U:X  d  M  Us  $    g)z
Gets an internal beam object by number.

>>> a = beam.Beams()
>>> a.fill('16th')
>>> a.setAll('start')
>>> a.getByNumber(2).type
'start'

>>> a.getByNumber(30)
Traceback (most recent call last):
IndexError: beam number 30 cannot be accessed
beam number  cannot be accessedN)rw   
IndexErrorr=   r'   )r-   r'   r   s      r   rx   Beams.getByNumber4  sE     **|F83FGHHNND{{f$ #r   c                X    U R                    Vs/ s H  oR                  PM     sn$ s  snf )z
Returns a list of all defined beam numbers; it should normally be a set
of consecutive integers, but it might not be.

>>> a = beam.Beams()
>>> a.fill('32nd')
>>> a.getNumbers()
[1, 2, 3]
)r=   r'   r-   xs     r   rw   Beams.getNumbersH  s"     #'..1.Q.111   'c                    U R                  U5      nUR                  c  UR                  $ UR                   SUR                   3$ )z
Get beam type, with direction, by number

>>> a = beam.Beams()
>>> a.fill('16th')
>>> a.setAll('start')
>>> a.setByNumber(2, 'partial-right')
>>> a.getTypeByNumber(2)
'partial-right'

>>> a.getTypeByNumber(1)
'start'
-)rx   r$   r(   )r-   r'   beamObjs      r   getTypeByNumberBeams.getTypeByNumberT  sF     ""6*$<<ll^1W%6%6$788r   c                X    U R                    Vs/ s H  oR                  PM     sn$ s  snf )z
Returns a list of all beam types defined for the current beams

>>> a = beam.Beams()
>>> a.fill('16th')
>>> a.setAll('start')
>>> a.getTypes()
['start', 'start']
)r=   r(   r   s     r   r   Beams.getTypesh  s"     !%/1///r   c                j    US;  a  [        SU 35      eU R                   H  nXl        X#l        M     g)a1  
`setAll` is a method of convenience that sets the type
of each of the beam objects within the beamsList to the specified type.
It also takes an optional "direction" attribute that sets the direction
for each beam (otherwise the direction of each beam is set to None)
Acceptable directions (start, stop, continue, etc.) are listed under
Beam() above.

>>> a = beam.Beams()
>>> a.fill('16th')
>>> a.setAll('start')
>>> a.getTypes()
['start', 'start']

>>> a.setAll('sexy')
Traceback (most recent call last):
music21.beam.BeamException: beam type cannot be sexy

rs   rr   rq   ro   beam type cannot be N)r   r=   r(   r$   )r-   r(   r$   r   s       r   r   Beams.setAllt  s8    ( ??"6tf =>>NNDI&N #r   c                   SU;   a  UR                  S5      u  p#US;  a  [        SU 35      eXR                  5       ;  a  [        SU S35      eU R                   H!  nUR
                  U:X  d  M  X$l        X4l        M#     g)aZ  
Set an internal beam object by number, or rhythmic symbol level.

>>> a = beam.Beams()
>>> a.fill('16th')
>>> a.setAll('start')
>>> a.setByNumber(1, 'continue')
>>> a.beamsList[0].type
'continue'

>>> a.setByNumber(2, 'stop')
>>> a.beamsList[1].type
'stop'

>>> a.setByNumber(2, 'partial-right')
>>> a.beamsList[1].type
'partial'

>>> a.beamsList[1].direction
'right'

>>> a.setByNumber(30, 'stop')
Traceback (most recent call last):
IndexError: beam number 30 cannot be accessed

>>> a.setByNumber(2, 'crazy')
Traceback (most recent call last):
music21.beam.BeamException: beam type cannot be crazy

r   r   r   r   r   N)splitr   rw   r   r=   r'   r(   r$   )r-   r'   r(   r$   r   s        r   setByNumberBeams.setByNumber  s}    @ $;"jjoOD??"6tf =>>**|F83FGHHNND{{f$ 	!* #r   )r`   zIterable[base.Music21Object])r=   list[Beams | None])r=   r   returnr   )NNr*   )r   r   r   r   r6   r7   r?   __annotations__r,   rE   rI   rO   rS   r4   staticmethodrc   rk   r   r   rV   r_   rx   rw   r   r   r   r   r   r   r   r   r:   r:      s    2I 	 '!I~ $#O % %N / /b B BH ! !L#>Qf(
29(
0'4)+r   r:   c                      \ 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   r   N)r   r   r   r   r   r   r   r   r   r   r     s    %r   r   __main__)!r6   
__future__r   collections.abcr   typingtunittestmusic21r   r   r   r   r	   music21.common.objectsr
   TYPE_CHECKINGr   Environmentry   Music21Exceptionr   r   r]   ProtoM21Object
StyleMixinr"   r:   TestCaser   
_DOC_ORDERr   mainTestr   r   r   <module>r      sT  =| # $         : ?? &&v.	L11 	
 QR (":":2">R (":":3"?S!8#;#;C#@T"H$<$<T$B F7!!#:E<L<L FTA+G""$; A+N%8 % T]
 zT r   