
    rhC                       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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  SSSSSS.             SS jjrSSSSS.           SS jjrSS.       SS jjrSSS.     SS jjr " S S\R4                  5      r\S:X  a  SSKr\R:                  " \5        gg)zG
Tools for creating timespans (fast, manipulable objects) from Streams
    )annotations)SequenceN)Music21Object)
M21ObjType
StreamType)common)note)spans)timespanTree)treesstream         F)
classListscurrentParentageinitialOffsetflattenuseTimespansc                  SSK Jn  Uc  U 4nUS   nU(       a  [        R                  nO[        R
                  nU(       d  U" US9/n	OU V
s/ s H  o" US9PM
     n	n
U R                  SS U R                  -   nU GH  nUR                  U5      U-   nSnUR                  (       a}  [        R                  " SU5      nX,4-   n[        UUUUUUS9n[        U	U5       HA  u  nnUSLa  UR                  USS 5        M!  UR                  UR                  5       U5        MC     S	nU(       a  US
:X  d  M  UnX7R                   R"                  -   nXR                   R"                  -   n[        X5       H  u  nnU(       a"  UR$                  R'                  U5      (       a  M/  U(       a|  [)        U[*        R,                  UR.                  45      (       a  [0        R2                  nO[0        R4                  nU" U[7        [9        U5      5      UUUUS9nUR                  U5        M  UR                  X5        M     GM     U	$ s  sn
f )a>  
To be DEPRECATED in v8: this is no faster than calling streamToTimespanTree
multiple times with different classLists.

Recurses through `inputStream`, and constructs TimespanTrees for each
encountered substream and PitchedTimespan for each encountered non-stream
element.

`classLists` should be a sequence of elements contained in `classSet`. One
TimespanTree will be constructed for each element in `classLists`, in
a single optimized pass through the `inputStream`.

This is used internally by `streamToTimespanTree`.


>>> score = tree.makeExampleScore()

Get everything in the score

>>> treeList = tree.fromStream.listOfTreesByClass(score, useTimespans=True)
>>> treeList
[<TimespanTree {2} (-inf to inf) <music21.stream.Score ...>>]
>>> tl0 = treeList[0]
>>> for t in tl0:
...     print(t)
<TimespanTree {4} (-inf to inf) <music21.stream.Part ...>>
    <TimespanTree {0} (-inf to inf) <music21.stream.Measure 1 offset=0.0>>
    <TimespanTree {0} (-inf to inf) <music21.stream.Measure 2 offset=2.0>>
    <TimespanTree {0} (-inf to inf) <music21.stream.Measure 3 offset=4.0>>
    <TimespanTree {0} (-inf to inf) <music21.stream.Measure 4 offset=6.0>>
<TimespanTree {4} (-inf to inf) <music21.stream.Part ...>>
    <TimespanTree {0} (-inf to inf) <music21.stream.Measure 1 offset=0.0>>
    <TimespanTree {0} (-inf to inf) <music21.stream.Measure 2 offset=2.0>>
    <TimespanTree {0} (-inf to inf) <music21.stream.Measure 3 offset=4.0>>
    <TimespanTree {0} (-inf to inf) <music21.stream.Measure 4 offset=6.0>>

Now filter the Notes and the Clefs & TimeSignatures of the score
(flattened) into a list of two TimespanTrees

>>> classLists = ((note.Note,), (clef.Clef, meter.TimeSignature))
>>> treeList = tree.fromStream.listOfTreesByClass(score, useTimespans=True,
...                                               classLists=classLists, flatten=True)
>>> treeList
[<TimespanTree {12} (0.0 to 8.0) <music21.stream.Score ...>>,
 <TimespanTree {4} (0.0 to 0.0) <music21.stream.Score ...>>]

* Changed in v8: it is now a stickler that classLists must be sequences of sequences,
    such as tuples of tuples.
r   r   NsourceFzmusic21.stream.Stream)r   r   r   r   r   TsemiFlatelement	parentageparentOffsetparentEndTimeoffsetendTime)music21r   r   TimespanTreer   
OffsetTree	_elements_endElementselementOffsetisStreamtcastlistOfTreesByClasszipinsertlowestPositiondurationquarterLengthclassSet
isdisjoint
isinstancer	   NotRestStreamr
   PitchedTimespanElementTimespantuplereversed)inputStreamr   r   r   r   r   r   lastParentage	treeClassoutputTrees_inputStreamElementsr   r    	wasStreamlocalParentagecontainedTrees
outputTreesubTreer   r   r!   classBasedTree	classList	spanClasselementTimespans                             Q/home/james-whalen/.local/lib/python3.13/site-packages/music21/tree/fromStream.pyr+   r+   !   s'   v '>$R(M  --	$$	 67@JK
1y6
K%//2[5M5MM&,,W5E	ff4g>G-
:N/AO>D8?;E=IKN (+;'G#
G%'%%gaj1%%g&<&<&>H	 (H
 IGz1(L),B,B,P,PPM//===G-0-I)	!1!1!<!<Y!G!G!'DLL&--+HII$)$9$9	$)$9$9	&/:?IY@Z:[=I>K7=8?'AO #))/:"))&:# .J3 'X _ Ls   H>)r   rF   r   groupOffsetsc                 ^^^^^^  SUUUUUU4S jjmT(       a  [         R                  mO&TSL a  [        R                  mO[        R                  mU R
                  (       d!  U R                  (       a  U R                  5         U R
                  (       a,  TSL a'  U R                  (       d  TSL a  T" U S9n[        U UTS9$ T" U U 4SS9$ )a  
Converts a Stream and constructs an :class:`~music21.tree.trees.ElementTree` based on this.

Use Stream.asTree() generally since that caches the ElementTree.

>>> score = tree.makeExampleScore()
>>> elementTree = tree.fromStream.asTree(score)
>>> elementTree
<ElementTree {2} (0.0 <0.-20...> to 8.0) <music21.stream.Score exampleScore>>
>>> for x in elementTree.iterNodes():
...     x
<ElementNode: Start:0.0 <0.-20...> Indices:(l:0 *0* r:1) Payload:<music21.stream.Part ...>>
<ElementNode: Start:0.0 <0.-20...> Indices:(l:0 *1* r:2) Payload:<music21.stream.Part ...>>

>>> etFlat = tree.fromStream.asTree(score, flatten=True)
>>> etFlat
<ElementTree {20} (0.0 <0.-25...> to 8.0) <music21.stream.Score exampleScore>>

The elementTree's classSortOrder has changed to -25 to match the lowest positioned element
in the score, which is an Instrument object (classSortOrder=-25)

>>> for x in etFlat.iterNodes():
...     x
<ElementNode: Start:0.0 <0.-25...> Indices:(l:0 *0* r:2)
    Payload:<music21.instrument.Instrument 'PartA: : '>>
<ElementNode: Start:0.0 <0.-25...> Indices:(l:1 *1* r:2)
    Payload:<music21.instrument.Instrument 'PartB: : '>>
<ElementNode: Start:0.0 <0.0...> Indices:(l:0 *2* r:4) Payload:<music21.clef.BassClef>>
<ElementNode: Start:0.0 <0.0...> Indices:(l:3 *3* r:4) Payload:<music21.clef.BassClef>>
...
<ElementNode: Start:0.0 <0.20...> Indices:(l:5 *6* r:8) Payload:<music21.note.Note C>>
<ElementNode: Start:0.0 <0.20...> Indices:(l:7 *7* r:8) Payload:<music21.note.Note C#>>
<ElementNode: Start:1.0 <0.20...> Indices:(l:0 *8* r:20) Payload:<music21.note.Note D>>
...
<ElementNode: Start:7.0 <0.20...> Indices:(l:15 *17* r:20) Payload:<music21.note.Note C>>
<ElementNode: Start:End <0.-5...> Indices:(l:18 *18* r:20)
    Payload:<music21.bar.Barline type=final>>
<ElementNode: Start:End <0.-5...> Indices:(l:19 *19* r:20)
    Payload:<music21.bar.Barline type=final>>

>>> etFlat.getPositionAfter(0.5)
SortTuple(atEnd=0, offset=1.0, priority=0, classSortOrder=20, isNotGrace=1, insertIndex=...)

>>> etFlatNotes = tree.fromStream.asTree(score, flatten=True, classList=(note.Note,))
>>> etFlatNotes
<ElementTree {12} (0.0 <0.20...> to 8.0) <music21.stream.Score exampleScore>>

c           
       > US   nUc  T" US9nU R                   S S  U R                  -   nX$R                  R                  -   nU GH(  n[        R
                  " UR                  U5      U-   5      nUR                  (       a  TSLa  X4-   n	T" UU	UUS9  TS:w  a  MX  T(       a"  UR                  R                  T5      (       a  M  T(       aV  XR                  R                  -   n
[        R                  " U[        [        U5      5      UUUU
S9nUR                  U5        M  TSL a4  UR                  U5      nUR!                  US9nUR                  X5        GM  UR                  X5        GM+     U$ )Nr   r   F)r   r   inner_outputTreer   r   )r    )r%   r&   r/   r0   r   opFracr'   r(   r1   r2   r
   r6   r8   r9   r-   	sortTuplemodify)innerStreamr   r   rM   r;   innerStreamElementsr   r   
flatOffsetrA   r!   pitchedTimespanpositionflatPositionrF   r   rJ   recurseGetTreeByClassr<   r   s                 rI   rW   %asTree.<locals>.recurseGetTreeByClass   sr   
 ),#(> *33A69Q9QQ%(>(>(L(LL*G}'B'B7'Km'[\JG5$8!1J!>%g7E4>7GI j(W--88CC$'7'7'E'EE"'"7"7##H-=$>?!."/%##% !''8&",,];'jA ''> ''
<? +B      Fr   )rC   rF   r   )r   r   )N)
r   r#   r   ElementTreer$   isSortedautoSortsortisFlat#makeFastShallowTreeFromSortedStream)r:   r   rF   r   rJ   rC   rW   r<   s    ```` @@rI   asTreer`      s    x "	/  / h  --			%%	$$	 K$8$8 	%##w%'79B+9V
2;>H=FH 	H %[7Bn368 	8rY   )rF   c                  U R                   SS U R                  -   nUc#  U Vs/ s H  oDR                  U 5      U4PM     nnOEU Vs/ s H8  nUR                  R	                  U5      (       a  M%  UR                  U 5      U4PM:     nnUR                  U5        UR                  b  UR                  R                  5         U$ s  snf s  snf )a  
Use populateFromSortedList to quickly make a tree from a stream.

This only works if the stream is flat (or we are not flattening) and
sorts have already been run, and we are not making an OffsetTree.

Returns the same outputTree that was put in, only with elements in it.
N)r%   r&   rO   r1   r2   populateFromSortedListrootNodeupdateEndTimes)r:   rC   rF   r?   eelementTupleLists         rI   r_   r_   #  s     &//2[5M5MMCVWCVa[[5q9CVWCV ECVa#$::#8#8#C :Q[[5q9CV E%%&67&**, XEs   C$C/C)r   rF   c                   Uc	  [         //nOU/n[        U SUUSS9nUS   n[        R                  (       a!  [	        U[
        R                  5      (       d   eU$ )a  
Recurses through a score and constructs a
:class:`~music21.tree.trees.TimespanTree`.  Use Stream.asTimespans() generally
since that caches the TimespanTree.

>>> score = corpus.parse('bwv66.6')
>>> scoreTree = tree.fromStream.asTimespans(score, flatten=True,
...                                         classList=(note.Note, chord.Chord))
>>> scoreTree
<TimespanTree {165} (0.0 to 36.0) <music21.stream.Score ...>>
>>> for x in scoreTree[:5]:
...     x
...
<PitchedTimespan (0.0 to 0.5) <music21.note.Note C#>>
<PitchedTimespan (0.0 to 0.5) <music21.note.Note A>>
<PitchedTimespan (0.0 to 0.5) <music21.note.Note A>>
<PitchedTimespan (0.0 to 1.0) <music21.note.Note E>>
<PitchedTimespan (0.5 to 1.0) <music21.note.Note B>>

>>> scoreTree = tree.fromStream.asTimespans(score, flatten=False, classList=())

Each of these has 11 elements -- mainly the Measures

>>> for x in scoreTree:
...     x
...
<ElementTimespan (0.0 to 0.0) <music21.metadata.Metadata object at 0x...>>
<ElementTimespan (0.0 to 0.0) <music21.layout.StaffGroup ...>>
<TimespanTree {11} (0.0 to 36.0) <music21.stream.Part Soprano>>
<TimespanTree {11} (0.0 to 36.0) <music21.stream.Part Alto>>
<TimespanTree {11} (0.0 to 36.0) <music21.stream.Part Tenor>>
<TimespanTree {11} (0.0 to 36.0) <music21.stream.Part Bass>>

>>> tenorElements = scoreTree[4]
>>> tenorElements
<TimespanTree {11} (0.0 to 36.0) <music21.stream.Part Tenor>>

>>> tenorElements.source
<music21.stream.Part Tenor>

>>> tenorElements.source is score[3]
True
r   T)r   r   r   r   r   )r   r+   r)   TYPE_CHECKINGr3   r   r#   )r:   r   rF   r   listOfTimespanTreestimespanTreeFirsts         rI   asTimespansrk   >  sj    d $o&
[
,[;>5<8B:>	@
 ,A.+\-F-FGGGGrY   c                       \ rS rSrS rS rSrg)Testi  c                   SSK Jn  UR                  S5      R                  5       nUR	                  5       nSUl        0 Ul        UR	                  5       nU R                  [        U5      [        U5      5        U R                  [        U5      [        U5      5        [        X45       H  u  pVU R                  XV5        M     g)zM
tests that the isSorted speed up trick ends up producing identical results.
r   )corpuszbwv66.6FN)r"   ro   parser   r`   r[   _cacheassertEquallenr,   assertIs)selfro   sfsfTree
sfTreeSlowfastIslowIs          rI   testFastPopulateTest.testFastPopulate  s     	#\\)$,,. 	YY[
R#j/2R#f+.3LEMM%' 4rY   c                    SSK Jn  U" 5       nUR                  5         [        U5      nU R	                  UR
                  S5        g )Nr   )makeExampleScoreg       @)music21.treer~   r]   r`   rr   r!   )ru   r~   scscTrees       rI   testAutoSortExampleTest.testAutoSortExample  s3    1
	-rY   r   N)__name__
__module____qualname____firstlineno__r{   r   __static_attributes__r   rY   rI   rm   rm     s    (".rY   rm   __main__)r:   r   r   z$Sequence[Sequence[type[M21ObjType]]]r   z tuple[stream.Stream, ...] | Noner   floatr   z
bool | strr   boolreturnz2list[trees.OffsetTree | timespanTree.TimespanTree])r:   r   r   zt.Literal['semiFlat'] | boolrF   Sequence[type] | Noner   r   rJ   r   r   z@trees.OffsetTree | trees.ElementTree | timespanTree.TimespanTree)r:   zstream.StreamrC   $trees.OffsetTree | trees.ElementTreerF   r   r   r   )r   z
str | boolrF   z$Sequence[type[Music21Object]] | Noner   ztimespanTree.TimespanTree)__doc__
__future__r   collections.abcr   typingr)   unittestmusic21.baser   music21.common.typesr   r   r"   r   r	   r   r
   r   r   rh   r   r+   r`   r_   rk   TestCaserm   r   mainTestr   rY   rI   <module>r      s~   # $   & 7    % ?? 8:7;zz 5z 5	z
 z z z 6z@ +0%)C8C8 (C8 #	C8
 C8 C8 BC8R &*	 3 #	
 (< 48	> > 2	>
 >D.8 .< zT rY   